--- /dev/null
+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."
+++ /dev/null
-#
-# 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 = configd
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Aggregate
-
-TOOLS = configd.tproj scselect.tproj scutil.tproj
-
-FRAMEWORK_SUBPROJECTS = SystemConfiguration.fproj
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
- preferences.xml
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = aggregate.make
-LIBS =
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-
-
-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 $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
+++ /dev/null
-###############################################################################
-# Makefile.postamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile, which is imported after all other makefiles, to
-# override attributes for a project's Makefile environment. This allows you
-# to take advantage of the environment set up by the other Makefiles.
-# You can also define custom rules at the end of this file.
-#
-###############################################################################
-#
-# These variables are exported by the standard makefiles and can be
-# used in any customizations you make. They are *outputs* of
-# the Makefiles and should be used, not set.
-#
-# PRODUCTS: products to install. All of these products will be placed in
-# the directory $(DSTROOT)$(INSTALLDIR)
-# GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-# OFILE_DIR: Directory into which .o object files are generated.
-# DERIVED_SRC_DIR: Directory used for all other derived files
-#
-# ALL_CFLAGS: flags to pass when compiling .c files
-# ALL_MFLAGS: flags to pass when compiling .m files
-# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files
-# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files
-# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files
-# ALL_LDFLAGS: flags to pass when linking object files
-# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files
-# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files
-# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files
-# ALL_YFLAGS: flags to pass when processing .y (yacc) files
-# ALL_LFLAGS: flags to pass when processing .l (lex) files
-#
-# NAME: name of application, bundle, subproject, palette, etc.
-# LANGUAGES: langages in which the project is written (default "English")
-# English_RESOURCES: localized resources (e.g. nib's, images) of project
-# GLOBAL_RESOURCES: non-localized resources of project
-#
-# SRCROOT: base directory in which to place the new source files
-# SRCPATH: relative path from SRCROOT to present subdirectory
-#
-# INSTALLDIR: Directory the product will be installed into by 'install' target
-# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-#
-# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost)
-# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults
-# to -g)
-# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG)
-# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults
-# to -O)
-# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults
-# to -pg -DPROFILE)
-# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to
-# the include path (defaults to -I.)
-# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-# passed to ld/libtool (defaults to nothing)
-
-
-# Library and Framework projects only:
-# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked
-# against the framework will run against the correct version even if
-# the current version of the framework changes. You may override this
-# to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-# development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
- # User/group ownership
-#INSTALL_AS_GROUP = wheel
- # (probably want to set both of these)
-#INSTALL_PERMISSIONS =
- # If set, 'install' chmod's executable to this
-
-
-# Options to strip. Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here. Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where
-# derived files should go.
-#
-PREFS_DIR = /Library/Preferences/SystemConfiguration
-install_extra:
- $(MKDIRS) $(DSTROOT)$(PREFS_DIR)
- $(CHMOD) 755 $(DSTROOT)$(PREFS_DIR)
- install -c -m 644 preferences.xml $(DSTROOT)$(PREFS_DIR)/preferences.plist
+++ /dev/null
-###############################################################################
-# Makefile.preamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile for configuring the standard application makefiles
-# associated with ProjectBuilder. It is included before the main makefile.
-# In Makefile.preamble you set attributes for a project, so they are available
-# to the project's makefiles. In contrast, you typically write additional rules or
-# override built-in behavior in the Makefile.postamble.
-#
-# Each directory in a project tree (main project plus subprojects) should
-# have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-# MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults: The OTHER_* variables will be
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible. To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler
-# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-# .cc, .cxx, .C, and .M files. There is no need to respecify the
-# flags in OTHER_MFLAGS, etc.
-# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files
-# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files
-# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files
-# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when
-# precompiling header files
-# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool
-# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap
-# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen
-# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc
-# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every
-# stage of the make:
-#
-# BEFORE_PREBUILD: targets to build before installing headers for a subproject
-# AFTER_PREBUILD: targets to build after installing headers for a subproject
-# BEFORE_BUILD_RECURSION: targets to make before building subprojects
-# BEFORE_BUILD: targets to make before a build, but after subprojects
-# AFTER_BUILD: targets to make after a build
-#
-# BEFORE_INSTALL: targets to build before installing the product
-# AFTER_INSTALL: targets to build after installing the product
-# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-# AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-# BEFORE_INSTALLHDRS: targets to build before installing headers for a
-# subproject
-# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-# BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-# AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-# BEFORE_DEPEND: targets to build before building dependencies for a
-# subproject
-# AFTER_DEPEND: targets to build after building dependencies for a
-# subproject
-#
-# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-# updated every time the project is built. If NO, the dependency
-# file is only built when the depend target is invoked.
-
-# Framework-related variables:
-# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the framework's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-# PUBLIC_HEADER_DIR: Determines where public exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically. For library projects you should
-# set this to something like /Developer/Headers/$(NAME). Do not set
-# this variable for framework projects unless you do not want the
-# header files included in the framework.
-# PRIVATE_HEADER_DIR: Determines where private exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically.
-# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines
-# whether the libraries produced are statically linked when they
-# are used or if they are dynamically loadable. This defaults to
-# DYNAMIC.
-# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the library's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-#
-# INSTALL_AS_USER: owner of the intalled products (default root)
-# INSTALL_AS_GROUP: group of the installed products (default wheel)
-# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-# passed on the command line to recursive invocations of make. Note that
-# the values in OTHER_*FLAGS are inherited by subprojects automatically --
-# you do not have to (and shouldn't) add OTHER_*FLAGS to
-# OTHER_RECURSIVE_VARIABLES.
-
-# Additional headers to export beyond those in the PB.project:
-# OTHER_PUBLIC_HEADERS
-# OTHER_PROJECT_HEADERS
-# OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-# OTHER_RESOURCES: (non-localized) resources for this project
-# OTHER_OFILES: relocatables to be linked into this project
-# OTHER_LIBS: more libraries to link against
-# OTHER_PRODUCT_DEPENDS: other dependencies of this project
-# OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-# OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-# BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed. By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object). Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
-AFTER_INSTALL = install_extra
+++ /dev/null
-{
- "DYNAMIC_CODE_GEN" = YES;
- FILESTABLE = {
- "H_FILES" = ();
- "OTHER_SOURCES" = ("Makefile.preamble", Makefile, "Makefile.postamble", "preferences.xml");
- "PRECOMPILED_HEADERS" = ();
- "PROJECT_HEADERS" = ();
- "PUBLIC_HEADERS" = ();
- SUBPROJECTS = (
- "SystemConfiguration.fproj",
- "configd.tproj",
- "scselect.tproj",
- "scutil.tproj"
- );
- };
- LANGUAGE = English;
- MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
- "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake";
- "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac";
- "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc";
- "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make";
- "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac";
- "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = configd;
- PROJECTTYPE = Aggregate;
- PROJECTVERSION = "2.8";
- "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make";
- "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe";
- "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc";
-}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>ATconfig</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.ATconfig</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+ <string>com.apple.SystemConfiguration.KernelEventMonitor</string>
+ <string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+ </array>
+</dict>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * March 15, 2003 Allan Nathanson <ajn@apple.com>
+ * - startup/shutdown AT networking without Kicker's help and
+ * publish the state information after the configuration is
+ * active.
+ *
+ * April 29, 2002 Allan Nathanson <ajn@apple.com>
+ * - add global state information (primary service, interface)
+ *
+ * June 24, 2001 Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * July 7, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <netat/appletalk.h>
+#include <netat/at_var.h>
+#include <AppleTalk/at_paths.h>
+#include <AppleTalk/at_proto.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCDPlugin.h>
+#include <SystemConfiguration/SCValidation.h>
+
+#include "cache.h"
+#include "cfManager.h"
+
+#define HOSTCONFIG "/etc/hostconfig"
+
+static SCDynamicStoreRef store = NULL;
+static CFRunLoopSourceRef storeRls = NULL;
+
+static int curState = 0; // abs(state) == sequence #, < 0 == stop, > 0 == start
+static CFMutableDictionaryRef curGlobals = NULL;
+static CFMutableArrayRef curConfigFile = NULL;
+static CFMutableDictionaryRef curDefaults = NULL;
+static CFMutableDictionaryRef curStartup = NULL;
+
+static Boolean _verbose = FALSE;
+
+
+static void stopAppleTalk (CFRunLoopTimerRef timer, void *info);
+static void startAppleTalk(CFRunLoopTimerRef timer, void *info);
+
+
+static void
+updateDefaults(const void *key, const void *val, void *context)
+{
+ CFStringRef ifName = (CFStringRef)key;
+ CFDictionaryRef oldDict;
+ CFDictionaryRef newDict = (CFDictionaryRef)val;
+ CFNumberRef defaultNode;
+ CFNumberRef defaultNetwork;
+ CFStringRef defaultZone;
+
+ if (!CFDictionaryGetValueIfPresent(curDefaults, ifName, (const void **)&oldDict) ||
+ !CFEqual(oldDict, newDict)) {
+ char ifr_name[IFNAMSIZ+1];
+
+ bzero(&ifr_name, sizeof(ifr_name));
+ if (!_SC_cfstring_to_cstring(ifName, ifr_name, sizeof(ifr_name), kCFStringEncodingASCII)) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not convert interface name to C string"));
+ return;
+ }
+
+ /*
+ * Set preferred Network and Node ID
+ */
+ if (CFDictionaryGetValueIfPresent(newDict,
+ kSCPropNetAppleTalkNetworkID,
+ (const void **)&defaultNetwork) &&
+ CFDictionaryGetValueIfPresent(newDict,
+ kSCPropNetAppleTalkNodeID,
+ (const void **)&defaultNode)
+ ) {
+ struct at_addr init_address;
+ int status;
+
+ /*
+ * set the default node and network
+ */
+ CFNumberGetValue(defaultNetwork, kCFNumberShortType, &init_address.s_net);
+ CFNumberGetValue(defaultNode, kCFNumberCharType, &init_address.s_node);
+ status = at_setdefaultaddr(ifr_name, &init_address);
+ if (status == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("at_setdefaultaddr() failed"));
+ return;
+ }
+ }
+
+ /*
+ * Set default zone
+ */
+ if (CFDictionaryGetValueIfPresent(newDict,
+ kSCPropNetAppleTalkDefaultZone,
+ (const void **)&defaultZone)
+ ) {
+ int status;
+ at_nvestr_t zone;
+
+ /*
+ * set the "default zone" for this interface
+ */
+ bzero(&zone, sizeof(zone));
+ if (!_SC_cfstring_to_cstring(defaultZone, zone.str, sizeof(zone.str), kCFStringEncodingASCII)) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not convert default zone to C string"));
+ return;
+ }
+
+ zone.len = strlen(zone.str);
+ status = at_setdefaultzone(ifr_name, &zone);
+ if (status == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("at_setdefaultzone() failed"));
+ return;
+ }
+ }
+ }
+
+ return;
+}
+
+
+static void
+addZoneToPorts(const void *key, const void *val, void *context)
+{
+ CFStringRef zone = (CFStringRef)key;
+ CFArrayRef ifArray = (CFArrayRef)val;
+ CFMutableArrayRef zones = (CFMutableArrayRef)context;
+ CFStringRef ifList;
+ CFStringRef configInfo;
+
+ ifList = CFStringCreateByCombiningStrings(NULL, ifArray, CFSTR(":"));
+ configInfo = CFStringCreateWithFormat(NULL, NULL, CFSTR(":%@:%@"), zone, ifList);
+ CFArrayAppendValue(zones, configInfo);
+ CFRelease(configInfo);
+ CFRelease(ifList);
+ return;
+}
+
+
+/*
+ * Function: parse_component
+ * Purpose:
+ * Given a string 'key' and a string prefix 'prefix',
+ * return the next component in the slash '/' separated
+ * key.
+ *
+ * Examples:
+ * 1. key = "a/b/c" prefix = "a/"
+ * returns "b"
+ * 2. key = "a/b/c" prefix = "a/b/"
+ * returns "c"
+ */
+static CFStringRef
+parse_component(CFStringRef key, CFStringRef prefix)
+{
+ CFMutableStringRef comp;
+ CFRange range;
+
+ if (CFStringHasPrefix(key, prefix) == FALSE) {
+ return NULL;
+ }
+ comp = CFStringCreateMutableCopy(NULL, 0, key);
+ CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
+ range = CFStringFind(comp, CFSTR("/"), 0);
+ if (range.location == kCFNotFound) {
+ return comp;
+ }
+ range.length = CFStringGetLength(comp) - range.location;
+ CFStringDelete(comp, range);
+ return comp;
+}
+
+
+static CFDictionaryRef
+entity_one(SCDynamicStoreRef store, CFStringRef key)
+{
+ CFDictionaryRef ent_dict = NULL;
+ CFDictionaryRef if_dict = NULL;
+ CFStringRef if_key = NULL;
+ CFStringRef if_port;
+ CFMutableDictionaryRef new_dict = NULL;
+ static CFStringRef pre = NULL;
+ CFStringRef serviceID = NULL;
+ CFStringRef serviceType;
+
+ if (!pre) {
+ pre = SCDynamicStoreKeyCreate(NULL,
+ CFSTR("%@/%@/%@/"),
+ kSCDynamicStoreDomainSetup,
+ kSCCompNetwork,
+ kSCCompService);
+ }
+
+ /*
+ * get entity dictionary for service
+ */
+ ent_dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (!isA_CFDictionary(ent_dict)) {
+ goto done;
+ }
+
+ /*
+ * get interface dictionary for service
+ */
+ serviceID = parse_component(key, pre);
+ if (!serviceID) {
+ goto done;
+ }
+
+ if_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ serviceID,
+ kSCEntNetInterface);
+ if_dict = cache_SCDynamicStoreCopyValue(store, if_key);
+ CFRelease(if_key);
+ if (!isA_CFDictionary(if_dict)) {
+ goto done;
+ }
+
+ /* check the interface type */
+ serviceType = CFDictionaryGetValue(if_dict,
+ kSCPropNetInterfaceType);
+ if (!isA_CFString(serviceType) ||
+ !CFEqual(serviceType, kSCValNetInterfaceTypeEthernet)) {
+ /* sorry, no AT networking on this interface */
+ goto done;
+ }
+
+ /*
+ * get port name (from interface dictionary).
+ */
+ if_port = CFDictionaryGetValue(if_dict, kSCPropNetInterfaceDeviceName);
+ if (!isA_CFString(if_port)) {
+ goto done;
+ }
+
+ /*
+ * add ServiceID and interface port name to entity dictionary.
+ */
+ new_dict = CFDictionaryCreateMutableCopy(NULL, 0, ent_dict);
+ CFDictionarySetValue(new_dict, CFSTR("ServiceID"), serviceID);
+ CFDictionarySetValue(new_dict, kSCPropNetInterfaceDeviceName, if_port);
+
+ done:
+
+ if (ent_dict) CFRelease(ent_dict);
+ if (if_dict) CFRelease(if_dict);
+ if (serviceID) CFRelease(serviceID);
+ return (CFDictionaryRef)new_dict;
+}
+
+
+static CFArrayRef
+entity_all(SCDynamicStoreRef store, CFStringRef entity, CFArrayRef order)
+{
+ CFMutableArrayRef defined = NULL;
+ CFIndex i;
+ CFIndex n;
+ CFMutableArrayRef ordered = NULL;
+ CFStringRef pattern;
+
+ ordered = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCCompAnyRegex,
+ entity);
+ defined = (CFMutableArrayRef)SCDynamicStoreCopyKeyList(store, pattern);
+ CFRelease(pattern);
+ if (defined && (CFArrayGetCount(defined) > 0)) {
+ CFArrayRef tmp;
+
+ tmp = defined;
+ defined = CFArrayCreateMutableCopy(NULL, 0, tmp);
+ CFRelease(tmp);
+ } else {
+ goto done;
+ }
+
+ n = order ? CFArrayGetCount(order) : 0;
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict;
+ CFStringRef key;
+ CFIndex j;
+ CFStringRef service;
+
+ service = CFArrayGetValueAtIndex(order, i);
+ if (!isA_CFString(service)) {
+ continue;
+ }
+
+ key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ service,
+ entity);
+ dict = entity_one(store, key);
+ if (dict) {
+ CFArrayAppendValue(ordered, dict);
+ CFRelease(dict);
+ }
+
+ j = CFArrayGetFirstIndexOfValue(defined,
+ CFRangeMake(0, CFArrayGetCount(defined)),
+ key);
+ if (j != kCFNotFound) {
+ CFArrayRemoveValueAtIndex(defined, j);
+ }
+
+ CFRelease(key);
+ }
+
+ n = CFArrayGetCount(defined);
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict;
+ CFStringRef key;
+
+ key = CFArrayGetValueAtIndex(defined, i);
+ dict = entity_one(store, key);
+ if (dict) {
+ CFArrayAppendValue(ordered, dict);
+ CFRelease(dict);
+ }
+ }
+
+ done:
+
+ if (defined) CFRelease(defined);
+ if (CFArrayGetCount(ordered) == 0) {
+ CFRelease(ordered);
+ ordered = NULL;
+ }
+ return ordered;
+}
+
+
+static void
+encodeName(CFStringRef name,
+ CFStringEncoding encoding,
+ CFMutableDictionaryRef startup,
+ CFMutableDictionaryRef globals)
+{
+ CFDataRef bytes;
+ CFMutableStringRef encodedName = NULL;
+ CFIndex len;
+
+ if (!isA_CFString(name)) {
+ return;
+ }
+
+ if (encoding == kCFStringEncodingASCII) {
+ encodedName = (CFMutableStringRef)CFStringCreateCopy(NULL, name);
+ goto done;
+ }
+
+ /*
+ * encode the potentially non-printable string
+ */
+ bytes = CFStringCreateExternalRepresentation(NULL,
+ name,
+ encoding,
+ 0);
+ if (bytes) {
+ unsigned char *byte;
+ CFIndex i;
+
+ /*
+ * check if the MacRoman string can be represented as ASCII
+ */
+ if (encoding == kCFStringEncodingMacRoman) {
+ CFDataRef ascii;
+
+ ascii = CFStringCreateExternalRepresentation(NULL,
+ name,
+ kCFStringEncodingASCII,
+ 0);
+ if (ascii) {
+ CFRelease(ascii);
+ CFRelease(bytes);
+ encodedName = (CFMutableStringRef)CFStringCreateCopy(NULL, name);
+ goto done;
+ }
+ }
+
+ encodedName = CFStringCreateMutable(NULL, 0);
+
+ len = CFDataGetLength(bytes);
+ byte = (unsigned char *)CFDataGetBytePtr(bytes);
+ for (i = 0; i < len; i++, byte++) {
+ CFStringAppendFormat(encodedName,
+ NULL,
+ CFSTR("%02x"),
+ *byte);
+ }
+
+ /*
+ * add "encoded string" markers
+ */
+ CFStringInsert(encodedName, 0, CFSTR("*"));
+ CFStringAppend(encodedName, CFSTR("*"));
+
+ CFRelease(bytes);
+ }
+
+ done :
+
+ if (encodedName) {
+ if (startup) {
+ /* update "startup" dictionary */
+ CFDictionaryAddValue(startup, CFSTR("APPLETALK_HOSTNAME"), encodedName);
+ }
+
+ if (globals) {
+ CFNumberRef num;
+
+ /* update "global" dictionary */
+ num = CFNumberCreate(NULL, kCFNumberIntType, &encoding);
+ CFDictionaryAddValue(globals, kSCPropNetAppleTalkComputerName, name);
+ CFDictionaryAddValue(globals, kSCPropNetAppleTalkComputerNameEncoding, num);
+ CFRelease(num);
+ }
+
+ CFRelease(encodedName);
+ }
+
+ return;
+}
+
+
+static boolean_t
+updateConfiguration(int *newState)
+{
+ boolean_t changed = FALSE;
+ CFStringRef computerName;
+ CFStringEncoding computerNameEncoding;
+ CFArrayRef configuredServices = NULL;
+ CFDictionaryRef dict;
+ CFIndex i;
+ CFIndex ifCount = 0;
+ CFMutableArrayRef info = NULL;
+ CFArrayRef interfaces = NULL;
+ CFStringRef key;
+ CFArrayRef keys;
+ CFIndex n;
+ CFMutableArrayRef newConfigFile;
+ CFMutableDictionaryRef newDefaults;
+ CFMutableDictionaryRef newDict;
+ CFMutableDictionaryRef newGlobals;
+ CFMutableDictionaryRef newGlobalsX; /* newGlobals without ServiceID */
+ CFMutableDictionaryRef newStartup;
+ CFMutableDictionaryRef newZones;
+ CFNumberRef num;
+ CFMutableDictionaryRef curGlobalsX; /* curGlobals without ServiceID */
+ CFStringRef pattern;
+ boolean_t postGlobals = FALSE;
+ CFStringRef primaryPort = NULL; /* primary interface */
+ CFStringRef primaryZone = NULL;
+ CFArrayRef serviceOrder = NULL;
+ CFDictionaryRef setGlobals = NULL;
+
+ cache_open();
+
+ /*
+ * establish the "new" AppleTalk configuration
+ */
+ *newState = curState;
+ newConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ newGlobals = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ newDefaults = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ newStartup = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ newZones = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ /* initialize overall state */
+ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-NO-"));
+
+ /*
+ * get the global settings (ServiceOrder, ComputerName, ...)
+ */
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetAppleTalk);
+ setGlobals = cache_SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+ if (setGlobals) {
+ if (isA_CFDictionary(setGlobals)) {
+ /* get service order */
+ serviceOrder = CFDictionaryGetValue(setGlobals,
+ kSCPropNetServiceOrder);
+ serviceOrder = isA_CFArray(serviceOrder);
+ if (serviceOrder) {
+ CFRetain(serviceOrder);
+ }
+ } else {
+ CFRelease(setGlobals);
+ setGlobals = NULL;
+ }
+ }
+
+ /*
+ * if we don't have an AppleTalk ServiceOrder, use IPv4's (if defined)
+ */
+ if (!serviceOrder) {
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetIPv4);
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ serviceOrder = CFDictionaryGetValue(dict,
+ kSCPropNetServiceOrder);
+ serviceOrder = isA_CFArray(serviceOrder);
+ if (serviceOrder) {
+ CFRetain(serviceOrder);
+ }
+ }
+ CFRelease(dict);
+ }
+ }
+
+ /*
+ * get the list of ALL configured services
+ */
+ configuredServices = entity_all(store, kSCEntNetAppleTalk, serviceOrder);
+ if (configuredServices) {
+ ifCount = CFArrayGetCount(configuredServices);
+ }
+
+ if (serviceOrder) CFRelease(serviceOrder);
+
+ /*
+ * get the list of ALL active interfaces
+ */
+ key = SCDynamicStoreKeyCreateNetworkInterface(NULL, kSCDynamicStoreDomainState);
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ interfaces = CFDictionaryGetValue(dict,
+ kSCDynamicStorePropNetInterfaces);
+ interfaces = isA_CFArray(interfaces);
+ if (interfaces) {
+ CFRetain(interfaces);
+ }
+ }
+ CFRelease(dict);
+ }
+
+ /*
+ * get the list of previously configured services
+ */
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetAppleTalk);
+ keys = SCDynamicStoreCopyKeyList(store, pattern);
+ CFRelease(pattern);
+ if (keys) {
+ info = CFArrayCreateMutableCopy(NULL, 0, keys);
+ CFRelease(keys);
+ }
+
+ /*
+ * iterate over each configured service to establish the new
+ * configuration.
+ */
+ for (i = 0; i < ifCount; i++) {
+ CFDictionaryRef service;
+ CFStringRef ifName;
+ CFStringRef configMethod;
+ CFMutableStringRef portConfig = NULL;
+ CFArrayRef networkRange; /* for seed ports, CFArray[2] of CFNumber (lo, hi) */
+ int sNetwork;
+ int eNetwork;
+ CFArrayRef zoneList; /* for seed ports, CFArray[] of CFString (zones names) */
+ CFIndex zCount;
+ CFIndex j;
+ CFMutableDictionaryRef ifDefaults = NULL;
+ CFNumberRef defaultNetwork;
+ CFNumberRef defaultNode;
+ CFStringRef defaultZone;
+
+ /* get AppleTalk service dictionary */
+ service = CFArrayGetValueAtIndex(configuredServices, i);
+
+ /* get interface name */
+ ifName = CFDictionaryGetValue(service, kSCPropNetInterfaceDeviceName);
+
+ /* check inteface availability */
+ if (!interfaces ||
+ !CFArrayContainsValue(interfaces, CFRangeMake(0, CFArrayGetCount(interfaces)), ifName)) {
+ /* if interface not available */
+ goto nextIF;
+ }
+
+ /* check interface link status */
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ ifName,
+ kSCEntNetLink);
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+ if (dict) {
+ Boolean linkStatus = TRUE; /* assume the link is "up" */
+ Boolean ifDetaching = FALSE; /* assume link is not detaching */
+
+ /* the link key for this interface is available */
+ if (isA_CFDictionary(dict)) {
+ CFBooleanRef bVal;
+
+ bVal = CFDictionaryGetValue(dict, kSCPropNetLinkActive);
+ if (isA_CFBoolean(bVal)) {
+ linkStatus = CFBooleanGetValue(bVal);
+ }
+
+ /* check if interface is detaching - value
+ doesn't really matter, only that it exists */
+ ifDetaching = CFDictionaryContainsKey(dict, kSCPropNetLinkDetaching);
+ }
+ CFRelease(dict);
+
+ if (!linkStatus || ifDetaching) {
+ /* if link status down or the interface is detaching */
+ goto nextIF;
+ }
+ }
+
+ /*
+ * Determine configuration method for this service
+ */
+ configMethod = CFDictionaryGetValue(service, kSCPropNetAppleTalkConfigMethod);
+ if (!isA_CFString(configMethod)) {
+ /* if no ConfigMethod */
+ goto nextIF;
+ }
+
+ if (!CFEqual(configMethod, kSCValNetAppleTalkConfigMethodNode ) &&
+ !CFEqual(configMethod, kSCValNetAppleTalkConfigMethodRouter ) &&
+ !CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+ /* if not one of the expected values, disable */
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("Unexpected AppleTalk ConfigMethod: %@"),
+ configMethod);
+ goto nextIF;
+ }
+
+ /*
+ * the first service to be defined will always be "primary"
+ */
+ if (CFArrayGetCount(newConfigFile) == 0) {
+ CFDictionaryRef active;
+
+ CFDictionarySetValue(newGlobals,
+ kSCDynamicStorePropNetPrimaryService,
+ CFDictionaryGetValue(service, CFSTR("ServiceID")));
+ CFDictionarySetValue(newGlobals,
+ kSCDynamicStorePropNetPrimaryInterface,
+ ifName);
+
+ /* and check if AT newtorking is active on the primary interface */
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ ifName,
+ kSCEntNetAppleTalk);
+ active = cache_SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+ if (active) {
+ if (isA_CFDictionary(active)) {
+ postGlobals = TRUE;
+ }
+ CFRelease(active);
+ }
+ }
+
+ /*
+ * define the port
+ */
+ portConfig = CFStringCreateMutable(NULL, 0);
+ CFStringAppendFormat(portConfig, NULL, CFSTR("%@:"), ifName);
+
+ if (CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+ CFNumberRef num;
+
+ /*
+ * we have been asked to configure this interface as a
+ * seed port. Ensure that we have been provided at least
+ * one network number, have been provided with at least
+ * one zonename, ...
+ */
+
+ networkRange = CFDictionaryGetValue(service,
+ kSCPropNetAppleTalkSeedNetworkRange);
+ if (!isA_CFArray(networkRange) || (CFArrayGetCount(networkRange) == 0)) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("AppleTalk configuration error (%@)"),
+ kSCPropNetAppleTalkSeedNetworkRange);
+ goto nextIF;
+ }
+
+ /*
+ * establish the starting and ending network numbers
+ */
+ num = CFArrayGetValueAtIndex(networkRange, 0);
+ if (!isA_CFNumber(num)) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("AppleTalk configuration error (%@)"),
+ kSCPropNetAppleTalkSeedNetworkRange);
+ goto nextIF;
+ }
+ CFNumberGetValue(num, kCFNumberIntType, &sNetwork);
+ eNetwork = sNetwork;
+
+ if (CFArrayGetCount(networkRange) > 1) {
+ num = CFArrayGetValueAtIndex(networkRange, 1);
+ if (!isA_CFNumber(num)) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("AppleTalk configuration error (%@)"),
+ kSCPropNetAppleTalkSeedNetworkRange);
+ goto nextIF;
+ }
+ CFNumberGetValue(num, kCFNumberIntType, &eNetwork);
+ }
+ CFStringAppendFormat(portConfig, NULL, CFSTR("%d:%d:"), sNetwork, eNetwork);
+
+ /*
+ * establish the zones associated with this port
+ */
+ zoneList = CFDictionaryGetValue(service,
+ kSCPropNetAppleTalkSeedZones);
+ if (!isA_CFArray(zoneList)) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("AppleTalk configuration error (%@)"),
+ kSCPropNetAppleTalkSeedZones);
+ goto nextIF;
+ }
+
+ zCount = CFArrayGetCount(zoneList);
+ for (j = 0; j < zCount; j++) {
+ CFStringRef zone;
+ CFArrayRef ifList;
+ CFMutableArrayRef newIFList;
+
+ zone = CFArrayGetValueAtIndex(zoneList, j);
+ if (!isA_CFString(zone)) {
+ continue;
+ }
+
+ if (CFDictionaryGetValueIfPresent(newZones, zone, (const void **)&ifList)) {
+ /* known zone */
+ newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+ } else {
+ /* new zone */
+ newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(newIFList, ifName);
+ CFArraySortValues(newIFList,
+ CFRangeMake(0, CFArrayGetCount(newIFList)),
+ (CFComparatorFunction)CFStringCompare,
+ NULL);
+ CFDictionarySetValue(newZones, zone, newIFList);
+ CFRelease(newIFList);
+
+ /*
+ * flag the default zone
+ */
+ if (!primaryZone) {
+ primaryZone = CFRetain(zone);
+ }
+ }
+ if (!primaryZone) {
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("AppleTalk configuration error (%@)"),
+ kSCPropNetAppleTalkSeedZones);
+ goto nextIF;
+ }
+ }
+
+ /* get the (per-interface) "Computer Name" */
+ computerName = CFDictionaryGetValue(service,
+ kSCPropNetAppleTalkComputerName);
+ if (CFDictionaryGetValueIfPresent(service,
+ kSCPropNetAppleTalkComputerNameEncoding,
+ (const void **)&num) &&
+ isA_CFNumber(num)) {
+ CFNumberGetValue(num, kCFNumberIntType, &computerNameEncoding);
+ } else {
+ computerNameEncoding = CFStringGetSystemEncoding();
+ }
+ encodeName(computerName, computerNameEncoding, newStartup, newGlobals);
+
+ /*
+ * declare the first configured AppleTalk service / interface
+ * as the "home port".
+ */
+ if (CFArrayGetCount(newConfigFile) == 0) {
+ CFStringAppend(portConfig, CFSTR("*"));
+ primaryPort = CFRetain(ifName);
+ }
+ CFArrayAppendValue(newConfigFile, portConfig);
+
+ /*
+ * get the per-interface defaults
+ */
+ ifDefaults = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ defaultNetwork = CFDictionaryGetValue(service, kSCPropNetAppleTalkNetworkID);
+ defaultNode = CFDictionaryGetValue(service, kSCPropNetAppleTalkNodeID);
+ if (isA_CFNumber(defaultNetwork) && isA_CFNumber(defaultNode)) {
+ /*
+ * set the default node and network
+ */
+ CFDictionarySetValue(ifDefaults,
+ kSCPropNetAppleTalkNetworkID,
+ defaultNetwork);
+ CFDictionarySetValue(ifDefaults,
+ kSCPropNetAppleTalkNodeID,
+ defaultNode);
+ }
+
+ if ((CFDictionaryGetValueIfPresent(service,
+ kSCPropNetAppleTalkDefaultZone,
+ (const void **)&defaultZone) == TRUE)) {
+ /*
+ * set the default zone for this interface
+ */
+ CFDictionarySetValue(ifDefaults,
+ kSCPropNetAppleTalkDefaultZone,
+ defaultZone);
+ }
+
+ CFDictionarySetValue(newDefaults, ifName, ifDefaults);
+ CFRelease(ifDefaults);
+
+ switch (CFArrayGetCount(newConfigFile)) {
+ case 1:
+ /*
+ * first AppleTalk interface
+ */
+ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), ifName);
+ break;
+ case 2:
+ /* second AppleTalk interface */
+ if (!CFEqual(CFDictionaryGetValue(newStartup, CFSTR("APPLETALK")),
+ CFSTR("-ROUTER-"))) {
+ /*
+ * if not routing (yet), configure as multi-home
+ */
+ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-MULTIHOME-"));
+ }
+ break;
+ }
+
+ if (CFEqual(configMethod, kSCValNetAppleTalkConfigMethodRouter) ||
+ CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+ /* if not a simple node, enable routing */
+ CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-ROUTER-"));
+ }
+
+ /*
+ * establish the State:/Network/Service/nnn/AppleTalk key info
+ */
+ key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ CFDictionaryGetValue(service, CFSTR("ServiceID")),
+ kSCEntNetAppleTalk);
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(newDict, kSCPropInterfaceName, ifName);
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ CFRelease(newDict);
+ if (info) {
+ j = CFArrayGetFirstIndexOfValue(info,
+ CFRangeMake(0, CFArrayGetCount(info)),
+ key);
+ if (j != kCFNotFound) {
+ CFArrayRemoveValueAtIndex(info, j);
+ }
+ }
+ CFRelease(key);
+
+ nextIF :
+
+ if (portConfig) CFRelease(portConfig);
+ }
+
+ if (primaryZone) {
+ CFArrayRef ifList;
+ CFMutableArrayRef newIFList;
+
+ ifList = CFDictionaryGetValue(newZones, primaryZone);
+ if (CFArrayContainsValue(ifList,
+ CFRangeMake(0, CFArrayGetCount(ifList)),
+ primaryPort)) {
+ newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+ CFArrayAppendValue(newIFList, CFSTR("*"));
+ CFDictionarySetValue(newZones, primaryZone, newIFList);
+ CFRelease(newIFList);
+ }
+ CFRelease(primaryZone);
+ }
+ if (primaryPort) {
+ CFRelease(primaryPort);
+ }
+
+ /* sort the ports */
+ i = CFArrayGetCount(newConfigFile);
+ CFArraySortValues(newConfigFile,
+ CFRangeMake(0, i),
+ (CFComparatorFunction)CFStringCompare,
+ NULL);
+
+ /* add the zones to the configuration */
+ CFDictionaryApplyFunction(newZones, addZoneToPorts, newConfigFile);
+ CFRelease(newZones);
+
+ /* sort the zones */
+ CFArraySortValues(newConfigFile,
+ CFRangeMake(i, CFArrayGetCount(newConfigFile)-i),
+ (CFComparatorFunction)CFStringCompare,
+ NULL);
+
+ /* ensure that the last line of the configuration file is terminated */
+ CFArrayAppendValue(newConfigFile, CFSTR(""));
+
+ /*
+ * Check if we have a "ComputerName" and look elsewhere if we don't have
+ * one yet.
+ */
+ if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME")) &&
+ (setGlobals != NULL)) {
+ computerName = CFDictionaryGetValue(setGlobals,
+ kSCPropNetAppleTalkComputerName);
+ if (CFDictionaryGetValueIfPresent(setGlobals,
+ kSCPropNetAppleTalkComputerNameEncoding,
+ (const void **)&num) &&
+ isA_CFNumber(num)) {
+ CFNumberGetValue(num, kCFNumberIntType, &computerNameEncoding);
+ } else {
+ computerNameEncoding = CFStringGetSystemEncoding();
+ }
+ encodeName(computerName, computerNameEncoding, newStartup, newGlobals);
+ }
+ if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME"))) {
+ computerName = SCDynamicStoreCopyComputerName(store, &computerNameEncoding);
+ if (computerName) {
+ encodeName(computerName, computerNameEncoding, newStartup, newGlobals);
+ CFRelease(computerName);
+ }
+ }
+ if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME"))) {
+ struct utsname name;
+
+ if (uname(&name) == 0) {
+ computerName = CFStringCreateWithCString(NULL, name.nodename, kCFStringEncodingASCII);
+ if (computerName) {
+ encodeName(computerName, kCFStringEncodingASCII, NULL, newGlobals);
+ CFRelease(computerName);
+ }
+ }
+ }
+
+ /* compare the previous and current configurations */
+
+ curGlobalsX = CFDictionaryCreateMutableCopy(NULL, 0, curGlobals);
+ CFDictionaryRemoveValue(curGlobalsX, kSCDynamicStorePropNetPrimaryService);
+
+ newGlobalsX = CFDictionaryCreateMutableCopy(NULL, 0, newGlobals);
+ CFDictionaryRemoveValue(newGlobalsX, kSCDynamicStorePropNetPrimaryService);
+
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetAppleTalk);
+
+ if (CFEqual(curGlobalsX , newGlobalsX ) &&
+ CFEqual(curConfigFile , newConfigFile) &&
+ CFEqual(curDefaults , newDefaults ) &&
+ CFEqual(curStartup , newStartup )
+ ) {
+ /*
+ * the configuration has not changed.
+ */
+
+ if (postGlobals) {
+ /*
+ * the requested configuration hasn't changed but we
+ * now need to tell everyone that AppleTalk is active.
+ */
+ if (!SCDynamicStoreSetValue(store, key, newGlobals)) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("SCDynamicStoreSetValue() failed: %s"),
+ SCErrorString(SCError()));
+ }
+ }
+
+ CFRelease(newGlobals);
+ CFRelease(newConfigFile);
+ CFRelease(newDefaults);
+ CFRelease(newStartup);
+ } else if (CFArrayGetCount(newConfigFile) <= 1) {
+ /*
+ * the configuration has changed but there are no
+ * longer any interfaces configured for AppleTalk
+ * networking.
+ */
+
+ /*
+ * remove the global (State:/Network/Global/AppleTalk) key.
+ *
+ * Note: it will be restored later after AT networking has
+ * been activated.
+ */
+
+ /* remove the (/etc/appletalk.cfg) configuration file */
+ (void)unlink(AT_CFG_FILE);
+
+ /*
+ * update the per-service (and global) state
+ */
+ cache_SCDynamicStoreRemoveValue(store, key); // remove State:/Network/Global/AppleTalk
+ n = CFArrayGetCount(info);
+ for (i = 0; i < n; i++) {
+ CFStringRef xKey = CFArrayGetValueAtIndex(info, i);
+
+ cache_SCDynamicStoreRemoveValue(store, xKey);
+ }
+ cache_write(store);
+
+ /* flag this as a new configuration */
+ *newState = -(abs(curState) + 1);
+ changed = TRUE;
+ } else {
+ /*
+ * the configuration has changed.
+ */
+
+ /* update the (/etc/appletalk.cfg) configuration file */
+ configWrite(AT_CFG_FILE, newConfigFile);
+
+ /*
+ * update the per-service (and global) state
+ *
+ * Note: if present, we remove any existing global state key and allow it
+ * to be restored after the stack has been re-started.
+ */
+ CFDictionaryApplyFunction(newDefaults, updateDefaults, NULL);
+ cache_SCDynamicStoreRemoveValue(store, key); // remove State:/Network/Global/AppleTalk
+ n = CFArrayGetCount(info);
+ for (i = 0; i < n; i++) {
+ CFStringRef xKey = CFArrayGetValueAtIndex(info, i);
+
+ cache_SCDynamicStoreRemoveValue(store, xKey);
+ }
+ cache_write(store);
+
+ /* flag this as a new configuration */
+ *newState = abs(curState) + 1;
+ changed = TRUE;
+ }
+
+ CFRelease(curGlobalsX);
+ CFRelease(newGlobalsX);
+ CFRelease(key);
+
+ if (changed) {
+ CFRelease(curGlobals);
+ curGlobals = newGlobals;
+ CFRelease(curConfigFile);
+ curConfigFile = newConfigFile;
+ CFRelease(curDefaults);
+ curDefaults = newDefaults;
+ CFRelease(curStartup);
+ curStartup = newStartup;
+ }
+
+ if (info) CFRelease(info);
+ if (interfaces) CFRelease(interfaces);
+ if (configuredServices) CFRelease(configuredServices);
+ if (setGlobals) CFRelease(setGlobals);
+
+ cache_close();
+
+ return changed;
+}
+
+
+#include <sysexits.h>
+#define AT_CMD_SUCCESS EX_OK /* success */
+#define AT_CMD_ALREADY_RUNNING EX__MAX + 10
+#define AT_CMD_NOT_RUNNING EX__MAX + 11
+
+
+static int
+stackState()
+{
+ int ret;
+ int sock;
+ at_state_t state;
+
+ sock = socket(AF_APPLETALK, SOCK_RAW, 0);
+ ret = ioctl(sock, AIOCGETSTATE, (caddr_t)&state);
+ (void)close(sock);
+ if (ret == -1) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("ioctl(AIOCGETSTATE) failed: %s"), strerror(errno));
+ return FALSE;
+ }
+
+ if (state.flags & AT_ST_STARTED) {
+ return abs(curState);
+ } else {
+ return -(abs(curState));
+ }
+}
+
+
+static pid_t execCommand = 0;
+static int execRetry;
+
+
+static void
+stopComplete(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+ execCommand = 0;
+
+ if (WIFEXITED(status)) {
+ switch (WEXITSTATUS(status)) {
+ case AT_CMD_SUCCESS :
+ case AT_CMD_NOT_RUNNING :
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown complete"));
+ if (curState > 0) {
+ // the stack is down but we really want it up
+ startAppleTalk(NULL, (void *)curState);
+ }
+ return;
+ default :
+ break;
+ }
+ }
+
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("AppleTalk shutdown failed, status = %d%s"),
+ WEXITSTATUS(status),
+ (execRetry > 1) ? " (retrying)" : "");
+
+ // shutdown failed, retry
+ if (--execRetry > 0) {
+ CFRunLoopTimerContext timerContext = { 0, (void *)curState, NULL, NULL, NULL };
+ CFRunLoopTimerRef timer;
+
+ timer = CFRunLoopTimerCreate(NULL,
+ CFAbsoluteTimeGetCurrent() + 1.0,
+ 0.0,
+ 0,
+ 0,
+ stopAppleTalk,
+ &timerContext);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
+ CFRelease(timer);
+ return;
+ } else {
+ // we weren't able to stop
+ curState = stackState();
+ }
+
+ return;
+}
+
+
+static void
+stopAppleTalk(CFRunLoopTimerRef timer, void *info)
+{
+ char *argv[] = { "appletalk",
+ "-d",
+ NULL };
+
+ if (execCommand == 0) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown"));
+ } else {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown skipped, transition in progress"));
+ return;
+ }
+
+ execCommand = _SCDPluginExecCommand(stopComplete, // callback
+ info, // context
+ 0, // uid
+ 0, // gid
+ "/usr/sbin/appletalk", // path
+ argv); // argv
+
+ if (!timer) {
+ execRetry = 5; // initialize retry count
+ }
+
+ return;
+}
+
+
+static void
+startComplete(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+ execCommand = 0;
+
+ if (WIFEXITED(status)) {
+ switch (WEXITSTATUS(status)) {
+ case AT_CMD_SUCCESS :
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup complete"));
+ if ((curState < 0) || (curState > (int)context)) {
+ // the stack is now up but we really want it down
+ stopAppleTalk(NULL, (void *)curState);
+ }
+ return;
+ case AT_CMD_ALREADY_RUNNING :
+ // the stack is already up but we're not sure
+ // if the configuration is correct, restart
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk already running, restarting"));
+ stopAppleTalk(NULL, (void *)curState);
+ return;
+ default :
+ break;
+ }
+ }
+
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("AppleTalk startup failed, status = %d%s"),
+ WEXITSTATUS(status),
+ (execRetry > 1) ? " (retrying)" : "");
+
+ // startup failed, retry
+ if (--execRetry > 0) {
+ CFRunLoopTimerContext timerContext = { 0, (void *)curState, NULL, NULL, NULL };
+ CFRunLoopTimerRef timer;
+
+ timer = CFRunLoopTimerCreate(NULL,
+ CFAbsoluteTimeGetCurrent() + 1.0,
+ 0.0,
+ 0,
+ 0,
+ startAppleTalk,
+ &timerContext);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
+ CFRelease(timer);
+ return;
+ } else {
+ // we weren't able to start
+ curState = stackState();
+ }
+
+ return;
+}
+
+
+static void
+startAppleTalk(CFRunLoopTimerRef timer, void *info)
+{
+ int argc = 0;
+ char *argv[8];
+ char *computerName = NULL;
+ char *interface = NULL;
+ CFStringRef mode = CFDictionaryGetValue(curStartup, CFSTR("APPLETALK"));
+ CFStringRef name = CFDictionaryGetValue(curStartup, CFSTR("APPLETALK_HOSTNAME"));
+
+ if (execCommand == 0) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup"));
+ } else {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup skipped, transition in progress"));
+ return;
+ }
+
+ if (!mode) {
+ // Huh?
+ return;
+ }
+
+ // set command name
+ argv[argc++] = "appletalk";
+
+ // set hostname
+ if (name) {
+ computerName = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
+ if (computerName) {
+ argv[argc++] = "-C";
+ argv[argc++] = computerName;
+ } else {
+ // could not convert name
+ goto done;
+ }
+ }
+
+ // set mode
+ if (CFEqual(mode, CFSTR("-ROUTER-"))) {
+ argv[argc++] = "-r";
+ } else if (CFEqual(mode, CFSTR("-MULTIHOME-"))) {
+ argv[argc++] = "-x";
+ } else {
+ interface = _SC_cfstring_to_cstring(mode, NULL, 0, kCFStringEncodingASCII);
+ if (interface) {
+ argv[argc++] = "-u";
+ argv[argc++] = interface;
+ } else {
+ // could not convert interface
+ goto done;
+ }
+ }
+
+ // set non-interactive
+ argv[argc++] = "-q";
+
+ // close argument list
+ argv[argc++] = NULL;
+
+ execCommand = _SCDPluginExecCommand(startComplete, // callback
+ info, // context
+ 0, // uid
+ 0, // gid
+ "/usr/sbin/appletalk", // path
+ argv); // argv
+
+ if (!timer) {
+ execRetry = 5; // initialize retry count
+ }
+
+ done :
+
+ if (computerName) CFAllocatorDeallocate(NULL, computerName);
+ if (interface) CFAllocatorDeallocate(NULL, interface);
+
+ return;
+}
+
+
+static void
+atConfigChangedCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg)
+{
+ boolean_t configChanged;
+ int newState;
+
+ configChanged = updateConfiguration(&newState);
+
+ if (configChanged && (execCommand == 0)) {
+ // if the configuration has changed and we're not already transitioning
+ if (newState > 0) {
+ if (curState > 0) {
+ // already running, restart [with new configuration]
+ stopAppleTalk(NULL, (void *)newState);
+ } else {
+ startAppleTalk(NULL, (void *)newState);
+ }
+ } else {
+ if (curState > 0) {
+ stopAppleTalk(NULL, (void *)newState);
+ }
+ }
+ }
+
+ curState = newState;
+
+ return;
+}
+
+
+void
+stop_ATconfig(CFRunLoopSourceRef stopRls)
+{
+ // cleanup
+
+ if (storeRls != NULL) {
+ CFRunLoopSourceInvalidate(storeRls);
+ CFRelease(storeRls);
+ storeRls = NULL;
+ }
+
+ if (store != NULL) {
+ CFRelease(store);
+ store = NULL;
+ CFRelease(curGlobals);
+ CFRelease(curConfigFile);
+ CFRelease(curDefaults);
+ CFRelease(curStartup);
+ }
+
+ CFRunLoopSourceSignal(stopRls);
+ return;
+}
+
+
+void
+load_ATconfig(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ CFStringRef key;
+ CFMutableArrayRef keys = NULL;
+ CFStringRef pattern;
+ CFMutableArrayRef patterns = NULL;
+
+ if (bundleVerbose) {
+ _verbose = TRUE;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+ /* initialize a few globals */
+
+ curGlobals = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ curConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ curDefaults = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ curStartup = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ /* open a "configd" store to allow cache updates */
+ store = SCDynamicStoreCreate(NULL,
+ CFSTR("AppleTalk Configuraton plug-in"),
+ atConfigChangedCallback,
+ NULL);
+ if (!store) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed: %s"), SCErrorString(SCError()));
+ goto error;
+ }
+
+ /* establish notification keys and patterns */
+
+ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ /* ...watch for (global) AppleTalk configuration changes */
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetAppleTalk);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ /* ...watch for (per-service) AppleTalk configuration changes */
+ pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCCompAnyRegex,
+ kSCEntNetAppleTalk);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+
+ /* ...watch for network interface link status changes */
+ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetLink);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+
+ /* ...watch for (per-interface) AppleTalk configuration changes */
+ pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetAppleTalk);
+ CFArrayAppendValue(patterns, pattern);
+ CFRelease(pattern);
+
+ /* ...watch for computer name changes */
+ key = SCDynamicStoreKeyCreateComputerName(NULL);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ /* register the keys/patterns */
+ if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+ CFRelease(keys);
+ CFRelease(patterns);
+
+ storeRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+ if (!storeRls) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRls, kCFRunLoopDefaultMode);
+
+ return;
+
+ error :
+
+ if (curGlobals) CFRelease(curGlobals);
+ if (curConfigFile) CFRelease(curConfigFile);
+ if (curDefaults) CFRelease(curDefaults);
+ if (curStartup) CFRelease(curStartup);
+ if (store) CFRelease(store);
+ if (keys) CFRelease(keys);
+ if (patterns) CFRelease(patterns);
+ return;
+}
+
+
+#ifdef MAIN
+#include "cfManager.c"
+int
+main(int argc, char **argv)
+{
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_ATconfig(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * July 17, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "cfManager.h"
+
+
+#ifdef NOTNOW
+/*
+ * Opens a configuration file and returns a CFArrayRef consisting
+ * of a CFStringRef for each line.
+ */
+__private_extern__
+CFArrayRef
+configRead(const char *path)
+{
+ int fd;
+ struct stat statBuf;
+ CFMutableDataRef data;
+ CFStringRef str;
+ CFArrayRef config = NULL;
+
+ fd = open(path, O_RDONLY, 0644);
+ if (fd < 0) {
+ goto done;
+ }
+ if (fstat(fd, &statBuf) < 0) {
+ goto done;
+ }
+ if ((statBuf.st_mode & S_IFMT) != S_IFREG) {
+ goto done;
+ }
+
+ data = CFDataCreateMutable(NULL, statBuf.st_size);
+ CFDataSetLength(data, statBuf.st_size);
+ if(read(fd, (void *)CFDataGetMutableBytePtr(data), statBuf.st_size) != statBuf.st_size) {
+ CFRelease(data);
+ goto done;
+ }
+
+ str = CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingMacRoman);
+ CFRelease(data);
+
+ config = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR("\n"));
+ CFRelease(str);
+
+ done:
+
+ if (fd >= 0) {
+ close(fd);
+ }
+ if (config == NULL) {
+ CFMutableArrayRef emptyConfig;
+
+ /* pretend that we found an empty file */
+ emptyConfig = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFArrayAppendValue(emptyConfig, CFSTR(""));
+ config = (CFArrayRef)emptyConfig;
+ }
+ return config;
+}
+#endif /* NOTNOW */
+
+/*
+ * Writes a new configuration file with the contents of a CFArrayRef. Each
+ * element of the array is a CFStringRef.
+ */
+__private_extern__
+void
+configWrite(const char *path, CFArrayRef config)
+{
+ CFStringRef str;
+ CFDataRef data;
+ int fd = -1;
+ int len;
+
+ str = CFStringCreateByCombiningStrings(NULL, config, CFSTR("\n"));
+ data = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingMacRoman, '.');
+ CFRelease(str);
+
+ fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (fd < 0) {
+ goto done;
+ }
+
+ len = CFDataGetLength(data);
+ if (len) {
+ (void)write(fd, CFDataGetBytePtr(data), len);
+ }
+
+ done:
+
+ if (fd >= 0)
+ close(fd);
+ CFRelease(data);
+ return;
+}
+
+
+#ifdef NOTNOW
+__private_extern__
+void
+configSet(CFMutableArrayRef config, CFStringRef key, CFStringRef value)
+{
+ CFMutableStringRef pref;
+ CFIndex configLen = CFArrayGetCount(config);
+ CFIndex i;
+ CFIndex n;
+ CFMutableStringRef newValue;
+ CFRange range;
+ CFStringRef specialChars = CFSTR(" \"'$!|\\<>`{}[]");
+ boolean_t mustQuote = FALSE;
+
+ /* create search prefix */
+ pref = CFStringCreateMutableCopy(NULL, 0, key);
+ CFStringAppend(pref, CFSTR("="));
+
+ /*
+ * create new / replacement value
+ *
+ * Note: Since the configuration file may be processed by a
+ * shell script we need to ensure that, if needed, the
+ * string is properly quoted.
+ */
+ newValue = CFStringCreateMutableCopy(NULL, 0, value);
+
+ n = CFStringGetLength(specialChars);
+ for (i = 0; i < n; i++) {
+ CFStringRef specialChar;
+
+ specialChar = CFStringCreateWithSubstring(NULL, specialChars, CFRangeMake(i, 1));
+ range = CFStringFind(newValue, specialChar, 0);
+ CFRelease(specialChar);
+ if (range.location != kCFNotFound) {
+ /* this string has at least one special character */
+ mustQuote = TRUE;
+ break;
+ }
+ }
+
+ if (mustQuote) {
+ CFStringRef charsToQuote = CFSTR("\\\"$`");
+
+ /*
+ * in addition to quoting the entire string we also need to escape the
+ * space " " and backslash "\" characters
+ */
+ n = CFStringGetLength(charsToQuote);
+ for (i = 0; i < n; i++) {
+ CFStringRef quoteChar;
+ CFArrayRef matches;
+
+ quoteChar = CFStringCreateWithSubstring(NULL, charsToQuote, CFRangeMake(i, 1));
+ range = CFRangeMake(0, CFStringGetLength(newValue));
+ matches = CFStringCreateArrayWithFindResults(NULL,
+ newValue,
+ quoteChar,
+ range,
+ 0);
+ CFRelease(quoteChar);
+
+ if (matches) {
+ CFIndex j = CFArrayGetCount(matches);
+
+ while (--j >= 0) {
+ const CFRange *range;
+
+ range = CFArrayGetValueAtIndex(matches, j);
+ CFStringInsert(newValue, range->location, CFSTR("\\"));
+ }
+ CFRelease(matches);
+ }
+ }
+
+ CFStringInsert(newValue, 0, CFSTR("\""));
+ CFStringAppend(newValue, CFSTR("\""));
+ }
+
+ /* locate existing key */
+ for (i = 0; i < configLen; i++) {
+ if (CFStringHasPrefix(CFArrayGetValueAtIndex(config, i), pref)) {
+ break;
+ }
+ }
+
+ CFStringAppend(pref, newValue);
+ CFRelease(newValue);
+ if (i < configLen) {
+ /* if replacing an existing entry */
+ CFArraySetValueAtIndex(config, i, pref);
+ } else {
+ /*
+ * if new entry, insert it just prior to the last (emtpy)
+ * array element.
+ */
+ CFArrayInsertValueAtIndex(config, configLen-1, pref);
+ }
+ CFRelease(pref);
+
+ return;
+}
+
+
+__private_extern__
+void
+configRemove(CFMutableArrayRef config, CFStringRef key)
+{
+ CFMutableStringRef pref;
+ CFIndex configLen = CFArrayGetCount(config);
+ CFIndex i;
+
+ /* create search prefix */
+ pref = CFStringCreateMutableCopy(NULL, 0, key);
+ CFStringAppend(pref, CFSTR("="));
+
+ /* locate existing key */
+ for (i = 0; i < configLen; i++) {
+ if (CFStringHasPrefix(CFArrayGetValueAtIndex(config, i), pref)) {
+ /* entry found, remove it */
+ CFArrayRemoveValueAtIndex(config, i);
+ break;
+ }
+ }
+
+ CFRelease(pref);
+ return;
+}
+#endif /* NOTNOW */
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * July 17, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef __CFMANAGER_H
+#define __CFMANAGER_H
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <sys/cdefs.h>
+
+
+__BEGIN_DECLS
+
+#ifdef NOTNOW
+CFArrayRef configRead __P((const char *path));
+#endif /* NOTNOW */
+void configWrite __P((const char *path, CFArrayRef config));
+#ifdef NOTNOW
+void configSet __P((CFMutableArrayRef config, CFStringRef key, CFStringRef value));
+void configRemove __P((CFMutableArrayRef config, CFStringRef key));
+#endif /* NOTNOW */
+
+__END_DECLS
+
+
+#endif /* __CFMANAGER_H */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>IPMonitor</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.IPMonitor</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.IPConfiguration</string>
+ <string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+ </array>
+ <key>Builtin</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+ <dict>
+ <key>Options</key>
+ <string>attempts:4</string>
+ <key>ServerAddresses</key>
+ <array>
+ <string>224.0.0.251</string>
+ <string>ff02::fb</string>
+ </array>
+ <key>ServerPort</key>
+ <integer>5353</integer>
+ <key>ServerTimeout</key>
+ <integer>2</integer>
+ <key>SupplementalMatchDomains</key>
+ <array>
+ <string>local</string>
+ <string>254.169.in-addr.arpa</string>
+ <string>0.8.e.f.ip6.arpa</string>
+ </array>
+ </dict>
+</array>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * March 22, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+#include <dnsinfo.h>
+#include <dnsinfo_create.h>
+
+
+/* pre-defined (supplemental) resolver configurations */
+static CFArrayRef S_predefined = NULL;
+
+
+static void
+add_supplemental(CFMutableArrayRef supplemental, CFDictionaryRef dns, uint32_t defaultOrder)
+{
+ CFArrayRef domains;
+ CFIndex i;
+ CFIndex n_domains;
+ CFArrayRef orders;
+
+
+ domains = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchDomains);
+ n_domains = isA_CFArray(domains) ? CFArrayGetCount(domains) : 0;
+ if (n_domains == 0) {
+ return;
+ }
+
+ orders = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchOrders);
+ if (orders != NULL) {
+ if (!isA_CFArray(orders) || (n_domains != CFArrayGetCount(orders))) {
+ return;
+ }
+ }
+
+ /*
+ * yes, this is a "supplemental" resolver configuration, expand
+ * the match domains and add each to the supplemental list.
+ */
+ for (i = 0; i < n_domains; i++) {
+ CFIndex j;
+ CFStringRef match_domain;
+ CFNumberRef match_order;
+ uint32_t match_order_val = 0;
+ CFMutableDictionaryRef match_resolver;
+ CFIndex n_supplemental;
+
+ match_domain = CFArrayGetValueAtIndex(domains, i);
+ if (!isA_CFString(match_domain)) {
+ continue;
+ }
+
+ match_order = (orders != NULL) ? CFArrayGetValueAtIndex(orders, i) : NULL;
+
+ match_resolver = CFDictionaryCreateMutableCopy(NULL, 0, dns);
+ CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSupplementalMatchDomains);
+ CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSupplementalMatchOrders);
+ CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSearchDomains);
+ CFDictionarySetValue(match_resolver, kSCPropNetDNSDomainName, match_domain);
+ if (isA_CFNumber(match_order)) {
+ CFDictionarySetValue(match_resolver, kSCPropNetDNSSearchOrder, match_order);
+ } else if (!CFDictionaryContainsKey(match_resolver, kSCPropNetDNSSearchOrder)) {
+ CFNumberRef num;
+
+ num = CFNumberCreate(NULL, kCFNumberIntType, &defaultOrder);
+ CFDictionarySetValue(match_resolver, kSCPropNetDNSSearchOrder, num);
+ CFRelease(num);
+ }
+
+ match_order = CFDictionaryGetValue(match_resolver, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(match_order) ||
+ !CFNumberGetValue(match_order, kCFNumberIntType, &match_order_val)) {
+ match_order = NULL;
+ match_order_val = 0;
+ }
+
+ n_supplemental = CFArrayGetCount(supplemental);
+ for (j = 0; j < n_supplemental; j++) {
+ CFMutableDictionaryRef compare;
+ Boolean match;
+ CFDictionaryRef supplemental_resolver;
+
+ supplemental_resolver = CFArrayGetValueAtIndex(supplemental, j);
+ if (CFEqual(match_resolver, supplemental_resolver)) {
+ // a real duplicate
+ CFRelease(match_resolver);
+ match_resolver = NULL;
+ break;
+ }
+
+ compare = CFDictionaryCreateMutableCopy(NULL, 0, supplemental_resolver);
+ if (match_order != NULL) {
+ CFDictionarySetValue(compare, kSCPropNetDNSSearchOrder, match_order);
+ }
+ match = CFEqual(match_resolver, compare);
+ CFRelease(compare);
+
+ if (match) {
+ CFNumberRef supplemental_order;
+ uint32_t supplemental_order_val = 0;
+
+ // if only the search order's are different
+ supplemental_order = CFDictionaryGetValue(supplemental_resolver, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(supplemental_order) ||
+ !CFNumberGetValue(supplemental_order, kCFNumberIntType, &supplemental_order_val)) {
+ supplemental_order_val = 0;
+ }
+
+ if (match_order_val < supplemental_order_val ) {
+ // if we should prefer this match resolver, else just skip it
+ CFArraySetValueAtIndex(supplemental, j, match_resolver);
+ }
+
+ CFRelease(match_resolver);
+ match_resolver = NULL;
+ break;
+ }
+ }
+
+ if (match_resolver != NULL) {
+ CFArrayAppendValue(supplemental, match_resolver);
+ CFRelease(match_resolver);
+ }
+ }
+
+ return;
+}
+
+
+static void
+add_predefined_resolvers(CFMutableArrayRef supplemental)
+{
+ CFIndex i;
+ CFIndex n;
+
+ if (S_predefined == NULL) {
+ return;
+ }
+
+ n = CFArrayGetCount(S_predefined);
+ for (i = 0; i < n; i++) {
+ uint32_t defaultOrder;
+ CFDictionaryRef dns;
+
+ dns = CFArrayGetValueAtIndex(S_predefined, i);
+ if (!isA_CFDictionary(dns)) {
+ continue;
+ }
+
+ defaultOrder = DEFAULT_SEARCH_ORDER +
+ (DEFAULT_SEARCH_ORDER / 2) +
+ ((DEFAULT_SEARCH_ORDER / 1000) * i);
+ add_supplemental(supplemental, dns, defaultOrder);
+ }
+
+ return;
+}
+
+
+#define N_QUICK 32
+
+
+static void
+add_supplemental_resolvers(CFMutableArrayRef supplemental, CFDictionaryRef services, CFArrayRef service_order)
+{
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+ CFIndex i;
+ CFIndex n_order;
+ CFIndex n_services;
+ const void * vals_q[N_QUICK];
+ const void ** vals = vals_q;
+
+ n_services = isA_CFDictionary(services) ? CFDictionaryGetCount(services) : 0;
+ if (n_services == 0) {
+ return; // if no services
+ }
+
+ if (n_services > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n_services * sizeof(CFTypeRef), 0);
+ vals = CFAllocatorAllocate(NULL, n_services * sizeof(CFTypeRef), 0);
+ }
+
+ n_order = isA_CFArray(service_order) ? CFArrayGetCount(service_order) : 0;
+
+ CFDictionaryGetKeysAndValues(services, keys, vals);
+ for (i = 0; i < n_services; i++) {
+ uint32_t defaultOrder;
+ CFDictionaryRef dns;
+ CFDictionaryRef service = (CFDictionaryRef)vals[i];
+
+ if (!isA_CFDictionary(service)) {
+ continue;
+ }
+
+ dns = CFDictionaryGetValue(service, kSCEntNetDNS);
+ if (!isA_CFDictionary(dns)) {
+ continue;
+ }
+
+ defaultOrder = DEFAULT_SEARCH_ORDER -
+ (DEFAULT_SEARCH_ORDER / 2) +
+ ((DEFAULT_SEARCH_ORDER / 1000) * i);
+ if ((n_order > 0) &&
+ !CFArrayContainsValue(service_order, CFRangeMake(0, n_order), keys[i])) {
+ // push out services not specified in service order
+ defaultOrder += (DEFAULT_SEARCH_ORDER / 1000) * n_services;
+ }
+
+ add_supplemental(supplemental, dns, defaultOrder);
+ }
+
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ CFAllocatorDeallocate(NULL, vals);
+ }
+
+ return;
+}
+
+
+static CFComparisonResult
+compareBySearchOrder(const void *val1, const void *val2, void *context)
+{
+ CFDictionaryRef dns1 = (CFDictionaryRef)val1;
+ CFDictionaryRef dns2 = (CFDictionaryRef)val2;
+ CFNumberRef num;
+ uint32_t order1 = DEFAULT_SEARCH_ORDER;
+ uint32_t order2 = DEFAULT_SEARCH_ORDER;
+
+ num = CFDictionaryGetValue(dns1, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &order1)) {
+ order1 = DEFAULT_SEARCH_ORDER;
+ }
+
+ num = CFDictionaryGetValue(dns2, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &order2)) {
+ order2 = DEFAULT_SEARCH_ORDER;
+ }
+
+ if (order1 == order2) {
+ return kCFCompareEqualTo;
+ }
+
+ return (order1 < order2) ? kCFCompareLessThan : kCFCompareGreaterThan;
+}
+
+
+static void
+update_search_domains(CFMutableDictionaryRef *defaultDomain, CFArrayRef supplemental)
+{
+ CFStringRef defaultDomainName = NULL;
+ uint32_t defaultOrder = DEFAULT_SEARCH_ORDER;
+ CFArrayRef defaultSearchDomains = NULL;
+ CFIndex defaultSearchIndex = 0;
+ CFIndex i;
+ CFIndex n;
+ CFMutableArrayRef mySearchDomains;
+ CFMutableArrayRef mySupplemental = (CFMutableArrayRef)supplemental;
+ Boolean searchDomainAdded = FALSE;
+
+ n = CFArrayGetCount(supplemental);
+ if (n == 0) {
+ // if no supplemental domains
+ return;
+ }
+
+ if (*defaultDomain != NULL) {
+ CFNumberRef num;
+
+ num = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &defaultOrder)) {
+ defaultOrder = DEFAULT_SEARCH_ORDER;
+ }
+
+ defaultDomainName = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSDomainName);
+ defaultSearchDomains = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSSearchDomains);
+ }
+
+ if (isA_CFArray(defaultSearchDomains)) {
+ mySearchDomains = CFArrayCreateMutableCopy(NULL, 0, defaultSearchDomains);
+ } else {
+ mySearchDomains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (isA_CFString(defaultDomainName)) {
+ char *domain;
+ int domain_parts = 1;
+ char *dp;
+
+ domain = _SC_cfstring_to_cstring(defaultDomainName,
+ NULL,
+ 0,
+ kCFStringEncodingUTF8);
+
+ for (dp = domain; *dp != '\0'; dp++) {
+ if (*dp == '.') {
+ domain_parts++;
+ }
+ }
+
+ dp = domain;
+ for (i = LOCALDOMAINPARTS; i <= domain_parts; i++) {
+ CFStringRef searchDomain;
+
+ searchDomain = CFStringCreateWithCString(NULL,
+ dp,
+ kCFStringEncodingUTF8);
+ CFArrayAppendValue(mySearchDomains, searchDomain);
+ CFRelease(searchDomain);
+
+ dp = strchr(dp, '.') + 1;
+ }
+
+ CFAllocatorDeallocate(NULL, domain);
+ }
+ }
+
+ if (n > 1) {
+ mySupplemental = CFArrayCreateMutableCopy(NULL, 0, supplemental);
+ CFArraySortValues(mySupplemental,
+ CFRangeMake(0, n),
+ compareBySearchOrder,
+ NULL);
+ }
+
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dns;
+ CFNumberRef num;
+ CFStringRef supplementalDomain;
+ uint32_t supplementalOrder;
+
+ dns = CFArrayGetValueAtIndex(mySupplemental, i);
+
+ supplementalDomain = CFDictionaryGetValue(dns, kSCPropNetDNSDomainName);
+ if (CFArrayContainsValue(mySearchDomains,
+ CFRangeMake(0, CFArrayGetCount(mySearchDomains)),
+ supplementalDomain)) {
+ // if supplemental domain is already in the search list
+ continue;
+ }
+
+ num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &supplementalOrder)) {
+ supplementalOrder = DEFAULT_SEARCH_ORDER;
+ }
+
+ if (supplementalOrder < defaultOrder) {
+ CFArrayInsertValueAtIndex(mySearchDomains,
+ defaultSearchIndex,
+ supplementalDomain);
+ defaultSearchIndex++;
+ } else {
+ CFArrayAppendValue(mySearchDomains, supplementalDomain);
+ }
+
+ searchDomainAdded = TRUE;
+ }
+
+ if (searchDomainAdded) {
+ if (*defaultDomain == NULL) {
+ *defaultDomain = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ CFDictionarySetValue(*defaultDomain, kSCPropNetDNSSearchDomains, mySearchDomains);
+ }
+
+ CFRelease(mySearchDomains);
+ if (mySupplemental != supplemental) CFRelease(mySupplemental);
+ return;
+}
+
+
+static dns_create_resolver_t
+create_resolver(CFDictionaryRef dns)
+{
+ CFArrayRef list;
+ CFNumberRef num;
+ dns_create_resolver_t _resolver;
+ CFStringRef str;
+
+ _resolver = _dns_resolver_create();
+
+ // process domain
+ str = CFDictionaryGetValue(dns, kSCPropNetDNSDomainName);
+ if (isA_CFString(str)) {
+ char domain[NS_MAXDNAME];
+
+ if (_SC_cfstring_to_cstring(str, domain, sizeof(domain), kCFStringEncodingUTF8) != NULL) {
+ _dns_resolver_set_domain(&_resolver, domain);
+ }
+ }
+
+ // process search domains
+ list = CFDictionaryGetValue(dns, kSCPropNetDNSSearchDomains);
+ if (isA_CFArray(list)) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(list);
+
+ // add "search" domains
+ for (i = 0; i < n; i++) {
+ str = CFArrayGetValueAtIndex(list, i);
+ if (isA_CFString(str)) {
+ char search[NS_MAXDNAME];
+
+ if (_SC_cfstring_to_cstring(str, search, sizeof(search), kCFStringEncodingUTF8) != NULL) {
+ _dns_resolver_add_search(&_resolver, search);
+ }
+ }
+ }
+ }
+
+ // process nameserver addresses
+ list = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
+ if (isA_CFArray(list)) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(list);
+
+ for (i = 0; i < n; i++) {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } addr;
+ char buf[128];
+
+ str = CFArrayGetValueAtIndex(list, i);
+ if (!isA_CFString(str)) {
+ continue;
+ }
+
+ if (_SC_cfstring_to_cstring(str, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
+ continue;
+ }
+
+ bzero(&addr, sizeof(addr));
+ if (inet_aton(buf, &addr.sin.sin_addr) == 1) {
+ /* if IPv4 address */
+ addr.sin.sin_len = sizeof(addr.sin);
+ addr.sin.sin_family = AF_INET;
+ _dns_resolver_add_nameserver(&_resolver, &addr.sa);
+ } else if (inet_pton(AF_INET6, buf, &addr.sin6.sin6_addr) == 1) {
+ /* if IPv6 address */
+ char *p;
+
+ p = strchr(buf, '%');
+ if (p != NULL) {
+ addr.sin6.sin6_scope_id = if_nametoindex(p+1);
+ }
+
+ addr.sin6.sin6_len = sizeof(addr.sin6);
+ addr.sin6.sin6_family = AF_INET6;
+ _dns_resolver_add_nameserver(&_resolver, &addr.sa);
+ } else {
+ continue;
+ }
+ }
+ }
+
+ // process search order
+ num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
+ if (isA_CFNumber(num)) {
+ uint32_t order;
+
+ if (CFNumberGetValue(num, kCFNumberIntType, &order)) {
+ _dns_resolver_set_order(&_resolver, order);
+ }
+ }
+
+ // process port
+ num = CFDictionaryGetValue(dns, kSCPropNetDNSServerPort);
+ if (isA_CFNumber(num)) {
+ int port;
+
+ if (CFNumberGetValue(num, kCFNumberIntType, &port)) {
+ _dns_resolver_set_port(&_resolver, (uint16_t)port);
+ }
+ }
+
+ // process timeout
+ num = CFDictionaryGetValue(dns, kSCPropNetDNSServerTimeout);
+ if (isA_CFNumber(num)) {
+ int timeout;
+
+ if (CFNumberGetValue(num, kCFNumberIntType, &timeout)) {
+ _dns_resolver_set_timeout(&_resolver, (uint32_t)timeout);
+ }
+ }
+
+ // process options
+ str = CFDictionaryGetValue(dns, kSCPropNetDNSOptions);
+ if (isA_CFString(str)) {
+ char *options;
+
+ options = _SC_cfstring_to_cstring(str, NULL, 0, kCFStringEncodingUTF8);
+ if (options != NULL) {
+ _dns_resolver_set_options(&_resolver, options);
+ CFAllocatorDeallocate(NULL, options);
+ }
+ }
+
+ return _resolver;
+}
+
+
+__private_extern__
+void
+dns_configuration_set(CFDictionaryRef defaultResolver,
+ CFDictionaryRef services,
+ CFArrayRef serviceOrder)
+{
+ CFIndex i;
+ CFMutableDictionaryRef myDefault;
+ CFStringRef myDomain = NULL;
+ uint32_t myOrder = DEFAULT_SEARCH_ORDER;
+ Boolean myOrderAdded = FALSE;
+ CFIndex n_supplemental;
+ CFNumberRef order;
+ dns_create_resolver_t resolver;
+ CFArrayRef search;
+ CFMutableArrayRef supplemental;
+
+ if (defaultResolver == NULL) {
+ myDefault = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ } else {
+ myDefault = CFDictionaryCreateMutableCopy(NULL, 0, defaultResolver);
+
+ // ensure that the default resolver has a search order
+
+ order = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchOrder);
+ if (!isA_CFNumber(order) ||
+ !CFNumberGetValue(order, kCFNumberIntType, &myOrder)) {
+ myOrderAdded = TRUE;
+ myOrder = DEFAULT_SEARCH_ORDER;
+ order = CFNumberCreate(NULL, kCFNumberIntType, &myOrder);
+ CFDictionarySetValue(myDefault, kSCPropNetDNSSearchOrder, order);
+ CFRelease(order);
+ }
+ }
+
+ // establish list of supplemental resolvers
+
+ supplemental = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ // identify search[] list and/or domain name
+
+ search = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchDomains);
+ if (isA_CFArray(search) && (CFArrayGetCount(search) > 0)) {
+ myDomain = CFArrayGetValueAtIndex(search, 0);
+ myDomain = isA_CFString(myDomain);
+ }
+
+ if (myDomain == NULL) {
+ myDomain = CFDictionaryGetValue(myDefault, kSCPropNetDNSDomainName);
+ myDomain = isA_CFString(myDomain);
+ }
+
+ // add match for default domain
+
+ if (myDomain != NULL) {
+ CFMutableDictionaryRef mySupplemental;
+
+ mySupplemental = CFDictionaryCreateMutableCopy(NULL, 0, myDefault);
+ CFDictionarySetValue (mySupplemental, kSCPropNetDNSDomainName, myDomain);
+ CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSearchDomains);
+ CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSupplementalMatchDomains);
+ CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSupplementalMatchOrders);
+ CFArrayAppendValue(supplemental, mySupplemental);
+ CFRelease(mySupplemental);
+ }
+
+ // collect (and add) any supplemental resolver configurations
+
+ add_supplemental_resolvers(supplemental, services, serviceOrder);
+
+ // update the "search" list
+
+ update_search_domains(&myDefault, supplemental);
+
+ // add any pre-defined resolver configurations
+
+ add_predefined_resolvers(supplemental);
+
+ // check if the "match for default domain" (above) is really needed
+
+ if (myDomain != NULL) {
+ Boolean sharedDomain = FALSE;
+
+ n_supplemental = CFArrayGetCount(supplemental);
+ for (i = 1; i < n_supplemental; i++) {
+ CFStringRef domain;
+ CFDictionaryRef mySupplemental;
+
+ mySupplemental = CFArrayGetValueAtIndex(supplemental, i);
+ domain = CFDictionaryGetValue(mySupplemental, kSCPropNetDNSDomainName);
+ if (isA_CFString(domain)) {
+ if (CFEqual(myDomain, domain)) {
+ sharedDomain = TRUE;
+ break;
+ }
+
+ if (CFStringHasSuffix(myDomain, domain)) {
+ CFIndex dotIndex;
+
+ dotIndex = CFStringGetLength(myDomain) - CFStringGetLength(domain) - 1;
+ if (dotIndex > 0) {
+ UniChar dot;
+
+ dot = CFStringGetCharacterAtIndex(myDomain, dotIndex);
+ if (dot == (UniChar)'.') {
+ sharedDomain = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!sharedDomain) {
+ // if the default resolver domain name is not shared
+ CFArrayRemoveValueAtIndex(supplemental, 0);
+ }
+ }
+
+ // establish resolver configuration
+
+ n_supplemental = CFArrayGetCount(supplemental);
+ if ((defaultResolver == NULL) && (n_supplemental == 0)) {
+ /*
+ * if no default or supplemental resolvers
+ */
+ if (!_dns_configuration_store(NULL)) {
+ SCLog(TRUE, LOG_ERR, CFSTR("set_dns_configuration: could not store configuration"));
+ }
+ } else {
+ dns_create_config_t _config;
+
+ /*
+ * if default and/or supplemental resolvers are defined
+ */
+ _config = _dns_configuration_create();
+
+ // add [default] resolver
+
+ if ((n_supplemental == 0) && myOrderAdded) {
+ CFDictionaryRemoveValue(myDefault, kSCPropNetDNSSearchOrder);
+ }
+ resolver = create_resolver(myDefault);
+ _dns_configuration_add_resolver(&_config, resolver);
+ _dns_resolver_free(&resolver);
+
+ // add [supplemental] resolvers
+
+ for (i = 0; i < n_supplemental; i++) {
+ CFDictionaryRef supplementalResolver;
+
+ supplementalResolver = CFArrayGetValueAtIndex(supplemental, i);
+ resolver = create_resolver(supplementalResolver);
+ _dns_configuration_add_resolver(&_config, resolver);
+ _dns_resolver_free(&resolver);
+ }
+
+ // save configuration
+
+ if (!_dns_configuration_store(&_config)) {
+ SCLog(TRUE, LOG_ERR, CFSTR("set_dns_configuration() failed: could not store configuration"));
+ }
+
+ _dns_configuration_free(&_config);
+ }
+
+ CFRelease(myDefault);
+ CFRelease(supplemental);
+
+ return;
+}
+
+
+static void
+load_predefined_resolvers(CFBundleRef bundle)
+{
+ Boolean ok;
+ CFURLRef url;
+ CFStringRef xmlError = NULL;
+ CFDataRef xmlResolvers = NULL;
+
+ url = CFBundleCopyResourceURL(bundle, CFSTR("Resolvers"), CFSTR("plist"), NULL);
+ if (url == NULL) {
+ return;
+ }
+
+ ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlResolvers, NULL, NULL, NULL);
+ CFRelease(url);
+ if (!ok || (xmlResolvers == NULL)) {
+ return;
+ }
+
+ /* convert the XML data into a property list */
+ S_predefined = CFPropertyListCreateFromXMLData(NULL, xmlResolvers, kCFPropertyListImmutable, &xmlError);
+ CFRelease(xmlResolvers);
+ if (S_predefined == NULL) {
+ if (xmlError != NULL) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("add_predefined_resolvers: %@"), xmlError);
+ CFRelease(xmlError);
+ }
+ return;
+ }
+
+ if (!isA_CFArray(S_predefined)) {
+ CFRelease(S_predefined);
+ S_predefined = NULL;
+ return;
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+dns_configuration_init(CFBundleRef bundle)
+{
+ load_predefined_resolvers(bundle);
+ return;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2000-2004 Apple Computer, 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@
+ */
+
+/*
+ * ip_plugin.c
+ * - decides which interface will be made the "primary" interface,
+ * that is, the one with the default route assigned
+ */
+
+/*
+ * Modification History
+ *
+ * July 19, 2000 Dieter Siegmund (dieter@apple.com)
+ * - initial revision
+ *
+ * November 15, 2000 Dieter Siegmund (dieter@apple.com)
+ * - changed to use new configuration model
+ *
+ * March 19, 2001 Dieter Siegmund (dieter@apple.com)
+ * - use service state instead of interface state
+ *
+ * July 16, 2001 Allan Nathanson (ajn@apple.com)
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * August 28, 2001 Dieter Siegmund (dieter@apple.com)
+ * - specify the interface name when installing the default route
+ * - this ensures that default traffic goes to the highest priority
+ * service when multiple interfaces are configured to be on the same subnet
+ *
+ * September 16, 2002 Dieter Siegmund (dieter@apple.com)
+ * - don't elect a link-local service to be primary unless it's the only
+ * one that's available
+ *
+ * July 16, 2003 Dieter Siegmund (dieter@apple.com)
+ * - modifications to support IPv6
+ * - don't elect a service to be primary if it doesn't have a default route
+ *
+ * July 29, 2003 Dieter Siegmund (dieter@apple.com)
+ * - support installing a default route to a router that's not on our subnet
+ *
+ * March 22, 2004 Allan Nathanson (ajn@apple.com)
+ * - create expanded DNS configuration
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/sysctl.h>
+#include <limits.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h> /* for SCLog() */
+
+#include <dnsinfo.h>
+
+void load_hostname(Boolean verbose);
+void dns_configuration_init(CFBundleRef bundle);
+void dns_configuration_set(CFDictionaryRef defaultResolver,
+ CFDictionaryRef services,
+ CFArrayRef serviceOrder);
+
+#define IP_FORMAT "%d.%d.%d.%d"
+#define IP_CH(ip) ((u_char *)(ip))
+#define IP_LIST(ip) IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
+
+/* debug output on/off */
+static boolean_t S_IPMonitor_debug = FALSE;
+
+/* are we netbooted? If so, don't touch the default route */
+static boolean_t S_netboot = FALSE;
+
+/* notification key indicating dns configuration has been changed */
+static CFStringRef S_notify_dnsinfo = NULL;
+
+/* dictionary to hold per-service state: key is the serviceID */
+static CFMutableDictionaryRef S_service_state_dict = NULL;
+
+/* if set, a PPP interface overrides the primary */
+static boolean_t S_ppp_override_primary = TRUE;
+
+/* the current primary serviceID's */
+static CFStringRef S_primary_ipv4 = NULL;
+static CFStringRef S_primary_ipv6 = NULL;
+static CFStringRef S_primary_dns = NULL;
+static CFStringRef S_primary_proxies = NULL;
+
+static CFStringRef S_state_global_ipv4 = NULL;
+static CFStringRef S_state_global_ipv6 = NULL;
+static CFStringRef S_state_global_dns = NULL;
+static CFStringRef S_state_global_netinfo = NULL;
+static CFStringRef S_state_global_proxies = NULL;
+static CFStringRef S_state_service_prefix = NULL;
+static CFStringRef S_setup_global_ipv4 = NULL;
+static CFStringRef S_setup_global_netinfo = NULL;
+static CFStringRef S_setup_global_proxies = NULL;
+static CFStringRef S_setup_service_prefix = NULL;
+
+static struct in_addr S_router_subnet = { 0 };
+static struct in_addr S_router_subnet_mask = { 0 };
+
+static const struct in_addr S_ip_zeros = { 0 };
+static const struct in6_addr S_ip6_zeros = IN6ADDR_ANY_INIT;
+
+
+#define kRouterNeedsLocalIP CFSTR("com.apple.IPMonitor.RouterNeedsLocalIP")
+#define kRouterIsDirect CFSTR("com.apple.IPMonitor.IsDirect")
+
+#define VAR_RUN_RESOLV_CONF "/var/run/resolv.conf"
+#define VAR_RUN_NICONFIG_LOCAL_XML "/var/run/niconfig_local.xml"
+
+#ifndef KERN_NETBOOT
+#define KERN_NETBOOT 40 /* int: are we netbooted? 1=yes,0=no */
+#endif KERN_NETBOOT
+
+/**
+ ** entityType*, GetEntityChanges*
+ ** - definitions for the entity types we handle
+ **/
+#define ENTITY_TYPES_COUNT 5
+enum {
+ kEntityTypeIPv4 = 0,
+ kEntityTypeIPv6 = 1,
+ kEntityTypeDNS = 2,
+ kEntityTypeNetInfo = 3,
+ kEntityTypeProxies = 4,
+};
+typedef uint32_t EntityType;
+
+static CFStringRef entityTypeNames[ENTITY_TYPES_COUNT];
+
+typedef boolean_t (GetEntityChangesFunc)(CFStringRef serviceID,
+ CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict,
+ CFDictionaryRef info);
+typedef GetEntityChangesFunc * GetEntityChangesFuncRef;
+
+static GetEntityChangesFunc get_ipv4_changes;
+static GetEntityChangesFunc get_ipv6_changes;
+static GetEntityChangesFunc get_dns_changes;
+static GetEntityChangesFunc get_netinfo_changes;
+static GetEntityChangesFunc get_proxies_changes;
+
+static void
+my_CFRelease(void * t);
+
+static void
+my_CFArrayAppendUniqueValue(CFMutableArrayRef arr, CFTypeRef new);
+
+static void
+my_CFArrayRemoveValue(CFMutableArrayRef arr, CFStringRef key);
+
+static GetEntityChangesFuncRef entityChangeFunc[ENTITY_TYPES_COUNT] = {
+ get_ipv4_changes, /* 0 */
+ get_ipv6_changes, /* 1 */
+ get_dns_changes, /* 2 */
+ get_netinfo_changes,/* 3 */
+ get_proxies_changes,/* 4 */
+};
+
+/**
+ ** keyChangeList
+ ** - mechanism to do an atomic update of the SCDynamicStore
+ ** when the content needs to be changed across multiple functions
+ **/
+typedef struct {
+ CFMutableArrayRef notify;
+ CFMutableArrayRef remove;
+ CFMutableDictionaryRef set;
+} keyChangeList, * keyChangeListRef;
+
+static void
+keyChangeListInit(keyChangeListRef keys)
+{
+ keys->notify = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ keys->remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ keys->set = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ return;
+}
+
+static void
+keyChangeListFree(keyChangeListRef keys)
+{
+ my_CFRelease(&keys->notify);
+ my_CFRelease(&keys->remove);
+ my_CFRelease(&keys->set);
+ return;
+}
+
+static void
+keyChangeListNotifyKey(keyChangeListRef keys, CFStringRef key)
+{
+ my_CFArrayAppendUniqueValue(keys->notify, key);
+ return;
+}
+
+static void
+keyChangeListRemoveValue(keyChangeListRef keys, CFStringRef key)
+{
+ my_CFArrayAppendUniqueValue(keys->remove, key);
+ CFDictionaryRemoveValue(keys->set, key);
+ return;
+}
+
+static void
+keyChangeListSetValue(keyChangeListRef keys, CFStringRef key, CFTypeRef value)
+{
+ my_CFArrayRemoveValue(keys->remove, key);
+ CFDictionarySetValue(keys->set, key, value);
+ return;
+}
+
+static void
+keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session)
+{
+ CFArrayRef notify = keys->notify;
+ CFArrayRef remove = keys->remove;
+ CFDictionaryRef set = keys->set;
+
+ if (CFArrayGetCount(notify) == 0) {
+ notify = NULL;
+ }
+ if (CFArrayGetCount(remove) == 0) {
+ remove = NULL;
+ }
+ if (CFDictionaryGetCount(set) == 0) {
+ set = NULL;
+ }
+ if (set == NULL && remove == NULL && notify == NULL) {
+ return;
+ }
+ if (S_IPMonitor_debug) {
+ if (set != NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: Setting:\n%@\n"), set);
+ }
+ if (remove != NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: Removing:\n%@\n"), remove);
+ }
+ if (notify != NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: Notifying:\n%@\n"), notify);
+ }
+ }
+ (void)SCDynamicStoreSetMultiple(session, set, remove, notify);
+ return;
+}
+
+static boolean_t
+S_netboot_root()
+{
+ int mib[2];
+ size_t len;
+ int netboot = 0;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_NETBOOT;
+ len = sizeof(netboot);
+ sysctl(mib, 2, &netboot, &len, NULL, 0);
+ return (netboot);
+}
+
+static void
+my_CFArrayAppendUniqueValue(CFMutableArrayRef arr, CFTypeRef new)
+{
+ CFIndex n = CFArrayGetCount(arr);
+
+ if (CFArrayContainsValue(arr, CFRangeMake(0, n), new)) {
+ return;
+ }
+ CFArrayAppendValue(arr, new);
+ return;
+}
+
+static void
+my_CFArrayRemoveValue(CFMutableArrayRef arr, CFStringRef key)
+{
+ CFIndex i;
+
+ i = CFArrayGetFirstIndexOfValue(arr,
+ CFRangeMake(0, CFArrayGetCount(arr)),
+ key);
+ if (i != kCFNotFound) {
+ CFArrayRemoveValueAtIndex(arr, i);
+ }
+ return;
+}
+
+static void
+my_CFRelease(void * t)
+{
+ void * * obj = (void * *)t;
+
+ if (obj && *obj) {
+ CFRelease(*obj);
+ *obj = NULL;
+ }
+ return;
+}
+
+static CFDictionaryRef
+my_CFDictionaryGetDictionary(CFDictionaryRef dict, CFStringRef key)
+{
+ if (isA_CFDictionary(dict) == NULL) {
+ return (NULL);
+ }
+ return (isA_CFDictionary(CFDictionaryGetValue(dict, key)));
+}
+
+static CFDictionaryRef
+my_SCDCopy(SCDynamicStoreRef session, CFStringRef key)
+{
+ CFDictionaryRef dict;
+
+ dict = SCDynamicStoreCopyValue(session, key);
+ if (isA_CFDictionary(dict) == NULL) {
+ my_CFRelease(&dict);
+ }
+ return dict;
+}
+
+static boolean_t
+cfstring_to_ipvx(int family, CFStringRef str, void * addr, int addr_size)
+{
+ char buf[128];
+
+ if (isA_CFString(str) == NULL) {
+ goto done;
+ }
+
+ switch (family) {
+ case AF_INET:
+ if (addr_size < sizeof(struct in_addr)) {
+ goto done;
+ }
+ break;
+ case AF_INET6:
+ if (addr_size < sizeof(struct in6_addr)) {
+ goto done;
+ }
+ break;
+ default:
+ goto done;
+ }
+ (void)_SC_cfstring_to_cstring(str, buf, sizeof(buf), kCFStringEncodingASCII);
+ if (inet_pton(family, buf, addr) == 1) {
+ return (TRUE);
+ }
+ done:
+ bzero(addr, addr_size);
+ return (FALSE);
+}
+
+static boolean_t
+cfstring_to_ip(CFStringRef str, struct in_addr * ip_p)
+{
+ return (cfstring_to_ipvx(AF_INET, str, ip_p, sizeof(*ip_p)));
+}
+
+static boolean_t
+cfstring_to_ip6(CFStringRef str, struct in6_addr * ip6_p)
+{
+ return (cfstring_to_ipvx(AF_INET6, str, ip6_p, sizeof(*ip6_p)));
+}
+
+/*
+ * Function: parse_component
+ * Purpose:
+ * Given a string 'key' and a string prefix 'prefix',
+ * return the next component in the slash '/' separated
+ * key.
+ *
+ * Examples:
+ * 1. key = "a/b/c" prefix = "a/"
+ * returns "b"
+ * 2. key = "a/b/c" prefix = "a/b/"
+ * returns "c"
+ */
+static CFStringRef
+parse_component(CFStringRef key, CFStringRef prefix)
+{
+ CFMutableStringRef comp;
+ CFRange range;
+
+ if (CFStringHasPrefix(key, prefix) == FALSE) {
+ return (NULL);
+ }
+ comp = CFStringCreateMutableCopy(NULL, 0, key);
+ if (comp == NULL) {
+ return (NULL);
+ }
+ CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
+ range = CFStringFind(comp, CFSTR("/"), 0);
+ if (range.location == kCFNotFound) {
+ return (comp);
+ }
+ range.length = CFStringGetLength(comp) - range.location;
+ CFStringDelete(comp, range);
+ return (comp);
+}
+
+static void
+append_netinfo_arrays(CFDictionaryRef dict, CFMutableArrayRef ni_addrs,
+ CFMutableArrayRef ni_tags)
+{
+ CFArrayRef addrs;
+ CFArrayRef tags;
+
+ if (isA_CFDictionary(dict) == NULL)
+ return;
+
+ addrs = isA_CFArray(CFDictionaryGetValue(dict, kSCPropNetNetInfoServerAddresses));
+ tags = isA_CFArray(CFDictionaryGetValue(dict, kSCPropNetNetInfoServerTags));
+ if (addrs && tags) {
+ CFIndex addrs_count = CFArrayGetCount(addrs);
+ CFIndex tags_count = CFArrayGetCount(tags);
+
+ if (addrs_count > 0) {
+ if (addrs_count == tags_count) {
+ CFArrayAppendArray(ni_addrs, addrs,
+ CFRangeMake(0, addrs_count));
+ CFArrayAppendArray(ni_tags, tags,
+ CFRangeMake(0, tags_count));
+ }
+
+ }
+
+ }
+ return;
+}
+
+static void
+append_netinfo_broadcast_addresses(CFDictionaryRef netinfo_dict,
+ CFDictionaryRef ipv4_dict,
+ CFMutableArrayRef ni_addrs,
+ CFMutableArrayRef ni_tags)
+{
+ CFArrayRef addrs;
+ CFIndex addrs_count;
+ CFIndex i;
+ CFArrayRef masks;
+ CFIndex masks_count;
+ CFStringRef tag;
+
+ tag = CFDictionaryGetValue(netinfo_dict,
+ kSCPropNetNetInfoBroadcastServerTag);
+ tag = isA_CFString(tag);
+ if (tag == NULL) {
+ tag = kSCValNetNetInfoDefaultServerTag;
+ }
+ addrs = isA_CFArray(CFDictionaryGetValue(ipv4_dict,
+ kSCPropNetIPv4Addresses));
+ masks = isA_CFArray(CFDictionaryGetValue(ipv4_dict,
+ kSCPropNetIPv4SubnetMasks));
+ if (addrs == NULL || masks == NULL) {
+ return;
+ }
+ masks_count = CFArrayGetCount(masks);
+ addrs_count = CFArrayGetCount(addrs);
+ if (addrs_count != masks_count) {
+ return;
+ }
+
+ for (i = 0; i < addrs_count; i++) {
+ struct in_addr addr;
+ CFStringRef broadcast = NULL;
+ struct in_addr mask;
+
+ if (cfstring_to_ip(CFArrayGetValueAtIndex(addrs, i), &addr)
+ && cfstring_to_ip(CFArrayGetValueAtIndex(masks, i), &mask)) {
+ struct in_addr b;
+
+ b.s_addr = htonl(ntohl(addr.s_addr) | ~ntohl(mask.s_addr));
+ broadcast = CFStringCreateWithFormat(NULL, NULL,
+ CFSTR(IP_FORMAT),
+ IP_LIST(&b));
+ CFArrayAppendValue(ni_addrs, broadcast);
+ CFArrayAppendValue(ni_tags, tag);
+ my_CFRelease(&broadcast);
+ }
+ }
+ return;
+}
+
+static CFDictionaryRef
+make_netinfo_dict(CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict,
+ CFDictionaryRef ipv4_dict)
+{
+ boolean_t has_manual = FALSE;
+ boolean_t has_broadcast = FALSE;
+ boolean_t has_dhcp = FALSE;
+ CFIndex i;
+ CFArrayRef m = NULL;
+ CFIndex n;
+ CFMutableArrayRef ni_addrs = NULL;
+ CFMutableDictionaryRef ni_dict = NULL;
+ CFMutableArrayRef ni_tags = NULL;
+
+ if (setup_dict == NULL || ipv4_dict == NULL) {
+ goto netinfo_done;
+ }
+ m = isA_CFArray(CFDictionaryGetValue(setup_dict,
+ kSCPropNetNetInfoBindingMethods));
+ if (m == NULL) {
+ goto netinfo_done;
+ }
+ ni_addrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ ni_tags = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ /* find out which are configured */
+ n = CFArrayGetCount(m);
+ for (i = 0; i < n; i++) {
+ CFStringRef method = CFArrayGetValueAtIndex(m, i);
+
+ if (CFEqual(method,
+ kSCValNetNetInfoBindingMethodsManual)) {
+ has_manual = TRUE;
+ }
+ else if (CFEqual(method,
+ kSCValNetNetInfoBindingMethodsDHCP)) {
+ has_dhcp = TRUE;
+ }
+ else if (CFEqual(method,
+ kSCValNetNetInfoBindingMethodsBroadcast)) {
+ has_broadcast = TRUE;
+ }
+ }
+ if (has_dhcp && state_dict != NULL) {
+ append_netinfo_arrays(state_dict, ni_addrs, ni_tags);
+ }
+ if (has_manual) {
+ append_netinfo_arrays(setup_dict, ni_addrs, ni_tags);
+ }
+ if (has_broadcast) {
+ append_netinfo_broadcast_addresses(setup_dict, ipv4_dict,
+ ni_addrs, ni_tags);
+ }
+ if (CFArrayGetCount(ni_addrs) == 0) {
+ goto netinfo_done;
+ }
+ ni_dict = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(ni_dict, kSCPropNetNetInfoServerAddresses,
+ ni_addrs);
+ CFDictionarySetValue(ni_dict, kSCPropNetNetInfoServerTags,
+ ni_tags);
+ netinfo_done:
+ my_CFRelease(&ni_addrs);
+ my_CFRelease(&ni_tags);
+ return (ni_dict);
+}
+
+static CFMutableDictionaryRef
+service_dict_copy(CFStringRef serviceID)
+{
+ CFDictionaryRef d = NULL;
+ CFMutableDictionaryRef service_dict;
+
+ /* create a modifyable dictionary, a copy or a new one */
+ d = CFDictionaryGetValue(S_service_state_dict, serviceID);
+ if (d == NULL) {
+ service_dict
+ = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ else {
+ service_dict = CFDictionaryCreateMutableCopy(NULL, 0, d);
+ }
+ return (service_dict);
+}
+
+static boolean_t
+service_dict_set(CFStringRef serviceID, CFStringRef entity,
+ CFDictionaryRef new_dict)
+{
+ boolean_t changed = FALSE;
+ CFDictionaryRef old;
+ CFMutableDictionaryRef service_dict;
+
+ service_dict = service_dict_copy(serviceID);
+ old = CFDictionaryGetValue(service_dict, entity);
+ if (new_dict == NULL) {
+ if (old != NULL) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: serviceID %@ removed %@ dictionary = %@"),
+ serviceID, entity, old);
+ CFDictionaryRemoveValue(service_dict, entity);
+ changed = TRUE;
+ }
+ }
+ else {
+ if (old == NULL || CFEqual(new_dict, old) == FALSE) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: serviceID %@ changed %@"
+ " dictionary\nold %@\nnew %@"), serviceID, entity,
+ (old != NULL) ? (CFTypeRef)old : (CFTypeRef)CFSTR("<none>"),
+ new_dict);
+ CFDictionarySetValue(service_dict, entity, new_dict);
+ changed = TRUE;
+ }
+ }
+ if (CFDictionaryGetCount(service_dict) == 0) {
+ CFDictionaryRemoveValue(S_service_state_dict, serviceID);
+ }
+ else {
+ CFDictionarySetValue(S_service_state_dict, serviceID, service_dict);
+ }
+ my_CFRelease(&service_dict);
+ return (changed);
+}
+
+static CFDictionaryRef
+service_dict_get(CFStringRef serviceID, CFStringRef entity)
+{
+ CFDictionaryRef service_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, serviceID);
+ if (service_dict == NULL) {
+ return (NULL);
+ }
+ return (CFDictionaryGetValue(service_dict, entity));
+}
+
+/**
+ ** GetEntityChangesFunc functions
+ **/
+static __inline__ struct in_addr
+subnet_addr(struct in_addr addr, struct in_addr mask)
+{
+ struct in_addr net;
+
+ net.s_addr = htonl((uint32_t)ntohl(addr.s_addr)
+ & (uint32_t)ntohl(mask.s_addr));
+ return (net);
+}
+
+static boolean_t
+get_ipv4_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+ struct in_addr addr = { 0 };
+ CFArrayRef addrs;
+ boolean_t changed = FALSE;
+ CFMutableDictionaryRef dict = NULL;
+ struct in_addr mask = { 0 };
+ CFArrayRef masks;
+ CFDictionaryRef new_dict = NULL;
+ CFStringRef router = NULL;
+ boolean_t valid_ip = FALSE;
+ boolean_t valid_mask = FALSE;
+
+ if (state_dict == NULL) {
+ goto done;
+ }
+ addrs = isA_CFArray(CFDictionaryGetValue(state_dict,
+ kSCPropNetIPv4Addresses));
+ if (addrs != NULL && CFArrayGetCount(addrs) > 0) {
+ valid_ip = cfstring_to_ip(CFArrayGetValueAtIndex(addrs, 0), &addr);
+ }
+ masks = isA_CFArray(CFDictionaryGetValue(state_dict,
+ kSCPropNetIPv4SubnetMasks));
+ if (masks != NULL && CFArrayGetCount(masks) > 0) {
+ valid_mask = cfstring_to_ip(CFArrayGetValueAtIndex(masks, 0), &mask);
+ }
+ if (valid_ip == FALSE) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: %@ has no valid IP address, ignoring"),
+ serviceID);
+ goto done;
+ }
+ dict = CFDictionaryCreateMutableCopy(NULL, 0, state_dict);
+ if (setup_dict != NULL) {
+ router = CFDictionaryGetValue(setup_dict,
+ kSCPropNetIPv4Router);
+ if (router != NULL) {
+ CFDictionarySetValue(dict,
+ kSCPropNetIPv4Router,
+ router);
+ }
+ }
+
+ /* check whether the router is direct, or non-local */
+ router = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
+ if (router != NULL) {
+ struct in_addr router_ip;
+
+ if (cfstring_to_ip(router, &router_ip)) {
+ if (router_ip.s_addr == addr.s_addr) {
+ /* default route routes directly to the interface */
+ CFDictionarySetValue(dict, kRouterIsDirect, kCFBooleanTrue);
+ }
+ else if (valid_mask
+ && subnet_addr(addr, mask).s_addr
+ != subnet_addr(router_ip, mask).s_addr) {
+ /* router is not on the same subnet */
+ CFDictionarySetValue(dict, kRouterNeedsLocalIP,
+ CFArrayGetValueAtIndex(addrs, 0));
+ }
+ }
+ }
+ new_dict = dict;
+
+ done:
+ changed = service_dict_set(serviceID, kSCEntNetIPv4, new_dict);
+ my_CFRelease(&new_dict);
+ return (changed);
+}
+
+static boolean_t
+get_ipv6_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+ struct in6_addr addr;
+ CFArrayRef addrs;
+ boolean_t changed = FALSE;
+ CFMutableDictionaryRef dict = NULL;
+ CFDictionaryRef new_dict = NULL;
+ CFStringRef router = NULL;
+ boolean_t valid_ip = FALSE;
+
+ if (state_dict == NULL) {
+ goto done;
+ }
+ addrs = isA_CFArray(CFDictionaryGetValue(state_dict,
+ kSCPropNetIPv6Addresses));
+ if (addrs != NULL && CFArrayGetCount(addrs) > 0) {
+ valid_ip = cfstring_to_ip6(CFArrayGetValueAtIndex(addrs, 0), &addr);
+ }
+ if (valid_ip == FALSE) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: %@ has no valid IPv6 address, ignoring"),
+ serviceID);
+ goto done;
+ }
+ dict = CFDictionaryCreateMutableCopy(NULL, 0, state_dict);
+ if (setup_dict != NULL) {
+ router = CFDictionaryGetValue(setup_dict,
+ kSCPropNetIPv6Router);
+ if (router != NULL) {
+ CFDictionarySetValue(dict,
+ kSCPropNetIPv6Router,
+ router);
+ }
+ }
+ new_dict = dict;
+ done:
+ changed = service_dict_set(serviceID, kSCEntNetIPv6, new_dict);
+ my_CFRelease(&new_dict);
+ return (changed);
+}
+
+static boolean_t
+dns_has_supplemental(CFStringRef serviceID)
+{
+ CFDictionaryRef dns_dict;
+ CFDictionaryRef service_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, serviceID);
+ if (service_dict == NULL) {
+ return FALSE;
+ }
+
+ dns_dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
+ if (dns_dict == NULL) {
+ return FALSE;
+ }
+
+ return CFDictionaryContainsKey(dns_dict, kSCPropNetDNSSupplementalMatchDomains);
+}
+
+static void
+merge_dns_prop(CFMutableDictionaryRef dict, CFStringRef key,
+ CFDictionaryRef state_dict, CFDictionaryRef setup_dict,
+ Boolean append)
+{
+ CFArrayRef setup_prop = NULL;
+ CFArrayRef state_prop = NULL;
+
+ if (setup_dict != NULL) {
+ setup_prop = isA_CFArray(CFDictionaryGetValue(setup_dict, key));
+ }
+ if (state_dict != NULL) {
+ state_prop = isA_CFArray(CFDictionaryGetValue(state_dict, key));
+ }
+ if ((setup_prop != NULL) && (state_prop != NULL)) {
+ CFMutableArrayRef merge_prop;
+
+ /* create a new list by merging the setup and state lists */
+ merge_prop = CFArrayCreateMutableCopy(NULL, 0, setup_prop);
+ if (append) {
+ CFRange state_range = CFRangeMake(0, CFArrayGetCount(state_prop));
+
+ CFArrayAppendArray(merge_prop, state_prop, state_range);
+ } else {
+ CFIndex i;
+ CFIndex n;
+ CFRange setup_range = CFRangeMake(0, CFArrayGetCount(setup_prop));
+
+ n = CFArrayGetCount(state_prop);
+ for (i = 0; i < n; i++) {
+ CFTypeRef val;
+
+ val = CFArrayGetValueAtIndex(state_prop, i);
+ if (!CFArrayContainsValue(setup_prop, setup_range, val)) {
+ CFArrayAppendValue(merge_prop, val);
+ }
+ }
+ }
+ CFDictionarySetValue(dict, key, merge_prop);
+ my_CFRelease(&merge_prop);
+ }
+ else if (setup_prop != NULL) {
+ CFDictionarySetValue(dict, key, setup_prop);
+ }
+ else if (state_prop != NULL) {
+ CFDictionarySetValue(dict, key, state_prop);
+ }
+ return;
+}
+
+static boolean_t
+get_dns_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+ boolean_t changed = FALSE;
+ CFStringRef domain;
+ int i;
+ struct {
+ CFStringRef key;
+ Boolean append;
+ } merge_list[] = {
+ { kSCPropNetDNSSearchDomains, FALSE },
+ { kSCPropNetDNSServerAddresses, FALSE },
+ { kSCPropNetDNSSortList, FALSE },
+ { kSCPropNetDNSSupplementalMatchDomains, TRUE },
+ { kSCPropNetDNSSupplementalMatchOrders, TRUE },
+ { NULL, FALSE }
+ };
+ CFMutableDictionaryRef new_dict = NULL;
+ CFStringRef pick_list[] = {
+ kSCPropNetDNSDomainName,
+ kSCPropNetDNSOptions,
+ kSCPropNetDNSSearchOrder,
+ kSCPropNetDNSServerPort,
+ kSCPropNetDNSServerTimeout,
+ NULL
+ };
+
+ if (state_dict == NULL && setup_dict == NULL) {
+ /* there is no DNS */
+ goto done;
+ }
+ if (service_dict_get(serviceID, kSCEntNetIPv4) == NULL
+ && service_dict_get(serviceID, kSCEntNetIPv6) == NULL) {
+ /* no point in remembering the DNS */
+ goto done;
+ }
+
+ // merge DNS configuration
+ new_dict = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ for (i = 0; merge_list[i].key != NULL; i++) {
+ merge_dns_prop(new_dict,
+ merge_list[i].key,
+ state_dict,
+ setup_dict,
+ merge_list[i].append);
+ }
+ for (i = 0; pick_list[i]; i++) {
+ CFTypeRef val = NULL;
+
+ if (setup_dict != NULL) {
+ val = CFDictionaryGetValue(setup_dict, pick_list[i]);
+ }
+ if (val == NULL && state_dict != NULL) {
+ val = CFDictionaryGetValue(state_dict, pick_list[i]);
+ }
+ if (val != NULL) {
+ CFDictionarySetValue(new_dict, pick_list[i], val);
+ }
+ }
+ if (CFDictionaryGetCount(new_dict) == 0) {
+ my_CFRelease(&new_dict);
+ goto done;
+ }
+
+ /*
+ * ensure any specified domain name (e.g. the domain returned by
+ * a DHCP server) is in the search list.
+ */
+ domain = CFDictionaryGetValue(new_dict, kSCPropNetDNSDomainName);
+ if (isA_CFString(domain)) {
+ CFArrayRef search;
+
+ search = CFDictionaryGetValue(new_dict, kSCPropNetDNSSearchDomains);
+ if (isA_CFArray(search) &&
+ !CFArrayContainsValue(search, CFRangeMake(0, CFArrayGetCount(search)), domain)) {
+ CFMutableArrayRef new_search;
+
+ new_search = CFArrayCreateMutableCopy(NULL, 0, search);
+ CFArrayAppendValue(new_search, domain);
+ CFDictionarySetValue(new_dict, kSCPropNetDNSSearchDomains, new_search);
+ my_CFRelease(&new_search);
+ }
+ }
+
+ done:
+ changed = service_dict_set(serviceID, kSCEntNetDNS, new_dict);
+ my_CFRelease(&new_dict);
+ return (changed);
+}
+
+static boolean_t
+get_netinfo_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+ boolean_t changed = FALSE;
+ CFDictionaryRef global_dict;
+ CFDictionaryRef ipv4_dict;
+ CFDictionaryRef new_dict = NULL;
+
+ global_dict = my_CFDictionaryGetDictionary(info, S_setup_global_netinfo);
+ ipv4_dict = service_dict_get(serviceID, kSCEntNetIPv4);
+ new_dict = make_netinfo_dict(state_dict, global_dict, ipv4_dict);
+ changed = service_dict_set(serviceID, kSCEntNetNetInfo, new_dict);
+ my_CFRelease(&new_dict);
+ return (changed);
+}
+
+static boolean_t
+get_proxies_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+ CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+ boolean_t changed = FALSE;
+ CFDictionaryRef new_dict = NULL;
+
+ if (service_dict_get(serviceID, kSCEntNetIPv4) == NULL
+ && service_dict_get(serviceID, kSCEntNetIPv6) == NULL) {
+ /* no point in remembering the Proxies */
+ goto done;
+ }
+ if (setup_dict != NULL) {
+ new_dict = setup_dict;
+ }
+ else {
+ new_dict = state_dict;
+ }
+ done:
+ changed = service_dict_set(serviceID, kSCEntNetProxies, new_dict);
+ return (changed);
+}
+
+static CFStringRef
+state_service_key(CFStringRef serviceID, CFStringRef entity)
+{
+ return (SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ serviceID,
+ entity));
+}
+
+static CFStringRef
+setup_service_key(CFStringRef serviceID, CFStringRef entity)
+{
+ return (SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ serviceID,
+ entity));
+}
+
+static CFDictionaryRef
+services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list)
+{
+ int count;
+ CFMutableArrayRef get_keys;
+ int i;
+ int s;
+ CFDictionaryRef info;
+
+ count = CFArrayGetCount(service_list);
+ get_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ CFArrayAppendValue(get_keys, S_setup_global_netinfo);
+ CFArrayAppendValue(get_keys, S_setup_global_proxies);
+ CFArrayAppendValue(get_keys, S_setup_global_ipv4);
+
+ for (s = 0; s < count; s++) {
+ CFStringRef serviceID = CFArrayGetValueAtIndex(service_list, s);
+
+ for (i = 0; i < ENTITY_TYPES_COUNT; i++) {
+ CFStringRef setup_key;
+ CFStringRef state_key;
+
+ setup_key = setup_service_key(serviceID, entityTypeNames[i]);
+ state_key = state_service_key(serviceID, entityTypeNames[i]);
+ CFArrayAppendValue(get_keys, setup_key);
+ CFArrayAppendValue(get_keys, state_key);
+ my_CFRelease(&setup_key);
+ my_CFRelease(&state_key);
+ }
+ }
+
+ info = SCDynamicStoreCopyMultiple(session, get_keys, NULL);
+ my_CFRelease(&get_keys);
+ return (info);
+}
+
+static CFDictionaryRef
+get_service_setup_entity(CFDictionaryRef service_info, CFStringRef serviceID,
+ CFStringRef entity)
+{
+ CFStringRef setup_key;
+ CFDictionaryRef setup_dict;
+
+ setup_key = setup_service_key(serviceID, entity);
+ setup_dict = my_CFDictionaryGetDictionary(service_info, setup_key);
+ my_CFRelease(&setup_key);
+ return (setup_dict);
+}
+
+static CFDictionaryRef
+get_service_state_entity(CFDictionaryRef service_info, CFStringRef serviceID,
+ CFStringRef entity)
+{
+ CFStringRef state_key;
+ CFDictionaryRef state_dict;
+
+ state_key = state_service_key(serviceID, entity);
+ state_dict = my_CFDictionaryGetDictionary(service_info, state_key);
+ my_CFRelease(&state_key);
+ return (state_dict);
+}
+
+static int rtm_seq = 0;
+
+static boolean_t
+ipv4_route(int cmd, struct in_addr gateway, struct in_addr netaddr,
+ struct in_addr netmask, char * ifname, boolean_t is_direct)
+{
+ boolean_t default_route = (netaddr.s_addr == 0);
+ int len;
+ boolean_t ret = TRUE;
+ struct {
+ struct rt_msghdr hdr;
+ struct sockaddr_in dst;
+ struct sockaddr_in gway;
+ struct sockaddr_in mask;
+ struct sockaddr_dl link;
+ } rtmsg;
+ int sockfd = -1;
+
+ if (default_route && S_netboot) {
+ return (TRUE);
+ }
+
+ if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("IPMonitor: ipv4_route: open routing socket failed, %s"),
+ strerror(errno));
+ return (FALSE);
+ }
+
+ memset(&rtmsg, 0, sizeof(rtmsg));
+ rtmsg.hdr.rtm_type = cmd;
+ if (default_route) {
+ if (is_direct) {
+ /* if router is directly reachable, don't set the gateway flag */
+ rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
+ }
+ else {
+ rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
+ }
+ }
+ else {
+ rtmsg.hdr.rtm_flags = RTF_UP | RTF_CLONING | RTF_STATIC;
+ }
+ rtmsg.hdr.rtm_version = RTM_VERSION;
+ rtmsg.hdr.rtm_seq = ++rtm_seq;
+ rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+ rtmsg.dst.sin_len = sizeof(rtmsg.dst);
+ rtmsg.dst.sin_family = AF_INET;
+ rtmsg.dst.sin_addr = netaddr;
+ rtmsg.gway.sin_len = sizeof(rtmsg.gway);
+ rtmsg.gway.sin_family = AF_INET;
+ rtmsg.gway.sin_addr = gateway;
+ rtmsg.mask.sin_len = sizeof(rtmsg.mask);
+ rtmsg.mask.sin_family = AF_INET;
+ rtmsg.mask.sin_addr = netmask;
+
+ len = sizeof(rtmsg);
+ if (ifname) {
+ rtmsg.link.sdl_len = sizeof(rtmsg.link);
+ rtmsg.link.sdl_family = AF_LINK;
+ rtmsg.link.sdl_nlen = strlen(ifname);
+ rtmsg.hdr.rtm_addrs |= RTA_IFP;
+ bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen);
+ }
+ else {
+ /* no link information */
+ len -= sizeof(rtmsg.link);
+ }
+ rtmsg.hdr.rtm_msglen = len;
+ if (write(sockfd, &rtmsg, len) < 0) {
+ if ((cmd == RTM_ADD) && (errno == EEXIST)) {
+ /* no sense complaining about a route that already exists */
+ }
+ else if ((cmd == RTM_DELETE) && (errno == ESRCH)) {
+ /* no sense complaining about a route that isn't there */
+ }
+ else {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor ipv4_route: "
+ "write routing socket failed, %s"), strerror(errno));
+ ret = FALSE;
+ }
+ }
+
+ close(sockfd);
+ return (ret);
+}
+
+static boolean_t
+ipv6_route(int cmd, struct in6_addr gateway, struct in6_addr netaddr,
+ struct in6_addr netmask, char * ifname, boolean_t is_direct)
+{
+ boolean_t default_route;
+ int len;
+ boolean_t ret = TRUE;
+ struct {
+ struct rt_msghdr hdr;
+ struct sockaddr_in6 dst;
+ struct sockaddr_in6 gway;
+ struct sockaddr_in6 mask;
+ struct sockaddr_dl link;
+ } rtmsg;
+ int sockfd = -1;
+ struct in6_addr zeroes = IN6ADDR_ANY_INIT;
+
+ default_route = (bcmp(&zeroes, &netaddr, sizeof(netaddr)) == 0);
+
+ if (IN6_IS_ADDR_LINKLOCAL(&gateway) && ifname != NULL) {
+ unsigned int index = if_nametoindex(ifname);
+
+ /* add the scope id to the link local address */
+ gateway.__u6_addr.__u6_addr16[1] = (uint16_t)htons(index);
+ }
+ if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("IPMonitor ipv6_route: open routing socket failed, %s"),
+ strerror(errno));
+ return (FALSE);
+ }
+ memset(&rtmsg, 0, sizeof(rtmsg));
+ rtmsg.hdr.rtm_type = cmd;
+ if (default_route) {
+ if (is_direct) {
+ /* if router is directly reachable, don't set the gateway flag */
+ rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
+ }
+ else {
+ rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
+ }
+ }
+ else {
+ rtmsg.hdr.rtm_flags = RTF_UP | RTF_CLONING | RTF_STATIC;
+ }
+ rtmsg.hdr.rtm_version = RTM_VERSION;
+ rtmsg.hdr.rtm_seq = ++rtm_seq;
+ rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+ rtmsg.dst.sin6_len = sizeof(rtmsg.dst);
+ rtmsg.dst.sin6_family = AF_INET6;
+ rtmsg.dst.sin6_addr = netaddr;
+ rtmsg.gway.sin6_len = sizeof(rtmsg.gway);
+ rtmsg.gway.sin6_family = AF_INET6;
+ rtmsg.gway.sin6_addr = gateway;
+ rtmsg.mask.sin6_len = sizeof(rtmsg.mask);
+ rtmsg.mask.sin6_family = AF_INET6;
+ rtmsg.mask.sin6_addr = netmask;
+
+ len = sizeof(rtmsg);
+ if (ifname) {
+ rtmsg.link.sdl_len = sizeof(rtmsg.link);
+ rtmsg.link.sdl_family = AF_LINK;
+ rtmsg.link.sdl_nlen = strlen(ifname);
+ rtmsg.hdr.rtm_addrs |= RTA_IFP;
+ bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen);
+ }
+ else {
+ /* no link information */
+ len -= sizeof(rtmsg.link);
+ }
+ rtmsg.hdr.rtm_msglen = len;
+ if (write(sockfd, &rtmsg, len) < 0) {
+ if ((cmd == RTM_ADD) && (errno == EEXIST)) {
+ /* no sense complaining about a route that already exists */
+ }
+ else if ((cmd == RTM_DELETE) && (errno == ESRCH)) {
+ /* no sense complaining about a route that isn't there */
+ }
+ else {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor ipv6_route: write routing"
+ " socket failed, %s"), strerror(errno));
+ ret = FALSE;
+ }
+ }
+
+ close(sockfd);
+ return (ret);
+}
+
+static boolean_t
+ipv4_subnet_route_add(struct in_addr local_ip,
+ struct in_addr subnet, struct in_addr mask, char * ifname)
+{
+ if (S_IPMonitor_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("IPMonitor: IPv4 route add -net "
+ IP_FORMAT " -netmask %s interface %s"),
+ IP_LIST(&subnet), inet_ntoa(mask), ifname);
+ }
+ return (ipv4_route(RTM_ADD, local_ip, subnet, mask, ifname, FALSE));
+}
+
+static boolean_t
+ipv4_subnet_route_delete(struct in_addr subnet, struct in_addr mask)
+{
+ if (S_IPMonitor_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("IPMonitor: IPv4 route delete -net "
+ IP_FORMAT " %s"),
+ IP_LIST(&subnet), inet_ntoa(mask));
+ }
+ return (ipv4_route(RTM_DELETE, S_ip_zeros, subnet, mask, NULL, FALSE));
+}
+
+
+static boolean_t
+ipv4_default_route_delete(void)
+{
+ if (S_IPMonitor_debug) {
+ SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: IPv4 route delete default"));
+ }
+ return (ipv4_route(RTM_DELETE, S_ip_zeros, S_ip_zeros, S_ip_zeros, NULL, FALSE));
+}
+
+static boolean_t
+ipv4_default_route_add(struct in_addr router, char * ifname,
+ boolean_t is_direct)
+{
+ if (S_IPMonitor_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("IPMonitor: IPv4 route add default"
+ " %s interface %s direct %d"),
+ inet_ntoa(router), ifname, is_direct);
+ }
+ return (ipv4_route(RTM_ADD, router, S_ip_zeros, S_ip_zeros, ifname, is_direct));
+}
+
+static boolean_t
+ipv4_default_route_change(struct in_addr router, char * ifname,
+ boolean_t is_direct)
+{
+ if (S_IPMonitor_debug) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR("IPMonitor: IPv4 route change default"
+ " %s interface %s direct %d"),
+ inet_ntoa(router), ifname, is_direct);
+ }
+ return (ipv4_route(RTM_CHANGE, router, S_ip_zeros, S_ip_zeros, ifname,
+ is_direct));
+}
+
+static boolean_t
+ipv6_default_route_delete(void)
+{
+ if (S_IPMonitor_debug) {
+ SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: IPv6 route delete default"));
+ }
+ return (ipv6_route(RTM_DELETE, S_ip6_zeros, S_ip6_zeros, S_ip6_zeros, NULL, FALSE));
+}
+
+static boolean_t
+ipv6_default_route_add(struct in6_addr router, char * ifname,
+ boolean_t is_direct)
+{
+ if (S_IPMonitor_debug) {
+ char str[128];
+
+ str[0] = '\0';
+
+ inet_ntop(AF_INET6, &router, str, sizeof(str));
+ SCLog(TRUE,LOG_INFO,
+ CFSTR("IPMonitor: IPv6 route add default"
+ " %s interface %s direct %d"),
+ str, ifname, is_direct);
+ }
+ return (ipv6_route(RTM_ADD, router, S_ip6_zeros, S_ip6_zeros, ifname, is_direct));
+}
+
+
+static boolean_t
+multicast_route_delete()
+{
+ struct in_addr gateway = { htonl(INADDR_LOOPBACK) };
+ struct in_addr netaddr = { htonl(INADDR_UNSPEC_GROUP) };
+ struct in_addr netmask = { htonl(IN_CLASSD_NET) };
+
+ return (ipv4_route(RTM_DELETE, gateway, netaddr, netmask, "lo0", FALSE));
+}
+
+static boolean_t
+multicast_route_add()
+{
+ struct in_addr gateway = { htonl(INADDR_LOOPBACK) };
+ struct in_addr netaddr = { htonl(INADDR_UNSPEC_GROUP) };
+ struct in_addr netmask = { htonl(IN_CLASSD_NET) };
+
+ return (ipv4_route(RTM_ADD, gateway, netaddr, netmask, "lo0", FALSE));
+}
+
+static void
+set_ipv4_router(struct in_addr * router, char * ifname, boolean_t is_direct)
+{
+ if (S_router_subnet.s_addr != 0) {
+ ipv4_subnet_route_delete(S_router_subnet, S_router_subnet_mask);
+ S_router_subnet.s_addr = S_router_subnet_mask.s_addr = 0;
+ }
+ /* assign the new default route, ensure local multicast route available */
+ (void)ipv4_default_route_delete();
+ if (router != NULL) {
+ (void)ipv4_default_route_add(*router, ifname, is_direct);
+ (void)multicast_route_delete();
+ }
+ else {
+ (void)multicast_route_add();
+ }
+
+ return;
+}
+
+static void
+set_ipv6_router(struct in6_addr * router, char * ifname, boolean_t is_direct)
+{
+ /* assign the new default route, ensure local multicast route available */
+ (void)ipv6_default_route_delete();
+ if (router != NULL) {
+ (void)ipv6_default_route_add(*router, ifname, is_direct);
+ }
+ return;
+}
+
+static __inline__ void
+empty_dns()
+{
+ (void)unlink(VAR_RUN_RESOLV_CONF);
+}
+
+static void
+empty_netinfo(SCDynamicStoreRef session)
+{
+ int fd = open(VAR_RUN_NICONFIG_LOCAL_XML "-",
+ O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ if (fd >= 0) {
+ close(fd);
+ rename(VAR_RUN_NICONFIG_LOCAL_XML "-", VAR_RUN_NICONFIG_LOCAL_XML);
+ }
+
+ return;
+}
+
+static void
+set_dns(CFArrayRef val_search_domains,
+ CFStringRef val_domain_name,
+ CFArrayRef val_servers,
+ CFArrayRef val_sortlist)
+{
+ FILE * f = fopen(VAR_RUN_RESOLV_CONF "-", "w");
+
+ /* publish new resolv.conf */
+ if (f) {
+ CFIndex i;
+ CFIndex n;
+
+ if (isA_CFString(val_domain_name)) {
+ SCPrint(TRUE, f, CFSTR("domain %@\n"), val_domain_name);
+ }
+
+ if (isA_CFArray(val_search_domains)) {
+ SCPrint(TRUE, f, CFSTR("search"));
+ n = CFArrayGetCount(val_search_domains);
+ for (i = 0; i < n; i++) {
+ CFStringRef domain;
+
+ domain = CFArrayGetValueAtIndex(val_search_domains, i);
+ if (isA_CFString(domain)) {
+ SCPrint(TRUE, f, CFSTR(" %@"), domain);
+ }
+ }
+ SCPrint(TRUE, f, CFSTR("\n"));
+ }
+
+ if (isA_CFArray(val_servers)) {
+ n = CFArrayGetCount(val_servers);
+ for (i = 0; i < n; i++) {
+ CFStringRef nameserver;
+
+ nameserver = CFArrayGetValueAtIndex(val_servers, i);
+ if (isA_CFString(nameserver)) {
+ SCPrint(TRUE, f, CFSTR("nameserver %@\n"), nameserver);
+ }
+ }
+ }
+
+ if (isA_CFArray(val_sortlist)) {
+ SCPrint(TRUE, f, CFSTR("sortlist"));
+ n = CFArrayGetCount(val_sortlist);
+ for (i = 0; i < n; i++) {
+ CFStringRef address;
+
+ address = CFArrayGetValueAtIndex(val_sortlist, i);
+ if (isA_CFString(address)) {
+ SCPrint(TRUE, f, CFSTR(" %@"), address);
+ }
+ }
+ SCPrint(TRUE, f, CFSTR("\n"));
+ }
+
+ fclose(f);
+ rename(VAR_RUN_RESOLV_CONF "-", VAR_RUN_RESOLV_CONF);
+ }
+ return;
+}
+
+static void
+set_netinfo(CFDictionaryRef dict)
+{
+ int fd = open(VAR_RUN_NICONFIG_LOCAL_XML "-",
+ O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ if (fd >= 0) {
+ /* publish new netinfo config */
+ CFDataRef contents;
+ contents = CFPropertyListCreateXMLData(NULL, dict);
+ if (contents) {
+ CFIndex len = CFDataGetLength(contents);
+
+ write(fd, CFDataGetBytePtr(contents), len);
+ CFRelease(contents);
+ }
+ close(fd);
+ rename(VAR_RUN_NICONFIG_LOCAL_XML "-", VAR_RUN_NICONFIG_LOCAL_XML);
+ }
+ return;
+}
+
+static boolean_t
+router_is_our_ipv6_address(CFStringRef router, CFArrayRef addr_list)
+{
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(addr_list);
+ struct in6_addr r;
+
+ (void)cfstring_to_ip6(router, &r);
+ for (i = 0; i < n; i++) {
+ struct in6_addr ip;
+
+ if (cfstring_to_ip6(CFArrayGetValueAtIndex(addr_list, i), &ip)
+ && bcmp(&r, &ip, sizeof(r)) == 0) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+static void
+update_ipv4(SCDynamicStoreRef session, CFDictionaryRef service_info,
+ CFStringRef primary, keyChangeListRef keys)
+{
+ CFDictionaryRef ipv4_dict = NULL;
+
+ if (primary != NULL) {
+ CFDictionaryRef service_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+ if (service_dict != NULL) {
+ ipv4_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+ }
+ }
+ if (ipv4_dict != NULL) {
+ CFMutableDictionaryRef dict = NULL;
+ CFStringRef if_name = NULL;
+ char ifn[IFNAMSIZ + 1] = { '\0' };
+ char * ifn_p = NULL;
+ boolean_t is_direct = FALSE;
+ struct in_addr local_ip = { 0 };
+ CFStringRef val_router = NULL;
+ struct in_addr router = { 0 };
+
+ dict = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ val_router = CFDictionaryGetValue(ipv4_dict, kSCPropNetIPv4Router);
+ if (val_router != NULL) {
+ cfstring_to_ip(val_router, &router);
+ CFDictionarySetValue(dict, kSCPropNetIPv4Router, val_router);
+ if (CFDictionaryContainsKey(ipv4_dict, kRouterIsDirect)) {
+ is_direct = TRUE;
+ }
+ else {
+ CFStringRef local_ip_str;
+
+ local_ip_str = CFDictionaryGetValue(ipv4_dict,
+ kRouterNeedsLocalIP);
+ if (local_ip_str != NULL) {
+ cfstring_to_ip(local_ip_str, &local_ip);
+ }
+ }
+ }
+ else {
+ CFArrayRef addrs;
+
+ addrs = CFDictionaryGetValue(ipv4_dict,
+ kSCPropNetIPv4Addresses);
+ val_router = CFArrayGetValueAtIndex(addrs, 0);
+ cfstring_to_ip(val_router, &router);
+ is_direct = TRUE;
+ }
+ if_name = CFDictionaryGetValue(ipv4_dict, kSCPropInterfaceName);
+ if (if_name) {
+ CFDictionarySetValue(dict,
+ kSCDynamicStorePropNetPrimaryInterface,
+ if_name);
+ if (CFStringGetCString(if_name, ifn, sizeof(ifn),
+ kCFStringEncodingASCII)) {
+ ifn_p = ifn;
+ }
+ }
+ CFDictionarySetValue(dict, kSCDynamicStorePropNetPrimaryService,
+ primary);
+ keyChangeListSetValue(keys, S_state_global_ipv4, dict);
+ CFRelease(dict);
+
+ /* route add default ... */
+ if (local_ip.s_addr != 0) {
+ struct in_addr m;
+
+ m.s_addr = htonl(INADDR_BROADCAST);
+ ipv4_subnet_route_add(local_ip, router, m, ifn_p);
+ set_ipv4_router(&local_ip, ifn_p, FALSE);
+ ipv4_default_route_change(router, ifn_p, FALSE);
+ S_router_subnet = router;
+ S_router_subnet_mask = m;
+ }
+ else {
+ set_ipv4_router(&router, ifn_p, is_direct);
+ }
+ }
+ else {
+ keyChangeListRemoveValue(keys, S_state_global_ipv4);
+ set_ipv4_router(NULL, NULL, FALSE);
+ }
+ return;
+}
+
+static void
+update_ipv6(SCDynamicStoreRef session, CFDictionaryRef service_info,
+ CFStringRef primary, keyChangeListRef keys)
+{
+ CFDictionaryRef ipv6_dict = NULL;
+
+ if (primary != NULL) {
+ CFDictionaryRef service_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+ if (service_dict != NULL) {
+ ipv6_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv6);
+ }
+ }
+ if (ipv6_dict != NULL) {
+ CFArrayRef addrs;
+ CFMutableDictionaryRef dict = NULL;
+ CFStringRef if_name = NULL;
+ char ifn[IFNAMSIZ + 1] = { '\0' };
+ char * ifn_p = NULL;
+ boolean_t is_direct = FALSE;
+ CFStringRef val_router = NULL;
+
+ dict = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ val_router = CFDictionaryGetValue(ipv6_dict, kSCPropNetIPv6Router);
+ addrs = CFDictionaryGetValue(ipv6_dict,
+ kSCPropNetIPv6Addresses);
+ if (val_router != NULL) {
+ /* no router if router is one of our IP addresses */
+ is_direct = router_is_our_ipv6_address(val_router, addrs);
+ CFDictionarySetValue(dict, kSCPropNetIPv6Router,
+ val_router);
+ }
+ else {
+ val_router = CFArrayGetValueAtIndex(addrs, 0);
+ is_direct = TRUE;
+ }
+ if_name = CFDictionaryGetValue(ipv6_dict, kSCPropInterfaceName);
+ if (if_name) {
+ CFDictionarySetValue(dict,
+ kSCDynamicStorePropNetPrimaryInterface,
+ if_name);
+ if (CFStringGetCString(if_name, ifn, sizeof(ifn),
+ kCFStringEncodingASCII)) {
+ ifn_p = ifn;
+ }
+ }
+ CFDictionarySetValue(dict, kSCDynamicStorePropNetPrimaryService,
+ primary);
+ keyChangeListSetValue(keys, S_state_global_ipv6, dict);
+ CFRelease(dict);
+
+ { /* route add default ... */
+ struct in6_addr router;
+
+ (void)cfstring_to_ip6(val_router, &router);
+ set_ipv6_router(&router, ifn_p, is_direct);
+ }
+ }
+ else {
+ keyChangeListRemoveValue(keys, S_state_global_ipv6);
+ set_ipv6_router(NULL, NULL, FALSE);
+ }
+ return;
+}
+
+static void
+update_dns(SCDynamicStoreRef session, CFDictionaryRef service_info,
+ CFStringRef primary, keyChangeListRef keys)
+{
+ CFDictionaryRef dict = NULL;
+
+ if (primary != NULL) {
+ CFDictionaryRef service_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+ if (service_dict != NULL) {
+ dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
+ }
+ }
+ if (dict == NULL) {
+ empty_dns();
+ keyChangeListRemoveValue(keys, S_state_global_dns);
+ }
+ else {
+ set_dns(CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains),
+ CFDictionaryGetValue(dict, kSCPropNetDNSDomainName),
+ CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses),
+ CFDictionaryGetValue(dict, kSCPropNetDNSSortList));
+ keyChangeListSetValue(keys, S_state_global_dns, dict);
+ }
+ return;
+}
+
+static void
+update_dnsinfo(CFStringRef primary, CFArrayRef service_order, keyChangeListRef keys)
+{
+ CFDictionaryRef dict = NULL;
+
+ if (primary != NULL) {
+ CFDictionaryRef service_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+ if (service_dict != NULL) {
+ dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
+ }
+ }
+ if (dict == NULL) {
+ /* update DNS configuration */
+ dns_configuration_set(NULL, NULL, NULL);
+ }
+ else {
+ /* update DNS configuration */
+ dns_configuration_set(dict, S_service_state_dict, service_order);
+ }
+ keyChangeListNotifyKey(keys, S_notify_dnsinfo);
+ return;
+}
+
+static void
+update_netinfo(SCDynamicStoreRef session, CFDictionaryRef service_info,
+ CFStringRef primary, keyChangeListRef keys)
+{
+ CFDictionaryRef dict = NULL;
+
+ if (primary != NULL) {
+ CFDictionaryRef ipv4_dict = NULL;
+ CFDictionaryRef service_dict;
+ CFDictionaryRef setup_dict;
+ CFStringRef state_key;
+ CFDictionaryRef state_dict;
+
+ service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+ if (service_dict != NULL) {
+ ipv4_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+ }
+ state_key = state_service_key(primary, kSCEntNetNetInfo);
+ state_dict = my_CFDictionaryGetDictionary(service_info, state_key);
+ if (state_dict != NULL) {
+ CFRetain(state_dict);
+ }
+ else {
+ state_dict = my_SCDCopy(session, state_key);
+ }
+ setup_dict = my_CFDictionaryGetDictionary(service_info,
+ S_setup_global_netinfo);
+ dict = make_netinfo_dict(state_dict, setup_dict, ipv4_dict);
+ my_CFRelease(&state_key);
+ my_CFRelease(&state_dict);
+ }
+ if (dict == NULL) {
+ empty_netinfo(session);
+ keyChangeListRemoveValue(keys, S_state_global_netinfo);
+ }
+ else {
+ set_netinfo(dict);
+ keyChangeListSetValue(keys, S_state_global_netinfo, dict);
+ my_CFRelease(&dict);
+ }
+ return;
+}
+
+static void
+update_proxies(SCDynamicStoreRef session, CFDictionaryRef service_info,
+ CFStringRef primary, keyChangeListRef keys)
+{
+ CFDictionaryRef dict = NULL;
+
+ if (primary != NULL) {
+ CFDictionaryRef service_dict;
+ service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+ if (service_dict != NULL) {
+ dict = CFDictionaryGetValue(service_dict, kSCEntNetProxies);
+ if (dict == NULL) {
+ dict = my_CFDictionaryGetDictionary(service_info,
+ S_setup_global_proxies);
+ }
+ }
+ }
+ if (dict == NULL) {
+ keyChangeListRemoveValue(keys, S_state_global_proxies);
+ }
+ else {
+ keyChangeListSetValue(keys, S_state_global_proxies, dict);
+ }
+ return;
+}
+
+static unsigned int
+get_service_rank(CFStringRef proto_key, CFArrayRef order, CFStringRef serviceID)
+{
+ CFDictionaryRef d;
+ CFIndex i;
+ CFDictionaryRef proto_dict;
+
+ if (serviceID == NULL) {
+ goto done;
+ }
+ d = CFDictionaryGetValue(S_service_state_dict, serviceID);
+ if (d == NULL) {
+ goto done;
+ }
+
+ proto_dict = CFDictionaryGetValue(d, proto_key);
+ if (proto_dict) {
+ CFStringRef if_name;
+ CFNumberRef override = NULL;
+
+ if_name = CFDictionaryGetValue(proto_dict, kSCPropInterfaceName);
+ if (S_ppp_override_primary == TRUE
+ && if_name != NULL
+ && CFStringHasPrefix(if_name, CFSTR("ppp"))) {
+ /* PPP override: make ppp* look the best */
+ /* Hack: should use interface type, not interface name */
+ return (0);
+ }
+ /* check for the "OverridePrimary" property */
+ override = CFDictionaryGetValue(proto_dict, kSCPropNetOverridePrimary);
+ if (isA_CFNumber(override) != NULL) {
+ int val = 0;
+
+ CFNumberGetValue(override, kCFNumberIntType, &val);
+ if (val != 0) {
+ return (0);
+ }
+ }
+ }
+
+ if (serviceID != NULL && order != NULL) {
+ CFIndex n = CFArrayGetCount(order);
+
+ for (i = 0; i < n; i++) {
+ CFStringRef s = isA_CFString(CFArrayGetValueAtIndex(order, i));
+
+ if (s == NULL) {
+ continue;
+ }
+ if (CFEqual(serviceID, s)) {
+ return (i + 1);
+ }
+ }
+ }
+
+ done:
+ return (UINT_MAX);
+}
+
+/**
+ ** Service election:
+ **/
+typedef boolean_t (*routerCheckFunc)(CFStringRef str);
+
+static boolean_t
+check_ipv4_router(CFStringRef router)
+{
+ struct in_addr ip;
+
+ return (cfstring_to_ip(router, &ip));
+}
+
+static boolean_t
+check_ipv6_router(CFStringRef router)
+{
+ struct in6_addr ip6;
+
+ return (cfstring_to_ip6(router, &ip6));
+}
+
+struct election_state {
+ routerCheckFunc router_check;
+ CFStringRef proto_key; /* e.g. kSCEntNetIPv4 */
+ CFStringRef router_key;/* e.g. kSCPropNetIPv4Router */
+ CFArrayRef order;
+ CFStringRef new_primary;
+ boolean_t new_has_router;
+ unsigned int new_primary_index;
+};
+
+static void
+elect_protocol(const void * key, const void * value, void * context)
+{
+ struct election_state * elect_p = (struct election_state *)context;
+ CFDictionaryRef proto_dict = NULL;
+ CFStringRef router;
+ boolean_t router_valid = FALSE;
+ CFStringRef serviceID = (CFStringRef)key;
+ CFDictionaryRef service_dict = (CFDictionaryRef)value;
+ unsigned int service_index;
+
+ proto_dict = CFDictionaryGetValue(service_dict, elect_p->proto_key);
+ if (proto_dict == NULL) {
+ return;
+ }
+ router = CFDictionaryGetValue(proto_dict, elect_p->router_key);
+ router_valid = (*elect_p->router_check)(router);
+ if (router_valid == FALSE && elect_p->new_has_router == TRUE) {
+ /* skip it */
+ return;
+ }
+ service_index
+ = get_service_rank(elect_p->proto_key, elect_p->order, serviceID);
+ if (elect_p->new_primary == NULL
+ || service_index < elect_p->new_primary_index
+ || (router_valid && elect_p->new_has_router == FALSE)) {
+ my_CFRelease(&elect_p->new_primary);
+ elect_p->new_primary = CFRetain(serviceID);
+ elect_p->new_primary_index = service_index;
+ elect_p->new_has_router = router_valid;
+ }
+ return;
+}
+
+static CFStringRef
+elect_new_primary(CFArrayRef order, CFStringRef proto_key,
+ CFStringRef router_key)
+{
+ struct election_state elect;
+
+ if (CFEqual(proto_key, kSCEntNetIPv4)) {
+ elect.router_check = check_ipv4_router;
+ }
+ else if (CFEqual(proto_key, kSCEntNetIPv6)) {
+ elect.router_check = check_ipv6_router;
+ }
+ else {
+ return (NULL);
+ }
+ elect.order = order;
+ elect.new_primary = NULL;
+ elect.new_primary_index = 0;
+ elect.new_has_router = FALSE;
+ elect.proto_key = proto_key;
+ elect.router_key = router_key;
+ CFDictionaryApplyFunction(S_service_state_dict, elect_protocol, &elect);
+ return (elect.new_primary);
+}
+
+static uint32_t
+service_changed(CFDictionaryRef services_info, CFStringRef serviceID)
+{
+ uint32_t changed = 0;
+ int i;
+
+ for (i = 0; i < ENTITY_TYPES_COUNT; i++) {
+ GetEntityChangesFuncRef func = entityChangeFunc[i];
+ if ((*func)(serviceID,
+ get_service_state_entity(services_info, serviceID,
+ entityTypeNames[i]),
+ get_service_setup_entity(services_info, serviceID,
+ entityTypeNames[i]),
+ services_info)) {
+ changed |= (1 << i);
+ }
+ }
+ return (changed);
+}
+
+static CFArrayRef
+service_order_get(CFDictionaryRef services_info)
+{
+ CFArrayRef order = NULL;
+ CFNumberRef ppp_override = NULL;
+ int ppp_val = TRUE;
+ CFDictionaryRef ipv4_dict = NULL;
+
+ ipv4_dict = my_CFDictionaryGetDictionary(services_info,
+ S_setup_global_ipv4);
+ if (ipv4_dict != NULL) {
+ order = CFDictionaryGetValue(ipv4_dict, kSCPropNetServiceOrder);
+ order = isA_CFArray(order);
+
+ /* get ppp override primary */
+ ppp_override = CFDictionaryGetValue(ipv4_dict,
+ kSCPropNetPPPOverridePrimary);
+ ppp_override = isA_CFNumber(ppp_override);
+ if (ppp_override != NULL) {
+ CFNumberGetValue(ppp_override, kCFNumberIntType, &ppp_val);
+ }
+ S_ppp_override_primary = (ppp_val != 0) ? TRUE : FALSE;
+ }
+ else {
+ S_ppp_override_primary = TRUE;
+ }
+ return (order);
+}
+
+static boolean_t
+set_new_primary(CFStringRef * primary_p, CFStringRef new_primary,
+ const char * entity)
+{
+ boolean_t changed = FALSE;
+ CFStringRef primary = *primary_p;
+
+ if (new_primary != NULL) {
+ if (primary != NULL && CFEqual(new_primary, primary)) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: %@ is still primary %s"),
+ new_primary, entity);
+ }
+ else {
+ my_CFRelease(primary_p);
+ *primary_p = CFRetain(new_primary);
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: %@ is the new primary %s"),
+ new_primary, entity);
+ changed = TRUE;
+ }
+ }
+ else if (primary != NULL) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: %@ is no longer primary %s"), primary, entity);
+ my_CFRelease(primary_p);
+ changed = TRUE;
+ }
+ return (changed);
+}
+
+static unsigned int
+rank_service_entity(CFArrayRef order, CFStringRef primary,
+ CFStringRef proto_key, CFStringRef entity)
+{
+ CFDictionaryRef dict;
+ dict = service_dict_get(primary, entity);
+ if (dict == NULL) {
+ return (UINT_MAX);
+ }
+ return (get_service_rank(proto_key, order, primary));
+}
+
+static void
+IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
+ void * not_used)
+{
+ CFIndex count;
+ boolean_t dnsinfo_changed = FALSE;
+ boolean_t global_ipv4_changed = FALSE;
+ boolean_t global_ipv6_changed = FALSE;
+ keyChangeList keys;
+ int i;
+ CFIndex n;
+ CFArrayRef service_order;
+ CFMutableArrayRef service_changes = NULL;
+ CFDictionaryRef services_info = NULL;
+
+ count = CFArrayGetCount(changed_keys);
+ if (count == 0) {
+ return;
+ }
+
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: changes %@ (%d)"), changed_keys, count);
+
+ keyChangeListInit(&keys);
+ service_changes = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+ for (i = 0; i < count; i++) {
+ CFStringRef change = CFArrayGetValueAtIndex(changed_keys, i);
+ if (CFEqual(change, S_setup_global_ipv4)) {
+ global_ipv4_changed = TRUE;
+ global_ipv6_changed = TRUE;
+ }
+ else if (CFEqual(change, S_setup_global_netinfo)) {
+ if (S_primary_ipv4 != NULL) {
+ my_CFArrayAppendUniqueValue(service_changes, S_primary_ipv4);
+ }
+ }
+ else if (CFEqual(change, S_setup_global_proxies)) {
+ if (S_primary_proxies != NULL) {
+ my_CFArrayAppendUniqueValue(service_changes, S_primary_proxies);
+ }
+ }
+ else if (CFStringHasPrefix(change, S_state_service_prefix)) {
+ CFStringRef serviceID = parse_component(change,
+ S_state_service_prefix);
+ if (serviceID) {
+ my_CFArrayAppendUniqueValue(service_changes, serviceID);
+ CFRelease(serviceID);
+ }
+ }
+ else if (CFStringHasPrefix(change, S_setup_service_prefix)) {
+ CFStringRef serviceID = parse_component(change,
+ S_setup_service_prefix);
+ if (serviceID) {
+ my_CFArrayAppendUniqueValue(service_changes, serviceID);
+ CFRelease(serviceID);
+ }
+ }
+ }
+
+ /* grab a snapshot of everything we need */
+ services_info = services_info_copy(session, service_changes);
+ service_order = service_order_get(services_info);
+ if (service_order != NULL) {
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: service_order %@ "), service_order);
+ }
+ n = CFArrayGetCount(service_changes);
+ for (i = 0; i < n; i++) {
+ uint32_t changes;
+ CFStringRef serviceID;
+ Boolean wasSupplemental;
+
+ serviceID = CFArrayGetValueAtIndex(service_changes, i);
+ wasSupplemental = dns_has_supplemental(serviceID);
+ changes = service_changed(services_info, serviceID);
+
+ if (S_primary_ipv4 != NULL && CFEqual(S_primary_ipv4, serviceID)) {
+ if ((changes & (1 << kEntityTypeIPv4)) != 0) {
+ update_ipv4(session, services_info, serviceID, &keys);
+ global_ipv4_changed = TRUE;
+ }
+ if ((changes & (1 << kEntityTypeNetInfo)) != 0) {
+ update_netinfo(session, services_info, serviceID, &keys);
+ }
+ }
+ else if ((changes & (1 << kEntityTypeIPv4)) != 0) {
+ global_ipv4_changed = TRUE;
+ }
+ if ((changes & (1 << kEntityTypeIPv6)) != 0) {
+ if (S_primary_ipv6 != NULL && CFEqual(S_primary_ipv6, serviceID)) {
+ update_ipv6(session, services_info, serviceID, &keys);
+ }
+ global_ipv6_changed = TRUE;
+ }
+ if ((changes & (1 << kEntityTypeDNS)) != 0) {
+ if (S_primary_dns != NULL && CFEqual(S_primary_dns, serviceID)) {
+ update_dns(session, services_info, serviceID, &keys);
+ dnsinfo_changed = TRUE;
+ }
+ else if (wasSupplemental || dns_has_supplemental(serviceID)) {
+ dnsinfo_changed = TRUE;
+ }
+ }
+ if ((changes & (1 << kEntityTypeProxies)) != 0) {
+ if (S_primary_proxies != NULL && CFEqual(S_primary_proxies, serviceID)) {
+ update_proxies(session, services_info, serviceID, &keys);
+ }
+ }
+ }
+
+ if (global_ipv4_changed) {
+ CFStringRef new_primary;
+
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: IPv4 service election"));
+ new_primary = elect_new_primary(service_order,
+ kSCEntNetIPv4, kSCPropNetIPv4Router);
+ if (set_new_primary(&S_primary_ipv4, new_primary, "IPv4")) {
+ update_ipv4(session, services_info, S_primary_ipv4, &keys);
+ update_netinfo(session, services_info, S_primary_ipv4, &keys);
+ }
+ my_CFRelease(&new_primary);
+ }
+ if (global_ipv6_changed) {
+ CFStringRef new_primary;
+
+ SCLog(S_IPMonitor_debug, LOG_INFO,
+ CFSTR("IPMonitor: IPv6 service election"));
+ new_primary = elect_new_primary(service_order,
+ kSCEntNetIPv6, kSCPropNetIPv6Router);
+ if (set_new_primary(&S_primary_ipv6, new_primary, "IPv6")) {
+ update_ipv6(session, services_info, S_primary_ipv6, &keys);
+ }
+ my_CFRelease(&new_primary);
+ }
+ if (global_ipv4_changed || global_ipv6_changed) {
+ CFStringRef new_primary_dns;
+ CFStringRef new_primary_proxies;
+
+ if (S_primary_ipv4 != NULL && S_primary_ipv6 != NULL) {
+ /* decide between IPv4 and IPv6 */
+ if (rank_service_entity(service_order, S_primary_ipv4,
+ kSCEntNetIPv4, kSCEntNetDNS)
+ <= rank_service_entity(service_order, S_primary_ipv6,
+ kSCEntNetIPv6, kSCEntNetDNS)) {
+ new_primary_dns = S_primary_ipv4;
+ }
+ else {
+ new_primary_dns = S_primary_ipv6;
+ }
+ if (rank_service_entity(service_order, S_primary_ipv4,
+ kSCEntNetIPv4, kSCEntNetProxies)
+ <= rank_service_entity(service_order, S_primary_ipv6,
+ kSCEntNetIPv6, kSCEntNetProxies)) {
+ new_primary_proxies = S_primary_ipv4;
+ }
+ else {
+ new_primary_proxies = S_primary_ipv6;
+ }
+
+ }
+ else if (S_primary_ipv6 != NULL) {
+ new_primary_dns = new_primary_proxies = S_primary_ipv6;
+ }
+ else if (S_primary_ipv4 != NULL) {
+ new_primary_dns = new_primary_proxies = S_primary_ipv4;
+ }
+ else {
+ new_primary_dns = new_primary_proxies = NULL;
+ }
+
+ if (set_new_primary(&S_primary_dns, new_primary_dns, "DNS")) {
+ update_dns(session, services_info, S_primary_dns, &keys);
+ dnsinfo_changed = TRUE;
+ }
+ if (set_new_primary(&S_primary_proxies, new_primary_proxies, "Proxies")) {
+ update_proxies(session, services_info, S_primary_proxies, &keys);
+ }
+ }
+ if (dnsinfo_changed) {
+ update_dnsinfo(S_primary_dns, service_order, &keys);
+ }
+ my_CFRelease(&service_changes);
+ my_CFRelease(&services_info);
+ keyChangeListApplyToStore(&keys, session);
+ keyChangeListFree(&keys);
+ return;
+}
+
+static void
+initEntityNames(void)
+{
+ entityTypeNames[0] = kSCEntNetIPv4; /* 0 */
+ entityTypeNames[1] = kSCEntNetIPv6; /* 1 */
+ entityTypeNames[2] = kSCEntNetDNS; /* 2 */
+ entityTypeNames[3] = kSCEntNetNetInfo; /* 3 */
+ entityTypeNames[4] = kSCEntNetProxies; /* 4 */
+ return;
+}
+
+static void
+ip_plugin_init()
+{
+ int i;
+ CFStringRef key;
+ CFMutableArrayRef keys = NULL;
+ CFMutableArrayRef patterns = NULL;
+ CFRunLoopSourceRef rls = NULL;
+ SCDynamicStoreRef session = NULL;
+
+ initEntityNames();
+ if (S_netboot_root() != 0) {
+ S_netboot = TRUE;
+ }
+ session = SCDynamicStoreCreate(NULL, CFSTR("IPMonitor"),
+ IPMonitorNotify, NULL);
+ if (session == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("IPMonitor ip_plugin_init SCDynamicStoreCreate failed: %s"),
+ SCErrorString(SCError()));
+ return;
+ }
+ S_state_global_ipv4
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv4);
+ S_state_global_ipv6
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv6);
+ S_state_global_dns
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetDNS);
+ S_state_global_netinfo
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetNetInfo);
+ S_state_global_proxies
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetProxies);
+ S_setup_global_ipv4
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetIPv4);
+ S_setup_global_netinfo
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetNetInfo);
+ S_setup_global_proxies
+ = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetProxies);
+ S_state_service_prefix
+ = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"),
+ kSCDynamicStoreDomainState,
+ kSCCompNetwork,
+ kSCCompService);
+ S_setup_service_prefix
+ = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"),
+ kSCDynamicStoreDomainSetup,
+ kSCCompNetwork,
+ kSCCompService);
+ S_service_state_dict
+ = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ key = CFStringCreateWithCString(NULL,
+ dns_configuration_notify_key(),
+ kCFStringEncodingASCII);
+ S_notify_dnsinfo = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), key);
+ CFRelease(key);
+
+ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ /* register for State: and Setup: per-service notifications */
+ for (i = 0; i < ENTITY_TYPES_COUNT; i++) {
+ key = state_service_key(kSCCompAnyRegex, entityTypeNames[i]);
+ CFArrayAppendValue(patterns, key);
+ CFRelease(key);
+ key = setup_service_key(kSCCompAnyRegex, entityTypeNames[i]);
+ CFArrayAppendValue(patterns, key);
+ CFRelease(key);
+ }
+
+ /* add notifier for setup global netinfo */
+ CFArrayAppendValue(keys, S_setup_global_netinfo);
+
+ /* add notifier for ServiceOrder/PPPOverridePrimary changes for IPv4 */
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCEntNetIPv4);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ if (!SCDynamicStoreSetNotificationKeys(session, keys, patterns)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("IPMonitor ip_plugin_init "
+ "SCDynamicStoreSetNotificationKeys failed: %s"),
+ SCErrorString(SCError()));
+ goto done;
+ }
+
+ rls = SCDynamicStoreCreateRunLoopSource(NULL, session, 0);
+ if (rls == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("IPMonitor ip_plugin_init "
+ "SCDynamicStoreCreateRunLoopSource failed: %s"),
+ SCErrorString(SCError()));
+ goto done;
+ }
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+ CFRelease(rls);
+
+ /* initialize dns configuration */
+ dns_configuration_set(NULL, NULL, NULL);
+ empty_dns();
+ (void)SCDynamicStoreRemoveValue(session, S_state_global_dns);
+
+ /* initialize netinfo state */
+ empty_netinfo(session);
+ (void)SCDynamicStoreRemoveValue(session, S_state_global_netinfo);
+
+ done:
+ my_CFRelease(&keys);
+ my_CFRelease(&patterns);
+ my_CFRelease(&session);
+ return;
+}
+
+__private_extern__
+void
+prime_IPMonitor()
+{
+ /* initialize multicast route */
+ set_ipv4_router(NULL, NULL, FALSE);
+}
+
+__private_extern__
+void
+load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ if (bundleVerbose) {
+ S_IPMonitor_debug = 1;
+ }
+
+ dns_configuration_init(bundle);
+ ip_plugin_init();
+
+ load_hostname(S_IPMonitor_debug);
+
+ return;
+}
+
+
+#ifdef MAIN
+#undef MAIN
+#include "dns-configuration.c"
+#include "set-hostname.c"
+
+int
+main(int argc, char **argv)
+{
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_IPMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ prime_IPMonitor();
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2004-2005 Apple Computer, 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 <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb_async.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h> // for SCLog(), SCPrint()
+
+#include <notify.h>
+
+
+static SCDynamicStoreRef store = NULL;
+static CFRunLoopSourceRef rls = NULL;
+
+static CFMachPortRef dnsPort = NULL;
+static CFRunLoopSourceRef dnsRLS = NULL;
+static struct timeval dnsQueryStart;
+
+static Boolean _verbose = FALSE;
+
+
+/* SPI (from SCNetworkReachability.c) */
+Boolean
+_SC_checkResolverReachability(SCDynamicStoreRef *storeP,
+ SCNetworkConnectionFlags *flags,
+ Boolean *haveDNS,
+ const char * nodename);
+
+
+/*
+ * checkResolverReachabilityByAddress()
+ *
+ * Given an IP address, determine whether a reverse DNS query can be issued
+ * using the current network configuration.
+ */
+static Boolean
+checkResolverReachabilityByAddress(SCDynamicStoreRef store, struct sockaddr *sa)
+{
+ SCNetworkConnectionFlags flags;
+ Boolean haveDNS;
+ int i;
+ Boolean ok = FALSE;
+ char ptr_name[128];
+
+ /*
+ * Ideally, we would have an API that given a local IP
+ * address would return the DNS server(s) that would field
+ * a given PTR query. Fortunately, we do have an SPI which
+ * which will provide this information given a "name" so we
+ * take the address, convert it into the inverse query name,
+ * and find out which servers should be consulted.
+ */
+
+ switch (sa->sa_family) {
+ case AF_INET : {
+ union {
+ in_addr_t s_addr;
+ unsigned char b[4];
+ } rev;
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ /*
+ * build "PTR" query name
+ * NNN.NNN.NNN.NNN.in-addr.arpa.
+ */
+ rev.s_addr = sin->sin_addr.s_addr;
+ (void) snprintf(ptr_name, sizeof(ptr_name), "%u.%u.%u.%u.in-addr.arpa.",
+ rev.b[3],
+ rev.b[2],
+ rev.b[1],
+ rev.b[0]);
+
+ break;
+ }
+
+ case AF_INET6 : {
+ int s = 0;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ int x = sizeof(ptr_name);
+ int n;
+
+#define USE_NIBBLE_QUERY
+#ifdef USE_NIBBLE_QUERY
+ /*
+ * build IPv6 "nibble" PTR query name (RFC 1886, RFC 3152)
+ * N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.ip6.arpa.
+ */
+ for (i = sizeof(sin6->sin6_addr) - 1; i >= 0; i--) {
+ n = snprintf(&ptr_name[s], x, "%x.%x.",
+ ( sin6->sin6_addr.s6_addr[i] & 0xf),
+ ((sin6->sin6_addr.s6_addr[i] >> 4) & 0xf));
+ if ((n == -1) || (n >= x)) {
+ goto done;
+ }
+
+ s += n;
+ x -= n;
+ }
+
+ n = snprintf(&ptr_name[s], x, "ip6.arpa.");
+ if ((n == -1) || (n >= x)) {
+ goto done;
+ }
+#else /* USE_NIBBLE_QUERY */
+ /*
+ * build IPv6 "bit-string" PTR query name (RFC 2673)
+ * \[xNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN].ip6.arpa.
+ */
+ n = snprintf(&ptr_name[0], x, "\\[x");
+ if ((n == -1) || (n >= x)) {
+ goto done;
+ }
+
+ s += n;
+ x -= n;
+ for (i = 0; i < 16; i++) {
+ n = snprintf(&ptr_name[s], x, "%2.2x", sin6->sin6_addr.s6_addr[i]);
+ if ((n == -1) || (n >= x)) {
+ goto done;
+ }
+
+ s += n;
+ x -= n;
+ }
+
+ n = snprintf(&ptr_name[s], x, "].ip6.arpa.");
+ if ((n == -1) || (n >= x)) {
+ goto done;
+ }
+#endif /* USE_NIBBLE_QUERY */
+
+ break;
+ }
+
+ default :
+ goto done;
+ }
+
+ ok = _SC_checkResolverReachability(&store, &flags, &haveDNS, ptr_name);
+ if (ok) {
+ if (!(flags & kSCNetworkFlagsReachable) ||
+ (flags & kSCNetworkFlagsConnectionRequired)) {
+ // if not reachable *OR* connection required
+ ok = FALSE;
+ }
+ }
+
+ done :
+
+ return ok;
+}
+
+
+#define HOSTNAME_NOTIFY_KEY "com.apple.system.hostname"
+
+
+static void
+set_hostname(CFStringRef hostname)
+{
+ if (hostname != NULL) {
+ char old_name[MAXHOSTNAMELEN];
+ char new_name[MAXHOSTNAMELEN];
+
+ if (gethostname(old_name, sizeof(old_name)) == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("gethostname() failed: %s"), strerror(errno));
+ old_name[0] = '\0';
+ }
+
+ if (_SC_cfstring_to_cstring(hostname,
+ new_name,
+ sizeof(new_name),
+ kCFStringEncodingUTF8) == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not convert [new] hostname"));
+ new_name[0] = '\0';
+ }
+
+ old_name[sizeof(old_name)-1] = '\0';
+ new_name[sizeof(new_name)-1] = '\0';
+ if (strcmp(old_name, new_name) != 0) {
+ if (sethostname(new_name, strlen(new_name)) == 0) {
+ uint32_t status;
+
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR("setting hostname to \"%s\""),
+ new_name);
+
+ status = notify_post(HOSTNAME_NOTIFY_KEY);
+ if (status != NOTIFY_STATUS_OK) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%lu"),
+ status);
+ }
+ } else {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("sethostname(%s, %d) failed: %s"),
+ new_name,
+ strlen(new_name),
+ strerror(errno));
+ }
+ }
+ }
+
+ return;
+}
+
+
+#define HOSTCONFIG "/etc/hostconfig"
+#define HOSTNAME_KEY "HOSTNAME="
+#define AUTOMATIC "-AUTOMATIC-"
+
+#define HOSTNAME_KEY_LEN (sizeof(HOSTNAME_KEY) - 1)
+
+static CFStringRef
+copy_static_name()
+{
+ FILE * f;
+ char buf[256];
+ CFStringRef name = NULL;
+
+ f = fopen(HOSTCONFIG, "r");
+ if (f == NULL) {
+ return NULL;
+ }
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char * bp;
+ int n;
+ char * np;
+ Boolean str_escape;
+ Boolean str_quote;
+
+ n = strlen(buf);
+ if (buf[n-1] == '\n') {
+ /* the entire line fit in the buffer, remove the newline */
+ buf[n-1] = '\0';
+ } else {
+ /* eat the remainder of the line */
+ do {
+ n = fgetc(f);
+ } while ((n != '\n') && (n != EOF));
+ }
+
+ // skip leading white space
+ bp = &buf[0];
+ while (isspace(*bp)) {
+ bp++;
+ }
+
+ // find "HOSTNAME=" key
+ if (strncmp(bp, HOSTNAME_KEY, HOSTNAME_KEY_LEN) != 0) {
+ continue; // if not
+ }
+
+ // get the hostname string
+ bp += HOSTNAME_KEY_LEN;
+ str_escape = FALSE;
+ str_quote = FALSE;
+
+ np = &buf[0];
+ while (*bp != '\0') {
+ char ch = *bp;
+
+ switch (ch) {
+ case '\\' :
+ if (!str_escape) {
+ str_escape = TRUE;
+ bp++;
+ continue;
+ }
+ break;
+ case '"' :
+ if (!str_escape) {
+ str_quote = !str_quote;
+ bp++;
+ continue;
+ }
+ break;
+ default :
+ break;
+ }
+
+ if (str_escape) {
+ str_escape = FALSE;
+ } else if (!str_quote && (isspace(ch) || (ch == '#'))) {
+ break;
+ }
+
+ *np++ = ch;
+ bp++;
+ }
+
+ *np = '\0';
+
+ if (name != NULL) {
+ CFRelease(name);
+ name = NULL;
+ }
+
+ if (str_quote) {
+ // the shell won't parse this file so neither will we
+ break;
+ }
+
+ if (strcmp(buf, AUTOMATIC) == 0) {
+ // skip "-AUTOMATIC-"
+ continue;
+ }
+
+ name = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
+ }
+
+ (void) fclose(f);
+ return name;
+}
+
+
+#ifndef kSCPropNetHostName
+#define kSCPropNetHostName CFSTR("HostName")
+#endif
+
+
+static CFStringRef
+copy_prefs_hostname(SCDynamicStoreRef store)
+{
+ CFDictionaryRef dict;
+ CFStringRef key;
+ CFStringRef name = NULL;
+
+ key = SCDynamicStoreKeyCreateComputerName(NULL);
+ dict = SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+ if (dict == NULL) {
+ goto done;
+ }
+ if (!isA_CFDictionary(dict)) {
+ goto done;
+ }
+
+ name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetHostName));
+ if (name == NULL) {
+ goto done;
+ }
+ CFRetain(name);
+
+ done :
+
+ if (dict != NULL) CFRelease(dict);
+
+ return name;
+}
+
+
+static CFStringRef
+copy_primary_service(SCDynamicStoreRef store)
+{
+ CFDictionaryRef dict;
+ CFStringRef key;
+ CFStringRef serviceID = NULL;
+
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv4);
+ dict = SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+
+ if (dict != NULL) {
+ if (isA_CFDictionary(dict)) {
+ serviceID = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryService);
+ if (isA_CFString(serviceID)) {
+ CFRetain(serviceID);
+ } else {
+ serviceID = NULL;
+ }
+ }
+ CFRelease(dict);
+ }
+
+ return serviceID;
+}
+
+
+static CFStringRef
+copy_primary_ip(SCDynamicStoreRef store, CFStringRef serviceID)
+{
+ CFDictionaryRef dict;
+ CFStringRef key;
+ CFStringRef address = NULL;
+
+ key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ serviceID,
+ kSCEntNetIPv4);
+ dict = SCDynamicStoreCopyValue(store, key);
+ CFRelease(key);
+
+ if (dict != NULL) {
+ if (isA_CFDictionary(dict)) {
+ CFArrayRef addresses;
+
+ addresses = CFDictionaryGetValue(dict, kSCPropNetIPv4Addresses);
+ if (isA_CFArray(addresses) && (CFArrayGetCount(addresses) > 0)) {
+ address = CFArrayGetValueAtIndex(addresses, 0);
+ if (isA_CFString(address)) {
+ CFRetain(address);
+ } else {
+ address = NULL;
+ }
+ }
+ }
+ CFRelease(dict);
+ }
+
+ return address;
+}
+
+
+#define DHCP_OPTION_HOSTNAME 12
+
+static CFStringRef
+copy_dhcp_name(SCDynamicStoreRef store, CFStringRef serviceID)
+{
+ CFDictionaryRef info;
+ CFStringRef name = NULL;
+
+ info = SCDynamicStoreCopyDHCPInfo(store, serviceID);
+ if (info != NULL) {
+ CFDataRef data;
+
+ data = DHCPInfoGetOptionData(info, DHCP_OPTION_HOSTNAME);
+ if (data != NULL) {
+ name = CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8);
+ }
+
+ CFRelease(info);
+ }
+
+ return name;
+}
+
+
+static void
+reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
+{
+ struct timeval dnsQueryComplete;
+ struct timeval dnsQueryElapsed;
+ CFStringRef hostname;
+ SCDynamicStoreRef store = (SCDynamicStoreRef)context;
+
+ (void) gettimeofday(&dnsQueryComplete, NULL);
+ timersub(&dnsQueryComplete, &dnsQueryStart, &dnsQueryElapsed);
+ SCLog(_verbose, LOG_INFO,
+ CFSTR("async DNS complete%s (query time = %d.%3.3d)"),
+ ((status == 0) && (host != NULL)) ? "" : ", host not found",
+ dnsQueryElapsed.tv_sec,
+ dnsQueryElapsed.tv_usec / 1000);
+
+ // use reverse DNS name, if available
+
+ switch (status) {
+ case 0 :
+ /*
+ * if [reverse] DNS query was successful
+ */
+ if (host != NULL) {
+ hostname = CFStringCreateWithCString(NULL, host, kCFStringEncodingUTF8);
+ SCLog(TRUE, LOG_INFO, CFSTR("hostname (reverse DNS query) = %@"), hostname);
+ set_hostname(hostname);
+ CFRelease(hostname);
+ goto done;
+ }
+ break;
+
+ case EAI_NONAME :
+ /*
+ * if no name available
+ */
+ break;
+
+ default :
+ /*
+ * Hmmmm...
+ */
+ SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo() failed: %s"), gai_strerror(status));
+ }
+
+ // get local (multicast DNS) name, if available
+
+ hostname = SCDynamicStoreCopyLocalHostName(store);
+ if (hostname != NULL) {
+ CFMutableStringRef localName;
+
+ SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
+ localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+ CFStringAppend(localName, CFSTR(".local"));
+ set_hostname(localName);
+ CFRelease(localName);
+ CFRelease(hostname);
+ goto done;
+ }
+
+ // use "localhost" if not other name is available
+
+ set_hostname(CFSTR("localhost"));
+
+ done :
+
+ if (host != NULL) free(host);
+ if (serv != NULL) free(serv);
+ return;
+}
+
+
+static void
+getnameinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
+{
+ getnameinfo_async_handle_reply(msg);
+
+ if (port == dnsPort) {
+ CFRelease(dnsRLS);
+ dnsRLS = NULL;
+ CFRelease(dnsPort);
+ dnsPort = NULL;
+ }
+
+ return;
+}
+
+
+static void
+start_dns_query(SCDynamicStoreRef store, CFStringRef address)
+{
+ char addr[64];
+ Boolean ok;
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+
+ if (_SC_cfstring_to_cstring(address, addr, sizeof(addr), kCFStringEncodingASCII) == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
+ return;
+ }
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+
+ if (inet_aton(addr, &sin.sin_addr) == 1) {
+ /*
+ * if IPv4 address
+ */
+ sa = (struct sockaddr *)&sin;
+ } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr) == 1) {
+ /*
+ * if IPv6 address
+ */
+ char *p;
+
+ p = strchr(addr, '%');
+ if (p != NULL) {
+ sin6.sin6_scope_id = if_nametoindex(p+1);
+ }
+
+ sa = (struct sockaddr *)&sin6;
+ } else {
+ goto done;
+ }
+
+ ok = checkResolverReachabilityByAddress(store, sa);
+ if (ok) {
+ CFMachPortContext context = { 0, (void *)store, CFRetain, CFRelease, CFCopyDescription };
+ mach_port_t port;
+ int32_t error;
+
+ if ((dnsPort != NULL) && (dnsRLS != NULL)) {
+ /* if we already have an active async DNS query */
+ lu_async_call_cancel(CFMachPortGetPort(dnsPort));
+ CFRelease(dnsRLS);
+ dnsRLS = NULL;
+ CFRelease(dnsPort);
+ dnsPort = NULL;
+ }
+
+ (void) gettimeofday(&dnsQueryStart, NULL);
+
+ error = getnameinfo_async_start(&port,
+ sa,
+ sa->sa_len,
+ 0, // flags
+ reverseDNSComplete,
+ NULL);
+ if (error != 0) {
+ goto done;
+ }
+
+ dnsPort = CFMachPortCreateWithPort(NULL,
+ port,
+ getnameinfo_async_handleCFReply,
+ &context,
+ NULL);
+ dnsRLS = CFMachPortCreateRunLoopSource(NULL, dnsPort, 0);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), dnsRLS, kCFRunLoopDefaultMode);
+ }
+
+ done :
+
+ return;
+}
+
+
+static void
+update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+ CFStringRef address = NULL;
+ CFStringRef hostname = NULL;
+ CFStringRef serviceID = NULL;
+
+ // get static hostname, if available
+
+ hostname = copy_static_name();
+ if (hostname != NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("hostname (static) = %@"), hostname);
+ set_hostname(hostname);
+ goto done;
+ }
+
+ // get [prefs] hostname, if available
+
+ hostname = copy_prefs_hostname(store);
+ if (hostname != NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("hostname (prefs) = %@"), hostname);
+ set_hostname(hostname);
+ goto done;
+ }
+
+ // get primary service ID
+
+ serviceID = copy_primary_service(store);
+ if (serviceID == NULL) {
+ goto mDNS;
+ }
+
+ // get DHCP provided name, if available
+
+ hostname = copy_dhcp_name(store, serviceID);
+ if (hostname != NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("hostname (DHCP) = %@"), hostname);
+ set_hostname(hostname);
+ goto done;
+ }
+
+ // get DNS name associated with primary IP, if available
+
+ address = copy_primary_ip(store, serviceID);
+ if (address != NULL) {
+ // start reverse DNS query using primary IP address
+ (void) start_dns_query(store, address);
+ goto done;
+ }
+
+ mDNS :
+
+ // get local (multicast DNS) name, if available
+
+ hostname = SCDynamicStoreCopyLocalHostName(store);
+ if (hostname != NULL) {
+ CFMutableStringRef localName;
+
+ SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
+ localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+ CFStringAppend(localName, CFSTR(".local"));
+ set_hostname(localName);
+ CFRelease(localName);
+ goto done;
+ }
+
+ // use "localhost" if not other name is available
+
+ set_hostname(CFSTR("localhost"));
+
+ done :
+
+ if (address) CFRelease(address);
+ if (hostname) CFRelease(hostname);
+ if (serviceID) CFRelease(serviceID);
+
+ return;
+}
+
+
+__private_extern__
+void
+load_hostname(Boolean verbose)
+{
+ CFStringRef key;
+ CFMutableArrayRef keys = NULL;
+ CFMutableArrayRef patterns = NULL;
+
+ if (verbose) {
+ _verbose = TRUE;
+ }
+
+ /* initialize a few globals */
+
+ store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), update_hostname, NULL);
+ if (store == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreCreate() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ /* establish notification keys and patterns */
+
+ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ /* ...watch for primary service / interface changes */
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv4);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ /* ...watch for DNS configuration changes */
+ key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCEntNetDNS);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ /* ...watch for (per-service) DHCP option changes */
+ key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetDHCP);
+ CFArrayAppendValue(patterns, key);
+ CFRelease(key);
+
+ /* ...watch for (BSD) hostname changes */
+ key = SCDynamicStoreKeyCreateComputerName(NULL);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ /* ...watch for local (multicast DNS) hostname changes */
+ key = SCDynamicStoreKeyCreateHostNames(NULL);
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ /* register the keys/patterns */
+ if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+ if (!rls) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+
+ CFRelease(keys);
+ CFRelease(patterns);
+ return;
+
+ error :
+
+ if (keys != NULL) CFRelease(keys);
+ if (patterns != NULL) CFRelease(patterns);
+ if (store != NULL) CFRelease(store);
+ return;
+}
+
+
+#ifdef MAIN
+int
+main(int argc, char **argv)
+{
+
+#ifdef DEBUG
+
+ _sc_log = FALSE;
+ if ((argc > 1) && (strcmp(argv[1], "-d") == 0)) {
+ _sc_verbose = TRUE;
+ argv++;
+ argc--;
+ }
+
+ CFStringRef address;
+ CFStringRef hostname;
+ CFStringRef serviceID;
+ SCDynamicStoreRef store;
+
+ store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), NULL, NULL);
+ if (store == NULL) {
+ SCPrint(TRUE, stdout,
+ CFSTR("SCDynamicStoreCreate() failed: %s\n"),
+ SCErrorString(SCError()));
+ exit(1);
+ }
+
+ // get static hostname
+ hostname = copy_static_name();
+ if (hostname != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("hostname (static) = %@\n"), hostname);
+ CFRelease(hostname);
+ }
+
+ // get [prefs] hostname, if available
+ hostname = copy_prefs_hostname(store);
+ if (hostname != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("hostname (prefs) = %@\n"), hostname);
+ CFRelease(hostname);
+ }
+
+ // get primary service
+ serviceID = copy_primary_service(store);
+ if (serviceID != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("primary service ID = %@\n"), serviceID);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No primary service\n"));
+ goto mDNS;
+ }
+
+ if ((argc == (2+1)) && (argv[1][0] == 's')) {
+ if (serviceID != NULL) CFRelease(serviceID);
+ serviceID = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
+ SCPrint(TRUE, stdout, CFSTR("alternate service ID = %@\n"), serviceID);
+ }
+
+ // get DHCP provided name
+ hostname = copy_dhcp_name(store, serviceID);
+ if (hostname != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("hostname (DHCP) = %@\n"), hostname);
+ CFRelease(hostname);
+ }
+
+ // get primary IP address
+ address = copy_primary_ip(store, serviceID);
+ if (address != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("primary address = %@\n"), address);
+
+ if ((argc == (2+1)) && (argv[1][0] == 'a')) {
+ if (address != NULL) CFRelease(address);
+ address = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
+ SCPrint(TRUE, stdout, CFSTR("alternate primary address = %@\n"), address);
+ }
+
+ // start reverse DNS query using primary IP address
+ start_dns_query(store, address);
+ CFRelease(address);
+ }
+
+ CFRelease(serviceID);
+
+ mDNS :
+
+ // get local (multicast DNS) name, if available
+
+ hostname = SCDynamicStoreCopyLocalHostName(store);
+ if (hostname != NULL) {
+ CFMutableStringRef localName;
+
+ SCPrint(TRUE, stdout, CFSTR("hostname (multicast DNS) = %@\n"), hostname);
+ localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+ CFStringAppend(localName, CFSTR(".local"));
+ CFRelease(localName);
+ }
+
+ if (hostname != NULL) CFRelease(hostname);
+
+ update_hostname(store, NULL, NULL);
+
+ CFRelease(store);
+
+ CFRunLoopRun();
+
+#else /* DEBUG */
+
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_hostname((argc > 1) ? TRUE : FALSE);
+ CFRunLoopRun();
+ /* not reached */
+
+#endif /* DEBUG */
+
+ exit(0);
+ return 0;
+}
+#endif /* MAIN */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>InterfaceNamer</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Builtin</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2001-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * October 3, 2003 Allan Nathanson <ajn@apple.com>
+ * - sort new interfaces by IOKit path (rather than MAC address) to
+ * help facilitate a more predictable interface-->name mapping for
+ * like hardware configurations.
+ *
+ * June 23, 2001 Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * January 23, 2001 Dieter Siegmund <dieter@apple.com>
+ * - initial revision
+ */
+
+/*
+ * ifnamer.c
+ * - module that receives IOKit Network Interface messages
+ * and names any interface that currently does not have a name
+ * - uses Interface Type and MACAddress as the unique identifying
+ * keys; any interface that doesn't contain both of these properties
+ * is ignored and not processed
+ * - stores the Interface Type, MACAddress, and Unit in permanent storage
+ * to give persistent interface names
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/sockio.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <mach/mach.h>
+#include <net/if_types.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCDPlugin.h>
+#include <SystemConfiguration/SCPrivate.h> // for SCLog(), SCPrint()
+#include <SystemConfiguration/SCValidation.h>
+
+#include <SystemConfiguration/BondConfiguration.h>
+#include <SystemConfiguration/BondConfigurationPrivate.h>
+
+#include <SystemConfiguration/VLANConfiguration.h>
+#include <SystemConfiguration/VLANConfigurationPrivate.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/network/IONetworkController.h>
+#include <IOKit/network/IONetworkInterface.h>
+
+#ifndef kIOBuiltin
+#define kIOBuiltin "IOBuiltin"
+#endif
+
+#ifndef kIOLocation
+#define kIOLocation "IOLocation"
+#endif
+
+#define kIONetworkStackUserCommand "IONetworkStackUserCommand"
+#define kIORegisterOne 1
+
+#define MY_PLUGIN_NAME "InterfaceNamer"
+
+static boolean_t S_debug = FALSE;
+static CFMutableArrayRef S_dblist = NULL;
+static io_connect_t S_connect = MACH_PORT_NULL;
+static io_iterator_t S_iter = MACH_PORT_NULL;
+static IONotificationPortRef S_notify = NULL;
+
+static void
+writeInterfaceList(CFArrayRef ilist);
+
+static void
+displayInterface(CFDictionaryRef if_dict);
+
+static CFDictionaryRef
+lookupIOKitPath(CFStringRef if_path);
+
+static __inline__ CFComparisonResult
+compareMacAddress(CFDataRef addr1, CFDataRef addr2)
+{
+ int len1;
+ int len2;
+ int clen;
+ int res;
+
+ len1 = CFDataGetLength(addr1);
+ len2 = CFDataGetLength(addr2);
+
+ if (len1 == len2) {
+ if (len1 == 0)
+ return (kCFCompareEqualTo);
+ return (memcmp(CFDataGetBytePtr(addr1),
+ CFDataGetBytePtr(addr2),
+ len1));
+ }
+ clen = len1;
+ if (len2 < clen)
+ clen = len2;
+ res = memcmp(CFDataGetBytePtr(addr1),
+ CFDataGetBytePtr(addr2),
+ clen);
+ if (res == 0) {
+ return (len1 - len2);
+ }
+ return (res);
+}
+
+static CFComparisonResult
+if_unit_compare(const void *val1, const void *val2, void *context)
+{
+ CFComparisonResult res;
+ CFNumberRef type1;
+ CFNumberRef type2;
+ CFNumberRef unit1;
+ CFNumberRef unit2;
+
+ type1 = CFDictionaryGetValue((CFDictionaryRef)val1,
+ CFSTR(kIOInterfaceType));
+ type2 = CFDictionaryGetValue((CFDictionaryRef)val2,
+ CFSTR(kIOInterfaceType));
+ res = CFNumberCompare(type1, type2, NULL);
+ if (res != kCFCompareEqualTo) {
+ return (res);
+ }
+ unit1 = CFDictionaryGetValue((CFDictionaryRef)val1,
+ CFSTR(kIOInterfaceUnit));
+ unit2 = CFDictionaryGetValue((CFDictionaryRef)val2,
+ CFSTR(kIOInterfaceUnit));
+ return (CFNumberCompare(unit1, unit2, NULL));
+}
+
+static CFArrayRef
+split_path(CFStringRef path)
+{
+ CFArrayRef components;
+ CFMutableStringRef nPath;
+
+ // turn '@'s into '/'s
+ nPath = CFStringCreateMutableCopy(NULL, 0, path);
+ (void) CFStringFindAndReplace(nPath,
+ CFSTR("@"),
+ CFSTR("/"),
+ CFRangeMake(0, CFStringGetLength(nPath)),
+ 0);
+
+ // split path into components to be compared
+ components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
+ CFRelease(nPath);
+
+ return components;
+}
+
+
+static CFComparisonResult
+if_path_compare(const void *val1, const void *val2, void *context)
+{
+ CFBooleanRef builtin;
+ Boolean builtin_val1 = FALSE;
+ Boolean builtin_val2 = FALSE;
+ CFArrayRef elements1 = NULL;
+ CFArrayRef elements2 = NULL;
+ CFIndex i;
+ CFIndex n;
+ CFIndex n1 = 0;
+ CFIndex n2 = 0;
+ CFStringRef path;
+ CFComparisonResult res;
+ CFNumberRef type1;
+ CFNumberRef type2;
+
+ /* sort by interface type */
+
+ type1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOInterfaceType));
+ type2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOInterfaceType));
+ res = CFNumberCompare(type1, type2, NULL);
+ if (res != kCFCompareEqualTo) {
+ return (res);
+ }
+
+ /* built-in interfaces sort first */
+ builtin = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOBuiltin));
+ if (isA_CFBoolean(builtin) != NULL) {
+ builtin_val1 = CFBooleanGetValue(builtin);
+ }
+ builtin = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOBuiltin));
+ if (isA_CFBoolean(builtin) != NULL) {
+ builtin_val2 = CFBooleanGetValue(builtin);
+ }
+ if (builtin_val1 != builtin_val2) {
+ if (builtin_val1) {
+ res = kCFCompareLessThan;
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+ return (res);
+ }
+
+ /* ... and then sort built-in interfaces by "location" */
+ if (builtin_val1) {
+ CFStringRef location1;
+ CFStringRef location2;
+
+ location1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOLocation));
+ location2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOLocation));
+ if (location1 != location2) {
+ if (isA_CFString(location1)) {
+ if (isA_CFString(location2)) {
+ res = CFStringCompare(location1, location2, 0);
+ } else {
+ res = kCFCompareLessThan;
+ }
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+
+ if (res != kCFCompareEqualTo) {
+ return (res);
+ }
+ }
+ }
+
+ /* ... and then sort by IOPathMatch */
+
+ path = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOPathMatchKey));
+ if (isA_CFString(path)) {
+ elements1 = split_path(path);
+ n1 = CFArrayGetCount(elements1);
+ } else {
+ goto done;
+ }
+
+ path = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOPathMatchKey));
+ if (isA_CFString(path)) {
+ elements2 = split_path(path);
+ n2 = CFArrayGetCount(elements2);
+ } else {
+ goto done;
+ }
+
+ n = (n1 <= n2) ? n1 : n2;
+ for (i = 0; i < n; i++) {
+ CFStringRef e1;
+ CFStringRef e2;
+ char *end;
+ quad_t q1;
+ quad_t q2;
+ char *str;
+ Boolean isNum;
+
+ e1 = CFArrayGetValueAtIndex(elements1, i);
+ e2 = CFArrayGetValueAtIndex(elements2, i);
+
+ str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingASCII);
+ errno = 0;
+ q1 = strtoq(str, &end, 16);
+ isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+ CFAllocatorDeallocate(NULL, str);
+
+ if (isNum) {
+ // if e1 is a valid numeric string
+ str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingASCII);
+ errno = 0;
+ q2 = strtoq(str, &end, 16);
+ isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+ CFAllocatorDeallocate(NULL, str);
+
+ if (isNum) {
+ // if e2 is also a valid numeric string
+
+ if (q1 == q2) {
+ res = kCFCompareEqualTo;
+ continue;
+ } else if (q1 < q2) {
+ res = kCFCompareLessThan;
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+ break;
+ }
+ }
+
+ res = CFStringCompare(e1, e2, 0);
+ if (res != kCFCompareEqualTo) {
+ break;
+ }
+ }
+
+ if (res == kCFCompareEqualTo) {
+ if (n1 < n2) {
+ res = kCFCompareLessThan;
+ } else if (n1 < n2) {
+ res = kCFCompareGreaterThan;
+ }
+ }
+
+ done :
+ if ( elements1 ) CFRelease( elements1 );
+ if ( elements2 ) CFRelease( elements2 );
+
+ return res;
+}
+
+static boolean_t
+addCFStringProperty( CFMutableDictionaryRef dict,
+ const char * key,
+ const char * string )
+{
+ boolean_t ret = false;
+ CFStringRef valObj, keyObj;
+
+ if ( (string == 0) || (key == 0) || (dict == 0) )
+ return false;
+
+ keyObj = CFStringCreateWithCString(NULL,
+ key,
+ kCFStringEncodingASCII );
+
+ valObj = CFStringCreateWithCString(NULL,
+ string,
+ kCFStringEncodingASCII );
+
+ if (valObj && keyObj) {
+ CFDictionarySetValue( dict, keyObj, valObj );
+ ret = true;
+ }
+
+ if ( keyObj ) CFRelease( keyObj );
+ if ( valObj ) CFRelease( valObj );
+
+ return ret;
+}
+
+static boolean_t
+addCFNumberProperty( CFMutableDictionaryRef dict,
+ const char * key,
+ unsigned int number )
+{
+ boolean_t ret = false;
+ CFNumberRef numObj;
+ CFStringRef keyObj;
+
+ if ( (key == 0) || (dict == 0) )
+ return false;
+
+ numObj = CFNumberCreate(NULL,
+ kCFNumberLongType,
+ &number);
+
+ keyObj = CFStringCreateWithCString(NULL,
+ key,
+ kCFStringEncodingASCII );
+
+ if ( numObj && keyObj )
+ {
+ CFDictionarySetValue( dict, keyObj, numObj );
+ ret = true;
+ }
+
+ if ( numObj ) CFRelease( numObj );
+ if ( keyObj ) CFRelease( keyObj );
+
+ return ret;
+}
+
+static void *
+read_file(char * filename, size_t * data_length)
+{
+ void * data = NULL;
+ size_t len = 0;
+ int fd = -1;
+ struct stat sb;
+
+ *data_length = 0;
+ if (stat(filename, &sb) < 0)
+ goto done;
+ len = sb.st_size;
+ if (len == 0)
+ goto done;
+
+ data = malloc(len);
+ if (data == NULL)
+ goto done;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto done;
+
+ if (read(fd, data, len) != len) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": read %s failed, %s"),
+ filename, strerror(errno));
+ goto done;
+ }
+ done:
+ if (fd >= 0)
+ close(fd);
+ if (data) {
+ *data_length = len;
+ }
+ return (data);
+}
+
+static CFPropertyListRef
+readPropertyList(char * filename)
+{
+ void * buf;
+ size_t bufsize;
+ CFDataRef data = NULL;
+ CFPropertyListRef plist = NULL;
+ CFStringRef errorString = NULL;
+
+ buf = read_file(filename, &bufsize);
+ if (buf == NULL) {
+ return (NULL);
+ }
+ data = CFDataCreate(NULL, buf, bufsize);
+ if (data == NULL) {
+ goto error;
+ }
+
+ plist = CFPropertyListCreateFromXMLData(NULL, data,
+ kCFPropertyListMutableContainers,
+ &errorString);
+ if (plist == NULL) {
+ if (errorString) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ":%@"),
+ errorString);
+ CFRelease(errorString);
+ }
+ }
+ error:
+ if (data)
+ CFRelease(data);
+ if (buf)
+ free(buf);
+ return (plist);
+}
+
+#define IFNAMER_ID CFSTR("com.apple.SystemConfiguration.InterfaceNamer")
+#define INTERFACES CFSTR("Interfaces")
+#define NETWORK_INTERFACES_PREFS CFSTR("NetworkInterfaces.plist")
+#define OLD_NETWORK_INTERFACES_FILE "/var/db/NetworkInterfaces.xml"
+
+static CFMutableArrayRef
+readInterfaceList()
+{
+ CFArrayRef ilist;
+ CFMutableArrayRef plist = NULL;
+ SCPreferencesRef prefs = NULL;
+
+ prefs = SCPreferencesCreate(NULL, IFNAMER_ID, NETWORK_INTERFACES_PREFS);
+ if (!prefs) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
+ SCErrorString(SCError()));
+ return (NULL);
+ }
+
+ ilist = SCPreferencesGetValue(prefs, INTERFACES);
+ if (isA_CFArray(ilist)) {
+ plist = CFArrayCreateMutableCopy(NULL, 0, ilist);
+ } else {
+ plist = (CFMutableArrayRef)readPropertyList(OLD_NETWORK_INTERFACES_FILE);
+ if (plist == NULL) {
+ goto done;
+ }
+ if (isA_CFArray(plist) == NULL) {
+ CFRelease(plist);
+ goto done;
+ }
+ writeInterfaceList(plist);
+ (void)unlink(OLD_NETWORK_INTERFACES_FILE);
+ }
+
+ done:
+ if (prefs) {
+ CFRelease(prefs);
+ }
+ return (plist);
+}
+
+static void
+writeInterfaceList(CFArrayRef ilist)
+{
+ SCPreferencesRef prefs;
+
+ if (isA_CFArray(ilist) == NULL) {
+ return;
+ }
+
+ prefs = SCPreferencesCreate(NULL, IFNAMER_ID, NETWORK_INTERFACES_PREFS);
+ if (prefs == NULL) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
+ SCErrorString(SCError()));
+ return;
+ }
+
+ if (!SCPreferencesSetValue(prefs, INTERFACES, ilist)) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": SCPreferencesSetValue failed, %s"),
+ SCErrorString(SCError()));
+ goto done;
+ }
+
+ if (!SCPreferencesCommitChanges(prefs)) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": SCPreferencesCommitChanges failed, %s"),
+ SCErrorString(SCError()));
+ goto done;
+ }
+
+done:
+
+ CFRelease(prefs);
+ return;
+}
+
+static void
+updateBondConfiguration(void)
+{
+ BondPreferencesRef prefs;
+
+ prefs = BondPreferencesCreate(NULL);
+ if (prefs == NULL) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": BondPreferencesCreate failed, %s"),
+ SCErrorString(SCError()));
+ return;
+ }
+
+ if (!_BondPreferencesUpdateConfiguration(prefs)) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": _BondPreferencesUpdateConfiguration failed, %s"),
+ SCErrorString(SCError()));
+ goto done;
+ }
+
+done:
+
+ CFRelease(prefs);
+ return;
+}
+
+static void
+updateVLANConfiguration(void)
+{
+ VLANPreferencesRef prefs;
+
+ prefs = VLANPreferencesCreate(NULL);
+ if (prefs == NULL) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": VLANPreferencesCreate failed, %s"),
+ SCErrorString(SCError()));
+ return;
+ }
+
+ if (!_VLANPreferencesUpdateConfiguration(prefs)) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": _VLANPreferencesUpdateConfiguration failed, %s"),
+ SCErrorString(SCError()));
+ goto done;
+ }
+
+done:
+
+ CFRelease(prefs);
+ return;
+}
+
+#define INDEX_BAD (-1)
+
+static CFDictionaryRef
+lookupInterfaceByType(CFArrayRef list, CFDictionaryRef if_dict, int * where)
+{
+ CFDataRef addr;
+ CFIndex i;
+ CFIndex n;
+ CFNumberRef type;
+
+ if (where) {
+ *where = INDEX_BAD;
+ }
+ if (list == NULL) {
+ return (NULL);
+ }
+ addr = CFDictionaryGetValue(if_dict, CFSTR(kIOMACAddress));
+ type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+ if (type == NULL || addr == NULL) {
+ return (NULL);
+ }
+
+ n = CFArrayGetCount(list);
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+ CFDataRef a;
+ CFNumberRef t;
+
+ a = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+ t = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+ if (a == NULL || t == NULL)
+ continue;
+
+ if (CFNumberCompare(type, t, NULL) == kCFCompareEqualTo
+ && compareMacAddress(addr, a) == kCFCompareEqualTo) {
+ if (where) {
+ *where = i;
+ }
+ return (dict);
+ }
+ }
+ return (NULL);
+}
+
+static CFDictionaryRef
+lookupInterfaceByUnit(CFArrayRef list, CFDictionaryRef if_dict, int * where)
+{
+ CFIndex i;
+ CFIndex n;
+ CFNumberRef type;
+ CFNumberRef unit;
+
+ if (where) {
+ *where = INDEX_BAD;
+ }
+ if (list == NULL) {
+ return (NULL);
+ }
+ type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+ unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+ if (type == NULL || unit == NULL) {
+ return (NULL);
+ }
+
+ n = CFArrayGetCount(list);
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+ CFNumberRef t;
+ CFNumberRef u;
+
+ t = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+ u = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+ if (t == NULL || u == NULL) {
+ continue;
+ }
+
+ if (CFNumberCompare(type, t, NULL) == kCFCompareEqualTo
+ && CFNumberCompare(unit, u, NULL) == kCFCompareEqualTo) {
+ if (where)
+ *where = i;
+ return (dict);
+ }
+ }
+ return (NULL);
+}
+
+#define kAirPortDriverPath CFSTR("AirPort")
+#define kIO80211InterfacePath CFSTR("IO80211Interface")
+#define APPLE_WIRELESS_80211 CFSTR("AppleWireless80211")
+
+static __inline__ boolean_t
+pathIsAirPort(CFStringRef path)
+{
+ CFRange r;
+
+ r = CFStringFind(path, kIO80211InterfacePath, 0);
+ if (r.location != kCFNotFound) {
+ return (TRUE);
+ }
+
+ r = CFStringFind(path, kAirPortDriverPath, 0);
+ if (r.location != kCFNotFound) {
+ return (TRUE);
+ }
+
+ r = CFStringFind(path, APPLE_WIRELESS_80211, 0);
+ if (r.location != kCFNotFound) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+static CFDictionaryRef
+lookupAirPortInterface(CFArrayRef list, int * where)
+{
+ CFIndex i;
+ CFIndex n;
+
+ if (where) {
+ *where = INDEX_BAD;
+ }
+ if (list == NULL) {
+ return (NULL);
+ }
+ n = CFArrayGetCount(list);
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+ CFStringRef path;
+
+ path = CFDictionaryGetValue(dict, CFSTR(kIOPathMatchKey));
+ if (path == NULL) {
+ continue;
+ }
+ if (pathIsAirPort(path) == TRUE) {
+ if (where)
+ *where = i;
+ return (dict);
+ }
+ }
+ return (NULL);
+}
+
+static void
+insertInterface(CFMutableArrayRef list, CFDictionaryRef if_dict)
+{
+ CFIndex i;
+ CFNumberRef if_type;
+ CFNumberRef if_unit;
+ CFIndex n = CFArrayGetCount(list);
+ CFComparisonResult res;
+
+ if_type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+ if_unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+ CFNumberRef type;
+ CFNumberRef unit;
+
+ type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+ unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+ res = CFNumberCompare(if_type, type, NULL);
+ if (res == kCFCompareLessThan
+ || (res == kCFCompareEqualTo
+ && (CFNumberCompare(if_unit, unit, NULL)
+ == kCFCompareLessThan))) {
+ CFArrayInsertValueAtIndex(list, i, if_dict);
+ return;
+ }
+ }
+ CFArrayAppendValue(S_dblist, if_dict);
+ return;
+}
+
+static void
+replaceInterface(CFDictionaryRef if_dict)
+{
+ int where;
+
+ if (S_dblist == NULL) {
+ S_dblist = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+ }
+ /* remove any dict that has our type/addr */
+ if (lookupInterfaceByType(S_dblist, if_dict, &where) != NULL) {
+ CFArrayRemoveValueAtIndex(S_dblist, where);
+ }
+ /* remove any dict that has the same type/unit */
+ if (lookupInterfaceByUnit(S_dblist, if_dict, &where) != NULL) {
+ CFArrayRemoveValueAtIndex(S_dblist, where);
+ }
+ insertInterface(S_dblist, if_dict);
+ return;
+}
+
+static CFNumberRef
+getHighestUnitForType(CFNumberRef if_type)
+{
+ int i;
+ CFIndex n;
+ CFNumberRef ret_unit = NULL;
+
+ if (S_dblist == NULL)
+ return (NULL);
+
+ n = CFArrayGetCount(S_dblist);
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef dict = CFArrayGetValueAtIndex(S_dblist, i);
+ CFNumberRef type;
+ CFNumberRef unit;
+
+ type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+ if (CFEqual(type, if_type)) {
+ unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+ if (ret_unit == NULL
+ || (CFNumberCompare(unit, ret_unit, NULL)
+ == kCFCompareGreaterThan)) {
+ ret_unit = unit;
+ }
+ }
+ }
+ return (ret_unit);
+}
+
+//------------------------------------------------------------------------
+// Register a single interface with the given service path to the
+// data link layer (BSD), using the specified unit number.
+
+static kern_return_t
+registerInterface(io_connect_t connect,
+ CFStringRef path,
+ CFNumberRef unit)
+{
+ CFMutableDictionaryRef dict;
+ kern_return_t kr = kIOReturnNoMemory;
+
+ dict = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (dict == NULL
+ || addCFNumberProperty(dict, kIONetworkStackUserCommand,
+ kIORegisterOne) == FALSE)
+ ;
+ else {
+ CFDictionarySetValue(dict, CFSTR(kIOPathMatchKey), path);
+ CFDictionarySetValue(dict, CFSTR(kIOInterfaceUnit), unit);
+ kr = IOConnectSetCFProperties(connect, dict);
+ }
+ if (dict) CFRelease( dict );
+ return kr;
+}
+
+/*
+ * Note: this function blocks all other plug-ins until it completes
+ */
+static void
+waitForQuiet(mach_port_t masterPort)
+{
+ mach_timespec_t t;
+ kern_return_t wait_ret;
+
+ t.tv_sec = 4;
+ t.tv_nsec = 0;
+
+ // kIOReturnTimeout if the wait timed out.
+ // kIOReturnSuccess on success.
+ wait_ret = IOKitWaitQuiet(masterPort, &t);
+ return;
+}
+
+/*
+ * Function: createNetworkStackObject
+ * Purpose:
+ * Get a reference to the single IONetworkStack object instance in
+ * the kernel. Naming requests must be sent to this object, which is
+ * attached as a client to all network interface objects in the system.
+ * Note:
+ * Call IOObjectRelease on the returned object.
+ */
+static io_object_t
+createNetworkStackObject(mach_port_t masterPort)
+{
+ io_iterator_t iter = MACH_PORT_NULL;
+ kern_return_t kr;
+ io_object_t stack = MACH_PORT_NULL;
+
+ kr = IOServiceGetMatchingServices(masterPort,
+ IOServiceMatching("IONetworkStack"),
+ &iter);
+ if (iter != MACH_PORT_NULL) {
+ if (kr == KERN_SUCCESS) {
+ stack = IOIteratorNext(iter);
+ }
+ IOObjectRelease(iter);
+ }
+ return stack;
+}
+
+static void
+printMacAddress(CFDataRef data)
+{
+ int i;
+ CFIndex n = CFDataGetLength(data);
+
+ for (i = 0; i < n; i++) {
+ if (i != 0) SCPrint(TRUE, stdout, CFSTR(":"));
+ SCPrint(TRUE, stdout, CFSTR("%02x"), CFDataGetBytePtr(data)[i]);
+ }
+ return;
+}
+
+/*
+ * Function: getMacAddress
+ *
+ * Purpose:
+ * Given an interface object if_obj, return its associated mac address.
+ * The mac address is stored in the parent, the network controller object.
+ *
+ * Returns:
+ * The CFDataRef containing the bytes of the mac address.
+ */
+static CFDataRef
+getMacAddress(io_object_t if_obj)
+{
+ CFMutableDictionaryRef dict = NULL;
+ CFDataRef data = NULL;
+ kern_return_t kr;
+ io_object_t parent_obj = MACH_PORT_NULL;
+
+ /* get the parent node */
+ kr = IORegistryEntryGetParentEntry(if_obj, kIOServicePlane, &parent_obj);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": IORegistryEntryGetParentEntry returned 0x%x"),
+ kr);
+ goto failed;
+ }
+
+ /* get the dictionary associated with the node */
+ kr = IORegistryEntryCreateCFProperties(parent_obj,
+ &dict,
+ NULL,
+ kNilOptions );
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": IORegistryEntryCreateCFProperties returned 0x%x"),
+ kr);
+ goto failed;
+ }
+ data = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+ if (data) {
+ CFRetain(data);
+ }
+
+ failed:
+ if (dict)
+ CFRelease(dict);
+ if (parent_obj)
+ IOObjectRelease(parent_obj);
+ return (data);
+}
+
+static CFDictionaryRef
+getInterface(io_object_t if_obj)
+{
+ CFBooleanRef builtin;
+ kern_return_t kr;
+ CFDataRef mac_address = NULL;
+ CFStringRef location;
+ CFMutableDictionaryRef new_if = NULL;
+ io_string_t path;
+ CFMutableDictionaryRef reginfo_if = NULL;
+ CFDictionaryRef ret_dict = NULL;
+ CFStringRef string;
+ CFNumberRef type;
+ CFNumberRef unit;
+
+ kr = IORegistryEntryGetPath(if_obj, kIOServicePlane, path);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": IORegistryEntryGetPath returned 0x%x"),
+ kr);
+ goto failed;
+ }
+ kr = IORegistryEntryCreateCFProperties(if_obj,
+ ®info_if,
+ NULL,
+ kNilOptions);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": IORegistryEntryCreateCFProperties returned 0x%x"),
+ kr);
+ goto failed;
+ }
+ type = isA_CFNumber(CFDictionaryGetValue(reginfo_if,
+ CFSTR(kIOInterfaceType)));
+ if (type == NULL) {
+ goto failed;
+ }
+ mac_address = getMacAddress(if_obj);
+ if (mac_address == NULL) {
+ goto failed;
+ }
+ builtin = isA_CFBoolean(CFDictionaryGetValue(reginfo_if,
+ CFSTR(kIOBuiltin)));
+ if ((builtin == NULL) || !CFBooleanGetValue(builtin)) {
+ builtin = isA_CFBoolean(CFDictionaryGetValue(reginfo_if,
+ CFSTR(kIOPrimaryInterface)));
+ }
+ location = isA_CFString(CFDictionaryGetValue(reginfo_if,
+ CFSTR(kIOLocation)));
+
+ new_if = CFDictionaryCreateMutable(NULL, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (new_if == NULL) {
+ goto failed;
+ }
+ CFDictionarySetValue(new_if, CFSTR(kIOInterfaceType), type);
+ CFDictionarySetValue(new_if, CFSTR(kIOMACAddress), mac_address);
+ if (builtin) {
+ CFDictionarySetValue(new_if, CFSTR(kIOBuiltin), builtin);
+ }
+ if (location) {
+ CFDictionarySetValue(new_if, CFSTR(kIOLocation), location);
+ }
+ addCFStringProperty(new_if, kIOPathMatchKey, path);
+
+ unit = isA_CFNumber(CFDictionaryGetValue(reginfo_if,
+ CFSTR(kIOInterfaceUnit)));
+ if (unit) {
+ CFDictionarySetValue(new_if, CFSTR(kIOInterfaceUnit), unit);
+ }
+ string = isA_CFString(CFDictionaryGetValue(reginfo_if, CFSTR(kIOBSDNameKey)));
+ if (string) {
+ CFDictionarySetValue(new_if, CFSTR(kIOBSDNameKey), string);
+ }
+ ret_dict = new_if;
+ new_if = NULL;
+
+ failed:
+ if (new_if) {
+ CFRelease(new_if);
+ }
+ if (reginfo_if) {
+ CFRelease(reginfo_if);
+ }
+ if (mac_address) {
+ CFRelease(mac_address);
+ }
+ return (ret_dict);
+}
+
+static CFDictionaryRef
+lookupIOKitPath(CFStringRef if_path)
+{
+ CFDictionaryRef dict = NULL;
+ io_registry_entry_t entry = MACH_PORT_NULL;
+ kern_return_t kr;
+ mach_port_t masterPort = MACH_PORT_NULL;
+ io_string_t path;
+
+ kr = IOMasterPort(bootstrap_port, &masterPort);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x\n"),
+ kr);
+ goto error;
+ }
+ _SC_cfstring_to_cstring(if_path, path, sizeof(path), kCFStringEncodingASCII);
+ entry = IORegistryEntryFromPath(masterPort, path);
+ if (entry == MACH_PORT_NULL) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": IORegistryEntryFromPath(%@) failed"),
+ if_path);
+ goto error;
+ }
+ dict = getInterface(entry);
+
+ error:
+ if (masterPort != MACH_PORT_NULL) {
+ mach_port_deallocate(mach_task_self(), masterPort);
+ }
+ if (entry != MACH_PORT_NULL) {
+ IOObjectRelease(entry);
+ }
+ return (dict);
+
+}
+
+static void
+displayInterface(CFDictionaryRef if_dict)
+{
+ CFStringRef name;
+ CFNumberRef type;
+ CFNumberRef unit;
+
+ name = CFDictionaryGetValue(if_dict, CFSTR(kIOBSDNameKey));
+ if (name) {
+ SCPrint(TRUE, stdout, CFSTR("BSD Name: %@\n"), name);
+ }
+
+ unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+ if (unit) {
+ SCPrint(TRUE, stdout, CFSTR("Unit: %@\n"), unit);
+ }
+
+ type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+ SCPrint(TRUE, stdout, CFSTR("Type: %@\n"), type);
+
+ SCPrint(TRUE, stdout, CFSTR("MAC address: "));
+ printMacAddress(CFDictionaryGetValue(if_dict, CFSTR(kIOMACAddress)));
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+}
+
+static void
+sort_interfaces_by_unit(CFMutableArrayRef if_list)
+{
+ int count = CFArrayGetCount(if_list);
+ CFRange range = CFRangeMake(0, count);
+
+ if (count < 2)
+ return;
+ CFArraySortValues(if_list, range, if_unit_compare, NULL);
+ return;
+}
+
+static void
+sort_interfaces_by_path(CFMutableArrayRef if_list)
+{
+ int count = CFArrayGetCount(if_list);
+ CFRange range = CFRangeMake(0, count);
+
+ if (count < 2)
+ return;
+ CFArraySortValues(if_list, range, if_path_compare, NULL);
+ return;
+}
+
+static void
+name_interfaces(CFArrayRef if_list)
+{
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(if_list);
+ CFIndex i_builtin = 0;
+ CFIndex n_builtin = 0;
+
+ if (S_debug)
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ for (i = 0; i < n; i++) {
+ CFBooleanRef builtin;
+ CFDictionaryRef if_dict;
+
+ if_dict = CFArrayGetValueAtIndex(if_list, i);
+ builtin = CFDictionaryGetValue(if_dict, CFSTR(kIOBuiltin));
+ if (builtin && CFBooleanGetValue(builtin)) {
+ n_builtin++; // reserve unit number for built-in interface
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef if_dict;
+ CFNumberRef type;
+ CFNumberRef unit;
+
+ if (S_debug) {
+ if (i != 0)
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ }
+
+ if_dict = CFArrayGetValueAtIndex(if_list, i);
+ unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+ type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+ if (unit) {
+ if (S_debug) {
+ SCPrint(TRUE, stdout, CFSTR("Interface already has a unit number\n"));
+ displayInterface(if_dict);
+ }
+ replaceInterface(if_dict);
+ }
+ else {
+ CFDictionaryRef dbdict = NULL;
+ kern_return_t kr = KERN_SUCCESS;
+ CFStringRef path;
+ CFNumberRef unit = NULL;
+
+ path = CFDictionaryGetValue(if_dict, CFSTR(kIOPathMatchKey));
+ dbdict = lookupInterfaceByType(S_dblist, if_dict, NULL);
+ if (dbdict == NULL
+ && pathIsAirPort(path) == TRUE) {
+ dbdict = lookupAirPortInterface(S_dblist, NULL);
+ }
+ if (dbdict != NULL) {
+ unit = CFDictionaryGetValue(dbdict,
+ CFSTR(kIOInterfaceUnit));
+ CFRetain(unit);
+ }
+ else {
+ int if_type;
+ boolean_t is_builtin = FALSE;
+ int next_unit = 0;
+
+ CFNumberGetValue(type,
+ kCFNumberIntType, &if_type);
+ if (if_type == IFT_ETHER) { /* ethernet */
+ CFBooleanRef builtin;
+
+ builtin = CFDictionaryGetValue(if_dict,
+ CFSTR(kIOBuiltin));
+ if (builtin && CFBooleanGetValue(builtin)) {
+ is_builtin = TRUE;
+ next_unit = i_builtin++;
+ }
+ else {
+#if defined(__ppc__)
+ /* skip over slots reserved for built-in ethernet interface(s) */
+ next_unit = n_builtin;
+#endif
+ }
+ }
+ if (is_builtin == FALSE) {
+ unit = getHighestUnitForType(type);
+ if (unit) {
+ int high_unit;
+
+ CFNumberGetValue(unit,
+ kCFNumberIntType, &high_unit);
+ if (high_unit >= next_unit) {
+ next_unit = high_unit + 1;
+ }
+ }
+ }
+ unit = CFNumberCreate(NULL,
+ kCFNumberIntType, &next_unit);
+ }
+ if (S_debug) {
+ SCPrint(TRUE, stdout, CFSTR("Interface assigned unit %@ %s\n"), unit,
+ dbdict ? "(from database)" : "(next available)");
+ }
+ kr = registerInterface(S_connect, path, unit);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": failed to name the interface 0x%x"),
+ kr);
+ if (S_debug) {
+ displayInterface(if_dict);
+ }
+ }
+ else {
+ CFDictionaryRef new_dict;
+
+ path = CFDictionaryGetValue(if_dict,
+ CFSTR(kIOPathMatchKey));
+ new_dict = lookupIOKitPath(path);
+ if (new_dict != NULL) {
+ CFNumberRef new_unit;
+
+ new_unit = CFDictionaryGetValue(new_dict,
+ CFSTR(kIOInterfaceUnit));
+ if (CFEqual(unit, new_unit) == FALSE) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": interface type %@ assigned "
+ "unit %@ instead of %@"),
+ type, new_unit, unit);
+ }
+ if (S_debug) {
+ displayInterface(new_dict);
+ }
+ replaceInterface(new_dict);
+ CFRelease(new_dict);
+ }
+ }
+ CFRelease(unit);
+ }
+ }
+ writeInterfaceList(S_dblist);
+ return;
+}
+
+static void
+interfaceArrivalCallback( void * refcon, io_iterator_t iter )
+{
+ CFMutableArrayRef if_list = NULL;
+ io_object_t obj;
+
+
+ while ((obj = IOIteratorNext(iter))) {
+ CFDictionaryRef dict;
+
+ dict = getInterface(obj);
+ if (dict) {
+ if (if_list == NULL) {
+ if_list = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+ }
+ if (if_list)
+ CFArrayAppendValue(if_list, dict);
+ CFRelease(dict);
+ }
+ IOObjectRelease(obj);
+ }
+ if (if_list) {
+ sort_interfaces_by_path(if_list);
+ name_interfaces(if_list);
+ updateBondConfiguration();
+ updateVLANConfiguration();
+ CFRelease(if_list);
+ }
+ return;
+}
+
+
+__private_extern__
+void
+load_InterfaceNamer(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ kern_return_t kr;
+ mach_port_t masterPort = MACH_PORT_NULL;
+ io_object_t stack = MACH_PORT_NULL;
+
+ if (bundleVerbose) {
+ S_debug++;
+ }
+
+ kr = IOMasterPort(bootstrap_port, &masterPort);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": IOMasterPort returned 0x%x"),
+ kr);
+ goto error;
+ }
+
+ /* synchronize with any drivers that might be loading at boot time */
+ waitForQuiet(masterPort);
+
+ stack = createNetworkStackObject(masterPort);
+ if (stack == MACH_PORT_NULL) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": No network stack object"));
+ goto error;
+ }
+ kr = IOServiceOpen(stack, mach_task_self(), 0, &S_connect);
+ if (kr != KERN_SUCCESS) {
+ SCPrint(TRUE, stdout, CFSTR(MY_PLUGIN_NAME ": IOServiceOpen returned 0x%x\n"), kr);
+ goto error;
+ }
+
+ // Creates and returns a notification object for receiving IOKit
+ // notifications of new devices or state changes.
+
+ S_notify = IONotificationPortCreate(masterPort);
+ if (S_notify == NULL) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME ": IONotificationPortCreate failed"));
+ goto error;
+ }
+ kr = IOServiceAddMatchingNotification(S_notify,
+ kIOFirstMatchNotification,
+ IOServiceMatching("IONetworkInterface"),
+ &interfaceArrivalCallback,
+ (void *) S_notify, /* refCon */
+ &S_iter ); /* notification */
+
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO,
+ CFSTR(MY_PLUGIN_NAME
+ ": IOServiceAddMatchingNotification returned 0x%x"),
+ kr);
+ goto error;
+ }
+
+ S_dblist = readInterfaceList();
+ if (S_dblist) {
+ sort_interfaces_by_unit(S_dblist);
+ }
+ // Get the current list of matches and arms the notification for
+ // future interface arrivals.
+
+ interfaceArrivalCallback((void *) S_notify, S_iter);
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(),
+ IONotificationPortGetRunLoopSource(S_notify),
+ kCFRunLoopDefaultMode);
+ if (stack != MACH_PORT_NULL) {
+ IOObjectRelease(stack);
+ }
+ if (masterPort != MACH_PORT_NULL) {
+ mach_port_deallocate(mach_task_self(), masterPort);
+ }
+ return;
+ error:
+ if (stack != MACH_PORT_NULL) {
+ IOObjectRelease(stack);
+ }
+ if (masterPort != MACH_PORT_NULL) {
+ mach_port_deallocate(mach_task_self(), masterPort);
+ }
+ if (S_connect != MACH_PORT_NULL) {
+ IOServiceClose(S_connect);
+ S_connect = MACH_PORT_NULL;
+ }
+ if (S_iter != MACH_PORT_NULL) {
+ IOObjectRelease(S_iter);
+ S_iter = MACH_PORT_NULL;
+ }
+ if (S_notify != MACH_PORT_NULL) {
+ IONotificationPortDestroy(S_notify);
+ }
+ return;
+}
+
+//------------------------------------------------------------------------
+// Main function.
+#ifdef MAIN
+int
+main(int argc, char ** argv)
+{
+ load_InterfaceNamer(CFBundleGetMainBundle(),
+ (argc > 1) ? TRUE : FALSE);
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif /* MAIN */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>KernelEventMonitor</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.KernelEventMonitor</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+ </array>
+ <key>Builtin</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2002-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_appletalk.h"
+
+// from <netat/ddp.h>
+#define DDP_MIN_NETWORK 0x0001
+#define DDP_MAX_NETWORK 0xfffe
+
+
+static int
+get_atalk_interface_cfg(const char *if_name, at_if_cfg_t *cfg)
+{
+ int fd;
+
+ /* open socket */
+ if ((fd = socket(AF_APPLETALK, SOCK_RAW, 0)) < 0)
+ return -1;
+
+ /* get config info for given interface */
+ strncpy(cfg->ifr_name, if_name, sizeof(cfg->ifr_name));
+ if (ioctl(fd, AIOCGETIFCFG, (caddr_t)cfg) < 0) {
+ (void)close(fd);
+ return -1;
+ }
+
+ (void)close(fd);
+ return 0;
+}
+
+
+static CFMutableDictionaryRef
+getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+{
+ CFDictionaryRef dict = NULL;
+ CFMutableDictionaryRef newDict = NULL;
+
+ if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ } else {
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (dict) {
+ CFDictionarySetValue(oldIFs, key, dict);
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkID);
+ CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNodeID);
+ CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkRange);
+ CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkDefaultZone);
+ }
+ CFRelease(dict);
+ }
+ }
+
+ if (!newDict) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ return newDict;
+}
+
+
+static void
+updateStore(const void *key, const void *value, void *context)
+{
+ CFDictionaryRef dict;
+ CFDictionaryRef newDict = (CFDictionaryRef)value;
+ CFDictionaryRef oldIFs = (CFDictionaryRef)context;
+
+ dict = CFDictionaryGetValue(oldIFs, key);
+
+ if (!dict || !CFEqual(dict, newDict)) {
+ if (CFDictionaryGetCount(newDict) > 0) {
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ } else if (dict) {
+ cache_SCDynamicStoreRemoveValue(store, key);
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+interface_update_appletalk(struct ifaddrs *ifap, const char *if_name)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifap_temp = NULL;
+ CFStringRef interface;
+ boolean_t interfaceFound = FALSE;
+ CFStringRef key = NULL;
+ CFMutableDictionaryRef oldIFs;
+ CFMutableDictionaryRef newDict = NULL;
+ CFMutableDictionaryRef newIFs;
+
+ oldIFs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ newIFs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (!ifap) {
+ if (getifaddrs(&ifap_temp) < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+ goto error;
+ }
+ ifap = ifap_temp;
+ }
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ at_if_cfg_t cfg;
+ int iVal;
+ CFNumberRef num;
+ struct sockaddr_at *sat;
+
+ if (ifa->ifa_addr->sa_family != AF_APPLETALK) {
+ continue; /* sorry, not interested */
+ }
+
+ /* check if this is the requested interface */
+ if (if_name) {
+ if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
+ interfaceFound = TRUE; /* yes, this is the one I want */
+ } else {
+ continue; /* sorry, not interested */
+ }
+ }
+
+ /* get the current cache information */
+ interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetAppleTalk);
+ CFRelease(interface);
+
+ newDict = getIF(key, oldIFs, newIFs);
+
+ sat = (struct sockaddr_at *)ifa->ifa_addr;
+
+ iVal = (int)sat->sat_addr.s_net;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, num);
+ CFRelease(num);
+
+ iVal = (int)sat->sat_addr.s_node;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, num);
+ CFRelease(num);
+
+ if (get_atalk_interface_cfg(ifa->ifa_name, &cfg) == 0) {
+ CFStringRef zone;
+
+ /*
+ * Set starting and ending net values
+ */
+ if (!(((cfg.netStart == 0) && (cfg.netEnd == 0)) ||
+ ((cfg.netStart == DDP_MIN_NETWORK) && (cfg.netEnd == DDP_MAX_NETWORK)))) {
+ CFMutableArrayRef array;
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ iVal = cfg.netStart;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+ CFArrayAppendValue(array, num);
+ CFRelease(num);
+
+ iVal = cfg.netEnd;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+ CFArrayAppendValue(array, num);
+ CFRelease(num);
+
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkRange, array);
+ CFRelease(array);
+ }
+
+ /*
+ * Set the default zone
+ */
+ zone = CFStringCreateWithPascalString(NULL,
+ (ConstStr255Param)&cfg.zonename,
+ kCFStringEncodingMacRoman);
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, zone);
+ CFRelease(zone);
+ }
+
+ CFDictionarySetValue(newIFs, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ }
+
+ /* if the last address[es] were removed from the target interface */
+ if (if_name && !interfaceFound) {
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetAppleTalk);
+ CFRelease(interface);
+
+ newDict = getIF(key, oldIFs, newIFs);
+
+ CFDictionarySetValue(newIFs, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ }
+
+ CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
+
+ error :
+
+ if (ifap_temp) freeifaddrs(ifap_temp);
+ CFRelease(oldIFs);
+ CFRelease(newIFs);
+
+ return;
+}
+
+
+__private_extern__
+void
+interface_update_atalk_address(struct kev_atalk_data *aEvent, const char *if_name)
+{
+ CFStringRef interface;
+ CFStringRef key;
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict = NULL;
+ CFNumberRef newNode, newNet;
+ int node;
+ int net;
+
+ /* get the current cache information */
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetAppleTalk);
+ CFRelease(interface);
+
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ }
+ CFRelease(dict);
+ }
+
+ if (!newDict) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ /* Update node/net values in cache */
+ node = (int)aEvent->node_data.address.s_node;
+ net = (int)aEvent->node_data.address.s_net;
+
+ newNode = CFNumberCreate(NULL, kCFNumberIntType, &node);
+ newNet = CFNumberCreate(NULL, kCFNumberIntType, &net);
+
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, newNode);
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, newNet);
+
+ CFRelease(newNode);
+ CFRelease(newNet);
+
+ /* update cache */
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ return;
+}
+
+
+__private_extern__
+void
+interface_update_atalk_zone(struct kev_atalk_data *aEvent, const char *if_name)
+{
+ CFStringRef interface;
+ CFStringRef key;
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict = NULL;
+ CFStringRef newZone;
+
+ /* get the current cache information */
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetAppleTalk);
+ CFRelease(interface);
+
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ }
+ CFRelease(dict);
+ }
+
+ if (!newDict) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ /* Update zone value in cache */
+ newZone = CFStringCreateWithPascalString(NULL, (ConstStr255Param)&(aEvent->node_data.zone), kCFStringEncodingMacRoman);
+
+ CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, newZone);
+
+ CFRelease(newZone);
+
+ /* update cache */
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ return;
+}
+
+
+__private_extern__
+void
+interface_update_shutdown_atalk()
+{
+ CFStringRef cacheKey;
+ CFDictionaryRef dict;
+ CFArrayRef ifList = NULL;
+ CFIndex count, index;
+ CFStringRef interface;
+ CFStringRef key;
+
+ cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
+ kSCDynamicStoreDomainState);
+
+ dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
+ CFRelease(cacheKey);
+
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ /*get a list of the interfaces*/
+ ifList = isA_CFArray(CFDictionaryGetValue(dict, kSCDynamicStorePropNetInterfaces));
+ if (ifList) {
+ count = CFArrayGetCount(ifList);
+
+ /*iterate through list and remove AppleTalk data*/
+ for (index = 0; index < count; index++) {
+ interface = CFArrayGetValueAtIndex(ifList, index);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetAppleTalk);
+ cache_SCDynamicStoreRemoveValue(store, key);
+ CFRelease(key);
+ }
+ }
+ }
+ CFRelease(dict);
+ }
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EV_APPLETALK_H
+#define _EV_APPLETALK_H
+
+#include <netat/appletalk.h>
+#include <netat/at_var.h>
+
+__BEGIN_DECLS
+
+void interface_update_appletalk (struct ifaddrs *ifap, const char *if_name);
+void interface_update_atalk_address (struct kev_atalk_data *aEvent, const char *if_name);
+void interface_update_atalk_zone (struct kev_atalk_data *aEvent, const char *if_name);
+void interface_update_shutdown_atalk ();
+
+__END_DECLS
+
+#endif /* _EV_EVENTMON_H */
+
--- /dev/null
+/*
+ * Copyright (c) 2002-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_dlil.h"
+
+static CFStringRef
+create_interface_key(const char * if_name)
+{
+ CFStringRef interface;
+ CFStringRef key;
+
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetLink);
+ CFRelease(interface);
+ return (key);
+}
+
+
+static CFMutableDictionaryRef
+copy_entity(CFStringRef key)
+{
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict = NULL;
+
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (dict != NULL) {
+ if (isA_CFDictionary(dict) != NULL) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ }
+ CFRelease(dict);
+ }
+ if (newDict == NULL) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ return (newDict);
+}
+
+
+static void
+interface_update_status(const char *if_name, CFBooleanRef active,
+ boolean_t attach)
+{
+ CFStringRef key = NULL;
+ CFMutableDictionaryRef newDict = NULL;
+ CFBooleanRef state = NULL;
+
+ key = create_interface_key(if_name);
+ newDict = copy_entity(key);
+ state = isA_CFBoolean(CFDictionaryGetValue(newDict,
+ kSCPropNetLinkActive));
+ /* if new status available, update cache */
+ if (active == NULL) {
+ CFDictionaryRemoveValue(newDict, kSCPropNetLinkActive);
+ } else {
+ CFDictionarySetValue(newDict, kSCPropNetLinkActive, active);
+ }
+ if (attach == TRUE) {
+ /* the interface was attached, remove stale state */
+ CFDictionaryRemoveValue(newDict, kSCPropNetLinkDetaching);
+ }
+
+ /* update status */
+ if (CFDictionaryGetCount(newDict) > 0) {
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ } else {
+ cache_SCDynamicStoreRemoveValue(store, key);
+ }
+
+ CFRelease(key);
+ CFRelease(newDict);
+ return;
+}
+
+__private_extern__
+void
+interface_detaching(const char *if_name)
+{
+ CFStringRef key;
+ CFMutableDictionaryRef newDict;
+
+ key = create_interface_key(if_name);
+ newDict = copy_entity(key);
+ CFDictionarySetValue(newDict, kSCPropNetLinkDetaching,
+ kCFBooleanTrue);
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ return;
+}
+
+static void
+interface_remove(const char *if_name)
+{
+ CFStringRef key;
+
+ key = create_interface_key(if_name);
+ cache_SCDynamicStoreRemoveValue(store, key);
+ CFRelease(key);
+ return;
+}
+
+
+__private_extern__
+void
+link_update_status(const char *if_name, boolean_t attach)
+{
+ CFBooleanRef active = NULL;
+ struct ifmediareq ifm;
+ int sock;
+
+ sock = dgram_socket(AF_INET);
+ if (sock < 0) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("link_update_status: socket open failed, %s"), strerror(errno));
+ goto done;
+ }
+ bzero((char *)&ifm, sizeof(ifm));
+ (void) strncpy(ifm.ifm_name, if_name, sizeof(ifm.ifm_name));
+
+ if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifm) == -1) {
+ /* if media status not available for this interface */
+ goto done;
+ }
+
+ if (ifm.ifm_count == 0) {
+ /* no media types */
+ goto done;
+ }
+
+ if (!(ifm.ifm_status & IFM_AVALID)) {
+ /* if active bit not valid */
+ goto done;
+ }
+
+ if (ifm.ifm_status & IFM_ACTIVE) {
+ active = kCFBooleanTrue;
+ } else {
+ active = kCFBooleanFalse;
+ }
+
+ done:
+ interface_update_status(if_name, active, attach);
+ if (sock >= 0)
+ close(sock);
+ return;
+}
+
+
+__private_extern__
+void
+link_add(const char *if_name)
+{
+ CFStringRef interface;
+ CFStringRef cacheKey;
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict = NULL;
+ CFArrayRef ifList;
+ CFMutableArrayRef newIFList = NULL;
+
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
+ kSCDynamicStoreDomainState);
+
+ dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ ifList = CFDictionaryGetValue(newDict, kSCDynamicStorePropNetInterfaces);
+ if (isA_CFArray(ifList)) {
+ newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+ }
+ }
+ CFRelease(dict);
+ }
+
+ if (!newDict) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ if (!newIFList) {
+ newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ if (CFArrayContainsValue(newIFList,
+ CFRangeMake(0, CFArrayGetCount(newIFList)),
+ interface) == FALSE) {
+ CFArrayAppendValue(newIFList, interface);
+ CFDictionarySetValue(newDict,
+ kSCDynamicStorePropNetInterfaces,
+ newIFList);
+ }
+ cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
+ link_update_status(if_name, TRUE);
+ CFRelease(cacheKey);
+ CFRelease(interface);
+ if (newDict) CFRelease(newDict);
+ if (newIFList) CFRelease(newIFList);
+
+ return;
+}
+
+
+__private_extern__
+void
+link_remove(const char *if_name)
+{
+ CFStringRef interface;
+ CFStringRef cacheKey;
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict = NULL;
+ CFArrayRef ifList;
+ CFMutableArrayRef newIFList = NULL;
+ CFIndex i;
+
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ cacheKey = SCDynamicStoreKeyCreateNetworkInterface(NULL,
+ kSCDynamicStoreDomainState);
+
+ dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
+ if (dict) {
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ ifList = CFDictionaryGetValue(newDict, kSCDynamicStorePropNetInterfaces);
+ if (isA_CFArray(ifList)) {
+ newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+ }
+ }
+ CFRelease(dict);
+ }
+
+ if (!newIFList ||
+ ((i = CFArrayGetFirstIndexOfValue(newIFList,
+ CFRangeMake(0, CFArrayGetCount(newIFList)),
+ interface)) == kCFNotFound)
+ ) {
+ /* we're not tracking this interface */
+ goto done;
+ }
+
+ CFArrayRemoveValueAtIndex(newIFList, i);
+ CFDictionarySetValue(newDict, kSCDynamicStorePropNetInterfaces, newIFList);
+ cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
+
+ interface_remove(if_name);
+
+ done:
+
+ CFRelease(cacheKey);
+ CFRelease(interface);
+ if (newDict) CFRelease(newDict);
+ if (newIFList) CFRelease(newIFList);
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EV_DLIL_H
+#define _EV_DLIL_H
+
+__BEGIN_DECLS
+
+void interface_detaching (const char *if_name);
+void link_add (const char *if_name);
+void link_remove (const char *if_name);
+void link_update_status (const char *if_name, boolean_t attach);
+
+__END_DECLS
+
+#endif /* _EV_DLIL_H */
+
--- /dev/null
+/*
+ * Copyright (c) 2002-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_ipv4.h"
+
+#ifndef kSCEntNetIPv4ARPCollision
+#define kSCEntNetIPv4ARPCollision CFSTR("IPv4ARPCollision")
+#endif kSCEntNetIPv4ARPCollision
+
+#define IP_FORMAT "%d.%d.%d.%d"
+#define IP_CH(ip, i) (((u_char *)(ip))[i])
+#define IP_LIST(ip) IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
+
+
+static void
+appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct in_addr *address)
+{
+ CFStringRef addr;
+ CFArrayRef addrs;
+ CFMutableArrayRef newAddrs;
+
+ addrs = CFDictionaryGetValue(dict, key);
+ if (addrs) {
+ newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
+ } else {
+ newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ addr = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(address));
+ CFArrayAppendValue(newAddrs, addr);
+ CFRelease(addr);
+
+ CFDictionarySetValue(dict, key, newAddrs);
+ CFRelease(newAddrs);
+ return;
+}
+
+
+static CFMutableDictionaryRef
+getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+{
+ CFDictionaryRef dict = NULL;
+ CFMutableDictionaryRef newDict = NULL;
+
+ if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ } else {
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (dict) {
+ CFDictionarySetValue(oldIFs, key, dict);
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv4Addresses);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv4SubnetMasks);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv4DestAddresses);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv4BroadcastAddresses);
+ }
+ CFRelease(dict);
+ }
+ }
+
+ if (!newDict) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ return newDict;
+}
+
+
+static void
+updateStore(const void *key, const void *value, void *context)
+{
+ CFDictionaryRef dict;
+ CFDictionaryRef newDict = (CFDictionaryRef)value;
+ CFDictionaryRef oldIFs = (CFDictionaryRef)context;
+
+ dict = CFDictionaryGetValue(oldIFs, key);
+
+ if (!dict || !CFEqual(dict, newDict)) {
+ if (CFDictionaryGetCount(newDict) > 0) {
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ } else if (dict) {
+ cache_SCDynamicStoreRemoveValue(store, key);
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+interface_update_ipv4(struct ifaddrs *ifap, const char *if_name)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifap_temp = NULL;
+ CFStringRef interface;
+ boolean_t interfaceFound = FALSE;
+ CFStringRef key = NULL;
+ CFMutableDictionaryRef oldIFs;
+ CFMutableDictionaryRef newDict = NULL;
+ CFMutableDictionaryRef newIFs;
+
+ oldIFs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ newIFs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (!ifap) {
+ if (getifaddrs(&ifap_temp) < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+ goto error;
+ }
+ ifap = ifap_temp;
+ }
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ struct sockaddr_in *sin;
+
+ if (ifa->ifa_addr->sa_family != AF_INET) {
+ continue; /* sorry, not interested */
+ }
+
+ /* check if this is the requested interface */
+ if (if_name) {
+ if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
+ interfaceFound = TRUE; /* yes, this is the one I want */
+ } else {
+ continue; /* sorry, not interested */
+ }
+ }
+
+ interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetIPv4);
+ CFRelease(interface);
+
+ newDict = getIF(key, oldIFs, newIFs);
+
+ sin = (struct sockaddr_in *)ifa->ifa_addr;
+ appendAddress(newDict, kSCPropNetIPv4Addresses, &sin->sin_addr);
+
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ struct sockaddr_in *dst;
+
+ dst = (struct sockaddr_in *)ifa->ifa_dstaddr;
+ appendAddress(newDict, kSCPropNetIPv4DestAddresses, &dst->sin_addr);
+ } else {
+ struct sockaddr_in *brd;
+ struct sockaddr_in *msk;
+
+ brd = (struct sockaddr_in *)ifa->ifa_broadaddr;
+ appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses, &brd->sin_addr);
+ msk = (struct sockaddr_in *)ifa->ifa_netmask;
+ appendAddress(newDict, kSCPropNetIPv4SubnetMasks, &msk->sin_addr);
+ }
+
+ CFDictionarySetValue(newIFs, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ }
+
+ /* if the last address[es] were removed from the target interface */
+ if (if_name && !interfaceFound) {
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetIPv4);
+ CFRelease(interface);
+
+ newDict = getIF(key, oldIFs, newIFs);
+
+ CFDictionarySetValue(newIFs, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ }
+
+ CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
+
+ error :
+
+ if (ifap_temp) freeifaddrs(ifap_temp);
+ CFRelease(oldIFs);
+ CFRelease(newIFs);
+
+ return;
+}
+
+__private_extern__
+void
+interface_collision_ipv4(const char *if_name, struct in_addr ip_addr, int hw_len, const void * hw_addr)
+{
+ uint8_t * hw_addr_bytes = (uint8_t *)hw_addr;
+ int i;
+ CFStringRef if_name_cf;
+ CFMutableStringRef key;
+ CFStringRef prefix;
+
+ if_name_cf = CFStringCreateWithCString(NULL, if_name,
+ kCFStringEncodingASCII);
+ prefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ if_name_cf,
+ kSCEntNetIPv4ARPCollision);
+ key = CFStringCreateMutableCopy(NULL, 0, prefix);
+ CFStringAppendFormat(key, NULL, CFSTR("/" IP_FORMAT),
+ IP_LIST(&ip_addr));
+ for (i = 0; i < hw_len; i++) {
+ CFStringAppendFormat(key, NULL, CFSTR("%s%02x"),
+ (i == 0) ? "/" : ":", hw_addr_bytes[i]);
+ }
+ cache_SCDynamicStoreNotifyValue(store, key);
+ CFRelease(key);
+ CFRelease(prefix);
+ CFRelease(if_name_cf);
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EV_IPV4_H
+#define _EV_IPV4_H
+
+#include <netinet/in_var.h>
+
+__BEGIN_DECLS
+
+void interface_update_ipv4 (struct ifaddrs *ifap, const char *if_name);
+void interface_collision_ipv4(const char *if_name,
+ struct in_addr ip_addr,
+ int hw_len, const void * hw_addr);
+__END_DECLS
+
+#endif /* _EV_IPV4_H */
+
--- /dev/null
+/*
+ * Copyright (c) 2002-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_ipv6.h"
+
+#define s6_addr16 __u6_addr.__u6_addr16
+
+#ifndef kSCPropNetIPv6DestAddresses
+#define kSCPropNetIPv6DestAddresses SCSTR("DestAddresses")
+#endif
+
+#ifndef kSCPropNetIPv6Flags
+#define kSCPropNetIPv6Flags SCSTR("Flags")
+#endif
+
+#ifndef kSCPropNetIPv6PrefixLength
+#define kSCPropNetIPv6PrefixLength SCSTR("PrefixLength")
+#endif
+
+#ifdef NOTYET
+#ifndef kSCPropNetIPv6ScopeID
+#define kSCPropNetIPv6ScopeID SCSTR("ScopeID")
+#endif
+#endif /* NOTYET */
+
+
+static void
+appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct sockaddr_in6 *sin6)
+{
+ CFStringRef addr;
+ CFArrayRef addrs;
+ CFMutableArrayRef newAddrs;
+ char str[64];
+
+ addrs = CFDictionaryGetValue(dict, key);
+ if (addrs) {
+ newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
+ } else {
+ newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr, str, sizeof(str)) == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("inet_ntop() failed: %s"), strerror(errno));
+ str[0] = '\0';
+ }
+
+ addr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), str);
+ CFArrayAppendValue(newAddrs, addr);
+ CFRelease(addr);
+
+ CFDictionarySetValue(dict, key, newAddrs);
+ CFRelease(newAddrs);
+ return;
+}
+
+
+static void
+appendFlags(CFMutableDictionaryRef dict, int flags6)
+{
+ CFArrayRef flags;
+ CFMutableArrayRef newFlags;
+ CFNumberRef v6Flags;
+
+ flags = CFDictionaryGetValue(dict, kSCPropNetIPv6Flags);
+ if (flags) {
+ newFlags = CFArrayCreateMutableCopy(NULL, 0, flags);
+ } else {
+ newFlags = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ v6Flags = CFNumberCreate(NULL, kCFNumberIntType, &flags6);
+ CFArrayAppendValue(newFlags, v6Flags);
+ CFRelease(v6Flags);
+
+ CFDictionarySetValue(dict, kSCPropNetIPv6Flags, newFlags);
+ CFRelease(newFlags);
+ return;
+}
+
+
+static void
+appendPrefixLen(CFMutableDictionaryRef dict, struct sockaddr_in6 *sin6)
+{
+ register u_int8_t *name = &sin6->sin6_addr.s6_addr[0];
+ CFNumberRef prefixLen;
+ CFArrayRef prefixLens;
+ CFMutableArrayRef newPrefixLens;
+
+ register int byte;
+ register int bit;
+ int plen = 0;
+
+ for (byte = 0; byte < sizeof(struct in6_addr); byte++, plen += 8) {
+ if (name[byte] != 0xff) {
+ break;
+ }
+ }
+
+ if (byte == sizeof(struct in6_addr)) {
+ goto append;
+ }
+
+ for (bit = 7; bit != 0; bit--, plen++) {
+ if (!(name[byte] & (1 << bit))) {
+ break;
+ }
+ }
+
+ for (; bit != 0; bit--) {
+ if (name[byte] & (1 << bit)) {
+ plen = 0;
+ goto append;
+ }
+ }
+
+ byte++;
+ for (; byte < sizeof(struct in6_addr); byte++) {
+ if (name[byte]) {
+ plen = 0;
+ goto append;
+ }
+ }
+
+ append :
+
+ prefixLens = CFDictionaryGetValue(dict, kSCPropNetIPv6PrefixLength);
+ if (prefixLens) {
+ newPrefixLens = CFArrayCreateMutableCopy(NULL, 0, prefixLens);
+ } else {
+ newPrefixLens = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ prefixLen = CFNumberCreate(NULL, kCFNumberIntType, &plen);
+ CFArrayAppendValue(newPrefixLens, prefixLen);
+ CFRelease(prefixLen);
+
+ CFDictionarySetValue(dict, kSCPropNetIPv6PrefixLength, newPrefixLens);
+ CFRelease(newPrefixLens);
+ return;
+}
+
+
+#ifdef NOTYET
+static void
+appendScopeID(CFMutableDictionaryRef dict, struct sockaddr_in6 *sin6)
+{
+ CFNumberRef scope;
+ CFArrayRef scopes;
+ CFMutableArrayRef newScopes;
+
+ scopes = CFDictionaryGetValue(dict, kSCPropNetIPv6ScopeID);
+ if (scopes) {
+ newScopes = CFArrayCreateMutableCopy(NULL, 0, scopes);
+ } else {
+ newScopes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ scope = CFNumberCreate(NULL, kCFNumberSInt32Type, &sin6->sin6_scope_id);
+ CFArrayAppendValue(newScopes, scope);
+ CFRelease(scope);
+
+ CFDictionarySetValue(dict, kSCPropNetIPv6ScopeID, newScopes);
+ CFRelease(newScopes);
+ return;
+}
+#endif /* NOTYET */
+
+
+static CFMutableDictionaryRef
+getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+{
+ CFDictionaryRef dict = NULL;
+ CFMutableDictionaryRef newDict = NULL;
+
+ if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ } else {
+ dict = cache_SCDynamicStoreCopyValue(store, key);
+ if (dict) {
+ CFDictionarySetValue(oldIFs, key, dict);
+ if (isA_CFDictionary(dict)) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv6Addresses);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv6DestAddresses);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv6Flags);
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv6PrefixLength);
+#ifdef NOTYET
+ CFDictionaryRemoveValue(newDict, kSCPropNetIPv6ScopeID);
+#endif /* NOTYET */
+ }
+ CFRelease(dict);
+ }
+ }
+
+ if (!newDict) {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ return newDict;
+}
+
+
+static void
+updateStore(const void *key, const void *value, void *context)
+{
+ CFDictionaryRef dict;
+ CFDictionaryRef newDict = (CFDictionaryRef)value;
+ CFDictionaryRef oldIFs = (CFDictionaryRef)context;
+
+ dict = CFDictionaryGetValue(oldIFs, key);
+
+ if (!dict || !CFEqual(dict, newDict)) {
+ if (CFDictionaryGetCount(newDict) > 0) {
+ cache_SCDynamicStoreSetValue(store, key, newDict);
+ } else if (dict) {
+ cache_SCDynamicStoreRemoveValue(store, key);
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+interface_update_ipv6(struct ifaddrs *ifap, const char *if_name)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifap_temp = NULL;
+ CFStringRef interface;
+ boolean_t interfaceFound = FALSE;
+ CFStringRef key = NULL;
+ CFMutableDictionaryRef oldIFs;
+ CFMutableDictionaryRef newDict = NULL;
+ CFMutableDictionaryRef newIFs;
+ int sock = -1;
+
+ oldIFs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ newIFs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (!ifap) {
+ if (getifaddrs(&ifap_temp) < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+ goto error;
+ }
+ ifap = ifap_temp;
+ }
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ struct in6_ifreq ifr6;
+#define flags6 ifr6.ifr_ifru.ifru_flags6
+ struct sockaddr_in6 *sin6;
+
+ if (ifa->ifa_addr->sa_family != AF_INET6) {
+ continue; /* sorry, not interested */
+ }
+
+ /* check if this is the requested interface */
+ if (if_name) {
+ if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
+ interfaceFound = TRUE; /* yes, this is the one I want */
+ } else {
+ continue; /* sorry, not interested */
+ }
+ }
+
+ if (sock < 0) {
+ sock = dgram_socket(AF_INET6);
+ if (sock < 0) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("interface_update_ipv6: socket open failed, %s"), strerror(errno));
+ goto error;
+ }
+ }
+
+ /* get the current cache information */
+ interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetIPv6);
+ CFRelease(interface);
+
+ newDict = getIF(key, oldIFs, newIFs);
+
+ sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+
+ /* XXX: embedded link local addr check */
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ u_int16_t index;
+
+ index = sin6->sin6_addr.s6_addr16[1];
+ if (index != 0) {
+ sin6->sin6_addr.s6_addr16[1] = 0;
+ if (sin6->sin6_scope_id == 0) {
+ sin6->sin6_scope_id = ntohs(index);
+ }
+ }
+ }
+
+ bzero((char *)&ifr6, sizeof(ifr6));
+ strncpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
+ ifr6.ifr_addr = *sin6;
+ if (ioctl(sock, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
+ /* if flags not available for this address */
+ SCLog(TRUE, LOG_NOTICE, CFSTR("interface_update_ipv6: ioctl failed, %s"), strerror(errno));
+ }
+
+ appendAddress (newDict, kSCPropNetIPv6Addresses, sin6);
+#ifdef NOTYET
+ appendScopeID (newDict, sin6);
+#endif /* NOTYET */
+ appendPrefixLen(newDict, (struct sockaddr_in6 *)ifa->ifa_netmask);
+ appendFlags (newDict, flags6);
+
+
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ struct sockaddr_in6 *dst6;
+
+ dst6 = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+
+ /* XXX: embedded link local addr check */
+ if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) {
+ u_int16_t index;
+
+ index = dst6->sin6_addr.s6_addr16[1];
+ if (index != 0) {
+ dst6->sin6_addr.s6_addr16[1] = 0;
+ if (dst6->sin6_scope_id == 0) {
+ dst6->sin6_scope_id = ntohs(index);
+ }
+ }
+ }
+
+ appendAddress(newDict, kSCPropNetIPv6DestAddresses, dst6);
+ }
+
+ CFDictionarySetValue(newIFs, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ }
+
+ /* if the last address[es] were removed from the target interface */
+ if (if_name && !interfaceFound) {
+ interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainState,
+ interface,
+ kSCEntNetIPv6);
+ CFRelease(interface);
+
+ newDict = getIF(key, oldIFs, newIFs);
+
+ CFDictionarySetValue(newIFs, key, newDict);
+ CFRelease(newDict);
+ CFRelease(key);
+ }
+
+ CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
+
+ error :
+
+ if (ifap_temp) freeifaddrs(ifap_temp);
+ if (sock >= 0) close(sock);
+ CFRelease(oldIFs);
+ CFRelease(newIFs);
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#ifndef _EV_IPV6_H
+#define _EV_IPV6_H
+
+#include <netinet6/in6_var.h>
+
+__BEGIN_DECLS
+
+void interface_update_ipv6 (struct ifaddrs *ifap, const char *if_name);
+
+__END_DECLS
+
+#endif /* _EV_IPV6_H */
+
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * December 3, 2002 Dieter Siegmund <dieter@apple.com>
+ * - handle the new KEV_INET_ARPCOLLISION event
+ * - format the event into a DynamicStore key
+ * State:/Network/Interface/ifname/IPv4Collision/ip_addr/hw_addr
+ * and send a notification on the key
+ *
+ * August 8, 2002 Allan Nathanson <ajn@apple.com>
+ * - added support for KEV_INET6_xxx events
+ *
+ * January 6, 2002 Jessica Vazquez <vazquez@apple.com>
+ * - added handling for KEV_ATALK_xxx events
+ *
+ * July 2, 2001 Dieter Siegmund <dieter@apple.com>
+ * - added handling for KEV_DL_PROTO_{ATTACHED, DETACHED}
+ * - mark an interface up if the number of protocols remaining is not 0,
+ * mark an interface down if the number is zero
+ * - allocate socket on demand instead of keeping it open all the time
+ *
+ * June 23, 2001 Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * May 17, 2001 Allan Nathanson <ajn@apple.com>
+ * - add/maintain per-interface address/netmask/destaddr information
+ * in the dynamic store.
+ *
+ * June 30, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_dlil.h"
+#include "ev_ipv4.h"
+#include "ev_ipv6.h"
+#include "ev_appletalk.h"
+
+static const char *inetEventName[] = {
+ "",
+ "INET address added",
+ "INET address changed",
+ "INET address deleted",
+ "INET destination address changed",
+ "INET broadcast address changed",
+ "INET netmask changed",
+ "INET ARP collision",
+};
+
+static const char *dlEventName[] = {
+ "",
+ "KEV_DL_SIFFLAGS",
+ "KEV_DL_SIFMETRICS",
+ "KEV_DL_SIFMTU",
+ "KEV_DL_SIFPHYS",
+ "KEV_DL_SIFMEDIA",
+ "KEV_DL_SIFGENERIC",
+ "KEV_DL_ADDMULTI",
+ "KEV_DL_DELMULTI",
+ "KEV_DL_IF_ATTACHED",
+ "KEV_DL_IF_DETACHING",
+ "KEV_DL_IF_DETACHED",
+ "KEV_DL_LINK_OFF",
+ "KEV_DL_LINK_ON",
+ "KEV_DL_PROTO_ATTACHED",
+ "KEV_DL_PROTO_DETACHED",
+};
+
+static const char *atalkEventName[] = {
+ "",
+ "KEV_ATALK_ENABLED",
+ "KEV_ATALK_DISABLED",
+ "KEV_ATALK_ZONEUPDATED",
+ "KEV_ATALK_ROUTERUP",
+ "KEV_ATALK_ROUTERUP_INVALID",
+ "KEV_ATALK_ROUTERDOWN",
+ "KEV_ATALK_ZONELISTCHANGED"
+};
+
+static const char *inet6EventName[] = {
+ "",
+ "KEV_INET6_NEW_USER_ADDR",
+ "KEV_INET6_CHANGED_ADDR",
+ "KEV_INET6_ADDR_DELETED",
+ "KEV_INET6_NEW_LL_ADDR",
+ "KEV_INET6_NEW_RTADV_ADDR",
+ "KEV_INET6_DEFROUTER"
+
+};
+
+
+__private_extern__ SCDynamicStoreRef store = NULL;
+__private_extern__ Boolean _verbose = FALSE;
+
+
+__private_extern__
+int
+dgram_socket(int domain)
+{
+ return (socket(domain, SOCK_DGRAM, 0));
+}
+
+static int
+ifflags_set(int s, char * name, short flags)
+{
+ struct ifreq ifr;
+ int ret;
+
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
+ if (ret < 0) {
+ return (ret);
+ }
+ ifr.ifr_flags |= flags;
+ return (ioctl(s, SIOCSIFFLAGS, &ifr));
+}
+
+static int
+ifflags_clear(int s, char * name, short flags)
+{
+ struct ifreq ifr;
+ int ret;
+
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
+ if (ret < 0) {
+ return (ret);
+ }
+ ifr.ifr_flags &= ~flags;
+ return (ioctl(s, SIOCSIFFLAGS, &ifr));
+}
+
+static void
+mark_if_up(char * name)
+{
+ int s = dgram_socket(AF_INET);
+ if (s < 0)
+ return;
+ ifflags_set(s, name, IFF_UP);
+ close(s);
+}
+
+static void
+mark_if_down(char * name)
+{
+ int s = dgram_socket(AF_INET);
+ if (s < 0)
+ return;
+ ifflags_clear(s, name, IFF_UP);
+ close(s);
+}
+
+static void
+logEvent(CFStringRef evStr, struct kern_event_msg *ev_msg)
+{
+ int i;
+ int j;
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("%@ event:"), evStr);
+ SCLog(_verbose, LOG_DEBUG,
+ CFSTR(" Event size=%d, id=%d, vendor=%d, class=%d, subclass=%d, code=%d"),
+ ev_msg->total_size,
+ ev_msg->id,
+ ev_msg->vendor_code,
+ ev_msg->kev_class,
+ ev_msg->kev_subclass,
+ ev_msg->event_code);
+ for (i = 0, j = KEV_MSG_HEADER_SIZE; j < ev_msg->total_size; i++, j+=4) {
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" Event data[%2d] = %08lx"), i, ev_msg->event_data[i]);
+ }
+}
+
+static const char *
+inetEventNameString(u_long event_code)
+{
+ if (event_code <= KEV_INET_ARPCOLLISION) {
+ return (inetEventName[event_code]);
+ }
+ return ("New Apple network INET subcode");
+}
+
+static const char *
+inet6EventNameString(u_long event_code)
+{
+ if (event_code <= KEV_INET6_DEFROUTER) {
+ return (inet6EventName[event_code]);
+ }
+ return ("New Apple network INET6 subcode");
+}
+
+static const char *
+dlEventNameString(u_long event_code)
+{
+ if (event_code <= KEV_DL_PROTO_DETACHED) {
+ return (dlEventName[event_code]);
+ }
+ return ("New Apple network DL subcode");
+}
+
+static const char *
+atalkEventNameString(u_long event_code)
+{
+ if (event_code <= KEV_ATALK_ZONELISTCHANGED) {
+ return (atalkEventName[event_code]);
+ }
+ return ("New Apple network AppleTalk subcode");
+}
+
+
+static void
+copy_if_name(struct net_event_data * ev, char * ifr_name, int ifr_len)
+{
+ snprintf(ifr_name, ifr_len, "%s%ld", ev->if_name, ev->if_unit);
+ return;
+}
+
+static void
+processEvent_Apple_Network(struct kern_event_msg *ev_msg)
+{
+ const char * eventName = NULL;
+ int dataLen = (ev_msg->total_size - KEV_MSG_HEADER_SIZE);
+ void * event_data = &ev_msg->event_data[0];
+ Boolean handled = TRUE;
+ char ifr_name[IFNAMSIZ+1];
+
+ switch (ev_msg->kev_subclass) {
+ case KEV_INET_SUBCLASS : {
+ eventName = inetEventNameString(ev_msg->event_code);
+ switch (ev_msg->event_code) {
+ case KEV_INET_NEW_ADDR :
+ case KEV_INET_CHANGED_ADDR :
+ case KEV_INET_ADDR_DELETED :
+ case KEV_INET_SIFDSTADDR :
+ case KEV_INET_SIFBRDADDR :
+ case KEV_INET_SIFNETMASK : {
+ struct kev_in_data * ev;
+
+ ev = (struct kev_in_data *)event_data;
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+ interface_update_ipv4(NULL, ifr_name);
+ break;
+ }
+ case KEV_INET_ARPCOLLISION : {
+ struct kev_in_collision * ev;
+
+ ev = (struct kev_in_collision *)event_data;
+ if ((dataLen < sizeof(*ev))
+ || (dataLen < (sizeof(*ev) + ev->hw_len))) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+ interface_collision_ipv4(ifr_name,
+ ev->ia_ipaddr,
+ ev->hw_len,
+ ev->hw_addr);
+ break;
+ }
+ default :
+ handled = FALSE;
+ break;
+ }
+ break;
+ }
+ case KEV_INET6_SUBCLASS : {
+ struct kev_in6_data * ev;
+
+ eventName = inet6EventNameString(ev_msg->event_code);
+ ev = (struct kev_in6_data *)event_data;
+ switch (ev_msg->event_code) {
+ case KEV_INET6_NEW_USER_ADDR :
+ case KEV_INET6_CHANGED_ADDR :
+ case KEV_INET6_ADDR_DELETED :
+ case KEV_INET6_NEW_LL_ADDR :
+ case KEV_INET6_NEW_RTADV_ADDR :
+ case KEV_INET6_DEFROUTER :
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+ interface_update_ipv6(NULL, ifr_name);
+ break;
+
+ default :
+ handled = FALSE;
+ break;
+ }
+ break;
+ }
+ case KEV_DL_SUBCLASS : {
+ struct net_event_data * ev;
+
+ eventName = dlEventNameString(ev_msg->event_code);
+ ev = (struct net_event_data *)event_data;
+ switch (ev_msg->event_code) {
+ case KEV_DL_IF_ATTACHED :
+ /*
+ * new interface added
+ */
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ link_add(ifr_name);
+ break;
+
+ case KEV_DL_IF_DETACHED :
+ /*
+ * interface removed
+ */
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ link_remove(ifr_name);
+ break;
+
+ case KEV_DL_IF_DETACHING :
+ /*
+ * interface detaching
+ */
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ interface_detaching(ifr_name);
+ break;
+
+ case KEV_DL_SIFFLAGS :
+ case KEV_DL_SIFMETRICS :
+ case KEV_DL_SIFMTU :
+ case KEV_DL_SIFPHYS :
+ case KEV_DL_SIFMEDIA :
+ case KEV_DL_SIFGENERIC :
+ case KEV_DL_ADDMULTI :
+ case KEV_DL_DELMULTI :
+ handled = FALSE;
+ break;
+
+ case KEV_DL_PROTO_ATTACHED :
+ case KEV_DL_PROTO_DETACHED : {
+ struct kev_dl_proto_data * protoEvent;
+
+ protoEvent = (struct kev_dl_proto_data *)event_data;
+ if (dataLen < sizeof(*protoEvent)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(&protoEvent->link_data,
+ ifr_name, sizeof(ifr_name));
+ if (protoEvent->proto_remaining_count == 0) {
+ mark_if_down(ifr_name);
+ } else {
+ mark_if_up(ifr_name);
+ }
+ break;
+ }
+
+ case KEV_DL_LINK_OFF :
+ case KEV_DL_LINK_ON :
+ /*
+ * update the link status in the store
+ */
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(ev, ifr_name, sizeof(ifr_name));
+ link_update_status(ifr_name, FALSE);
+ break;
+
+ default :
+ handled = FALSE;
+ break;
+ }
+ break;
+ }
+ case KEV_ATALK_SUBCLASS: {
+ struct kev_atalk_data * ev;
+
+ eventName = atalkEventNameString(ev_msg->event_code);
+ ev = (struct kev_atalk_data *)event_data;
+ if (dataLen < sizeof(*ev)) {
+ handled = FALSE;
+ break;
+ }
+ copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+ switch (ev_msg->event_code) {
+ case KEV_ATALK_ENABLED:
+ interface_update_atalk_address(ev, ifr_name);
+ break;
+
+ case KEV_ATALK_DISABLED:
+ interface_update_shutdown_atalk();
+ break;
+
+ case KEV_ATALK_ZONEUPDATED:
+ interface_update_atalk_zone(ev, ifr_name);
+ break;
+
+ case KEV_ATALK_ROUTERUP:
+ case KEV_ATALK_ROUTERUP_INVALID:
+ case KEV_ATALK_ROUTERDOWN:
+ interface_update_appletalk(NULL, ifr_name);
+ break;
+
+ case KEV_ATALK_ZONELISTCHANGED:
+ break;
+
+ default :
+ handled = FALSE;
+ break;
+ }
+ break;
+ }
+ default :
+ handled = FALSE;
+ break;
+ }
+
+ if (handled == FALSE) {
+ CFStringRef evStr;
+
+ evStr = CFStringCreateWithCString(NULL,
+ (eventName != NULL) ? eventName : "New Apple network subclass",
+ kCFStringEncodingASCII);
+ logEvent(evStr, ev_msg);
+ CFRelease(evStr);
+ }
+ return;
+}
+
+
+static void
+processEvent_Apple_IOKit(struct kern_event_msg *ev_msg)
+{
+ switch (ev_msg->kev_subclass) {
+ default :
+ logEvent(CFSTR("New Apple IOKit subclass"), ev_msg);
+ break;
+ }
+
+ return;
+}
+
+
+static void
+eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
+{
+ int so = CFSocketGetNative(s);
+ int status;
+ char buf[1024];
+ struct kern_event_msg *ev_msg = (struct kern_event_msg *)&buf[0];
+ int offset = 0;
+
+ status = recv(so, &buf, sizeof(buf), 0);
+ if (status == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("recv() failed: %s"), strerror(errno));
+ goto error;
+ }
+
+ cache_open();
+
+ while (offset < status) {
+ if ((offset + ev_msg->total_size) > status) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough"));
+ break;
+ }
+
+ switch (ev_msg->vendor_code) {
+ case KEV_VENDOR_APPLE :
+ switch (ev_msg->kev_class) {
+ case KEV_NETWORK_CLASS :
+ processEvent_Apple_Network(ev_msg);
+ break;
+ case KEV_IOKIT_CLASS :
+ processEvent_Apple_IOKit(ev_msg);
+ break;
+ default :
+ /* unrecognized (Apple) event class */
+ logEvent(CFSTR("New (Apple) class"), ev_msg);
+ break;
+ }
+ break;
+ default :
+ /* unrecognized vendor code */
+ logEvent(CFSTR("New vendor"), ev_msg);
+ break;
+ }
+ offset += ev_msg->total_size;
+ ev_msg = (struct kern_event_msg *)&buf[offset];
+ }
+
+ cache_write(store);
+ cache_close();
+
+ return;
+
+ error :
+
+ SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
+ CFSocketInvalidate(s);
+ return;
+
+}
+
+
+__private_extern__
+void
+prime_KernelEventMonitor()
+{
+ struct ifaddrs *ifap = NULL;
+ struct ifaddrs *scan;
+ int sock = -1;
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
+
+ cache_open();
+
+ sock = dgram_socket(AF_INET);
+ if (sock == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not get interface list, socket() failed: %s"), strerror(errno));
+ goto done;
+ }
+
+ if (getifaddrs(&ifap) < 0) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("could not get interface info, getifaddrs() failed: %s"),
+ strerror(errno));
+ goto done;
+ }
+
+ /* update list of interfaces & link status */
+ for (scan = ifap; scan != NULL; scan = scan->ifa_next) {
+ if (scan->ifa_addr == NULL
+ || scan->ifa_addr->sa_family != AF_LINK) {
+ continue;
+ }
+ /* get the per-interface link/media information */
+ link_add(scan->ifa_name);
+ }
+
+ /*
+ * update IPv4 network addresses already assigned to
+ * the interfaces.
+ */
+ interface_update_ipv4(ifap, NULL);
+
+ /*
+ * update IPv6 network addresses already assigned to
+ * the interfaces.
+ */
+ interface_update_ipv6(ifap, NULL);
+
+ /*
+ * update AppleTalk network addresses already assigned
+ * to the interfaces.
+ */
+ interface_update_appletalk(ifap, NULL);
+
+ freeifaddrs(ifap);
+
+ done:
+ if (sock >= 0)
+ close(sock);
+
+ cache_write(store);
+ cache_close();
+
+ return;
+}
+
+
+__private_extern__
+void
+load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ int so;
+ int status;
+ struct kev_request kev_req;
+ CFSocketRef es;
+ CFSocketContext context = { 0, NULL, NULL, NULL, NULL };
+ CFRunLoopSourceRef rls;
+
+ if (bundleVerbose) {
+ _verbose = TRUE;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+ /* open a "configd" session to allow cache updates */
+ store = SCDynamicStoreCreate(NULL,
+ CFSTR("Kernel Event Monitor plug-in"),
+ NULL,
+ NULL);
+ if (!store) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDnamicStoreCreate() failed: %s"), SCErrorString(SCError()));
+ SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
+ return;
+ }
+
+ /* Open an event socket */
+ so = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
+ if (so != -1) {
+ /* establish filter to return all events */
+ kev_req.vendor_code = 0;
+ kev_req.kev_class = 0; /* Not used if vendor_code is 0 */
+ kev_req.kev_subclass = 0; /* Not used if either kev_class OR vendor_code are 0 */
+ status = ioctl(so, SIOCSKEVFILT, &kev_req);
+ if (status) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not establish event filter, ioctl() failed: %s"), strerror(errno));
+ (void) close(so);
+ so = -1;
+ }
+ } else {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not open event socket, socket() failed: %s"), strerror(errno));
+ }
+
+ if (so != -1) {
+ int yes = 1;
+
+ status = ioctl(so, FIONBIO, &yes);
+ if (status) {
+ SCLog(TRUE, LOG_ERR, CFSTR("could not set non-blocking io, ioctl() failed: %s"), strerror(errno));
+ (void) close(so);
+ so = -1;
+ }
+ }
+
+ if (so == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
+ CFRelease(store);
+ return;
+ }
+
+ /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */
+ es = CFSocketCreateWithNative(NULL,
+ so,
+ kCFSocketReadCallBack,
+ eventCallback,
+ &context);
+
+ /* Create and add a run loop source for the event socket */
+ rls = CFSocketCreateRunLoopSource(NULL, es, 0);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+ CFRelease(rls);
+ CFRelease(es);
+
+ return;
+}
+
+#ifdef MAIN
+
+#include "ev_dlil.c"
+
+#define appendAddress appendAddress_v4
+#define getIF getIF_v4
+#define updateStore updateStore_v4
+#include "ev_ipv4.c"
+#undef appendAddress
+#undef getIF
+#undef updateStore
+
+#define appendAddress appendAddress_v6
+#define getIF getIF_v6
+#define updateStore updateStore_v6
+#include "ev_ipv6.c"
+#undef appendAddress
+#undef getIF
+#undef updateStore
+
+#define getIF getIF_at
+#define updateStore updateStore_at
+#include "ev_appletalk.c"
+#undef getIF
+#undef updateStore
+
+int
+main(int argc, char **argv)
+{
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_KernelEventMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ prime_KernelEventMonitor();
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2002 Allan Nathanson <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EVENTMON_H
+#define _EVENTMON_H
+
+#include <sys/cdefs.h>
+#include <unistd.h>
+#include <sys/types.h>
+#define KERNEL_PRIVATE
+#include <sys/sockio.h>
+#undef KERNEL_PRIVATE
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/filio.h>
+#include <sys/kern_event.h>
+#include <errno.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+
+extern SCDynamicStoreRef store;
+extern Boolean _verbose;
+
+
+__BEGIN_DECLS
+
+int dgram_socket (int domain);
+
+__END_DECLS
+
+#endif /* _EVENTMON_H */
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>Kicker</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.Kicker</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.ATconfig</string>
+ <string>com.apple.SystemConfiguration.IPConfiguration</string>
+ <string>com.apple.SystemConfiguration.IPMonitor</string>
+ </array>
+ <key>Builtin</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+ <dict>
+ <key>execCommand</key>
+ <string>$BUNDLE/Contents/Resources/enable-network</string>
+ <key>execUID</key>
+ <integer>0</integer>
+ <key>keys</key>
+ <array>
+ <string>State:/Network/Global/IPv4</string>
+ </array>
+ <key>name</key>
+ <string>enable-network</string>
+ </dict>
+ <dict>
+ <key>keys</key>
+ <array>
+ <string>State:/Network/Global/DNS</string>
+ <string>State:/Network/Global/IPv4</string>
+ <string>State:/Network/Global/IPv6</string>
+ <string>State:/Network/Global/NetInfo</string>
+ </array>
+ <key>name</key>
+ <string>network_change</string>
+ <key>postName</key>
+ <string>com.apple.system.config.network_change</string>
+ </dict>
+ <dict>
+ <key>execCommand</key>
+ <string>/usr/sbin/AppleFileServer</string>
+ <key>execUID</key>
+ <integer>0</integer>
+ <key>keys</key>
+ <array>
+ <string>daemon:AppleFileServer</string>
+ </array>
+ <key>name</key>
+ <string>AppleFileServer</string>
+ </dict>
+</array>
+</plist>
--- /dev/null
+#!/bin/sh
+#
+# network configuration has changed
+#
+logger -i -p daemon.debug -t enable-network "process network configuration change"
+
+. /etc/rc.common
+CheckForNetwork
+if [ "${NETWORKUP}" = "-NO-" ]; then exit 0; fi
+
+/System/Library/StartupItems/NetworkTime/NetworkTime start
+/System/Library/StartupItems/NIS/NIS start
+/System/Library/StartupItems/NFS/NFS start
+
+exit 1
--- /dev/null
+/*
+ * Copyright (c) 2000-2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * April 16, 2002 Allan Nathanson <ajn@apple.com>
+ * - updated to use _SCDPluginExecCommand()
+ *
+ * June 23, 2001 Allan Nathanson <ajn@apple.com>
+ * - updated to public SystemConfiguration.framework APIs
+ *
+ * June 4, 2001 Allan Nathanson <ajn@apple.com>
+ * - add changed keys as the arguments to the kicker script
+ *
+ * June 30, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <notify.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h> // for SCLog()
+#include <SystemConfiguration/SCDPlugin.h>
+#include <SystemConfiguration/SCValidation.h>
+
+/*
+ * Information maintained for each to-be-kicked registration.
+ */
+typedef struct {
+ boolean_t active;
+ boolean_t needsKick;
+
+ /* dictionary associated with this target */
+ CFDictionaryRef dict;
+
+ /* SCDynamicStore session information for this target */
+ CFRunLoopRef rl;
+ CFRunLoopSourceRef rls;
+ SCDynamicStoreRef store;
+
+ /* changed keys */
+ CFMutableArrayRef changedKeys;
+} kickee, *kickeeRef;
+
+static CFURLRef myBundleURL = NULL;
+static Boolean _verbose = FALSE;
+
+static void booter(kickeeRef target);
+static void booterExit(pid_t pid, int status, struct rusage *rusage, void *context);
+
+
+static void
+cleanupKicker(kickeeRef target)
+{
+ CFStringRef name = CFDictionaryGetValue(target->dict, CFSTR("name"));
+
+ SCLog(TRUE, LOG_NOTICE,
+ CFSTR(" target=%@: disabled"),
+ name);
+ CFRunLoopRemoveSource(target->rl, target->rls, kCFRunLoopDefaultMode);
+ CFRelease(target->rls);
+ CFRelease(target->store);
+ if (target->dict) CFRelease(target->dict);
+ if (target->changedKeys) CFRelease(target->changedKeys);
+ CFAllocatorDeallocate(NULL, target);
+}
+
+
+static void
+booter(kickeeRef target)
+{
+ char **argv = NULL;
+ char *cmd = NULL;
+ CFStringRef execCommand = CFDictionaryGetValue(target->dict, CFSTR("execCommand"));
+ int i;
+ CFArrayRef keys = NULL;
+ CFStringRef name = CFDictionaryGetValue(target->dict, CFSTR("name"));
+ int nKeys = 0;
+ Boolean ok = FALSE;
+ CFStringRef postName = CFDictionaryGetValue(target->dict, CFSTR("postName"));
+
+ if (target->active) {
+ /* we need another kick! */
+ target->needsKick = TRUE;
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("Kicker callback, target=%@ request queued"), name);
+ return;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("Kicker callback, target=%@"), name);
+
+ if (!isA_CFString(postName) && !isA_CFString(execCommand)) {
+ goto error; /* if no notifications to post nor commands to execute */
+ }
+
+ if (isA_CFString(postName)) {
+ uint32_t status;
+
+ /*
+ * post a notification
+ */
+ cmd = _SC_cfstring_to_cstring(postName, NULL, 0, kCFStringEncodingASCII);
+ if (!cmd) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" could not convert post name to C string"));
+ goto error;
+ }
+
+ SCLog(TRUE, LOG_NOTICE, CFSTR("posting notification %s"), cmd);
+ status = notify_post(cmd);
+ if (status != NOTIFY_STATUS_OK) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" notify_post() failed: error=%ld"), status);
+ goto error;
+ }
+
+ CFAllocatorDeallocate(NULL, cmd); /* clean up */
+ cmd = NULL;
+ }
+
+ /*
+ * get the arguments for the kickee
+ */
+ keys = target->changedKeys;
+ target->changedKeys = NULL;
+
+ if (isA_CFString(execCommand)) {
+ CFRange bpr;
+ CFNumberRef execGID = CFDictionaryGetValue(target->dict, CFSTR("execGID"));
+ CFNumberRef execUID = CFDictionaryGetValue(target->dict, CFSTR("execUID"));
+ CFBooleanRef passKeys = CFDictionaryGetValue(target->dict, CFSTR("changedKeysAsArguments"));
+ gid_t reqGID = 0;
+ uid_t reqUID = 0;
+ CFMutableStringRef str;
+
+ /*
+ * build the kickee command
+ */
+ str = CFStringCreateMutableCopy(NULL, 0, execCommand);
+ bpr = CFStringFind(str, CFSTR("$BUNDLE"), 0);
+ if (bpr.location != kCFNotFound) {
+ CFStringRef bundlePath;
+
+ bundlePath = CFURLCopyFileSystemPath(myBundleURL, kCFURLPOSIXPathStyle);
+ CFStringReplace(str, bpr, bundlePath);
+ CFRelease(bundlePath);
+ }
+
+ cmd = _SC_cfstring_to_cstring(str, NULL, 0, kCFStringEncodingASCII);
+ CFRelease(str);
+ if (!cmd) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" could not convert command to C string"));
+ goto error;
+ }
+
+ /*
+ * get the UID/GID for the kickee
+ */
+ if (isA_CFNumber(execUID)) {
+ CFNumberGetValue(execUID, kCFNumberIntType, &reqUID);
+ }
+
+ if (isA_CFNumber(execGID)) {
+ CFNumberGetValue(execGID, kCFNumberIntType, &reqGID);
+ }
+
+ nKeys = CFArrayGetCount(keys);
+ argv = CFAllocatorAllocate(NULL, (nKeys + 2) * sizeof(char *), 0);
+ for (i = 0; i < (nKeys + 2); i++) {
+ argv[i] = NULL;
+ }
+
+ /* create command name argument */
+ if ((argv[0] = rindex(cmd, '/')) != NULL) {
+ argv[0]++;
+ } else {
+ argv[0] = cmd;
+ }
+
+ /* create changed key arguments */
+ if (isA_CFBoolean(passKeys) && CFBooleanGetValue(passKeys)) {
+ for (i = 0; i < nKeys; i++) {
+ CFStringRef key = CFArrayGetValueAtIndex(keys, i);
+
+ argv[i+1] = _SC_cfstring_to_cstring(key, NULL, 0, kCFStringEncodingASCII);
+ if (!argv[i+1]) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" could not convert argument to C string"));
+ goto error;
+ }
+ }
+ }
+
+ SCLog(TRUE, LOG_NOTICE, CFSTR("executing %s"), cmd);
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" current uid = %d, requested = %d"), geteuid(), reqUID);
+
+ /* this kicker is now "running" */
+ target->active = TRUE;
+
+ (void)_SCDPluginExecCommand(booterExit,
+ target,
+ reqUID,
+ reqGID,
+ cmd,
+ argv);
+
+// CFAllocatorDeallocate(NULL, cmd); /* clean up */
+// cmd = NULL;
+ }
+ ok = TRUE;
+
+ error :
+
+ if (keys) CFRelease(keys);
+ if (cmd) CFAllocatorDeallocate(NULL, cmd);
+ if (argv) {
+ for (i = 0; i < nKeys; i++) {
+ if (argv[i+1]) {
+ CFAllocatorDeallocate(NULL, argv[i+1]);
+ }
+ }
+ CFAllocatorDeallocate(NULL, argv);
+ }
+
+ if (!ok) {
+ /*
+ * If the target action can't be performed this time then
+ * there's not much point in trying again. As such, I close
+ * the session and the kickee target released.
+ */
+ cleanupKicker(target);
+ }
+
+ return;
+}
+
+
+static void
+booterExit(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+ CFStringRef name;
+ Boolean ok = TRUE;
+ kickeeRef target = (kickeeRef)context;
+
+ name = CFDictionaryGetValue(target->dict, CFSTR("name"));
+ target->active = FALSE;
+ if (WIFEXITED(status)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR(" target=%@: exit status = %d"),
+ name,
+ WEXITSTATUS(status));
+ if (WEXITSTATUS(status) != 0) {
+ ok = FALSE;
+ }
+ } else if (WIFSIGNALED(status)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR(" target=%@: terminated w/signal = %d"),
+ name,
+ WTERMSIG(status));
+ ok = FALSE;
+ } else {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR(" target=%@: exit status = %d"),
+ name,
+ status);
+ ok = FALSE;
+ }
+
+ if (!ok) {
+ if (CFDictionaryContainsKey(target->dict, CFSTR("postName"))) {
+ CFDictionaryRef oldDict = target->dict;
+ CFMutableDictionaryRef newDict = CFDictionaryCreateMutableCopy(NULL, 0, oldDict);
+
+ /*
+ * if this target specifies both a BSD notification and
+ * a script to be executed then we want to continue to
+ * post the BSD notifications (and not execute the
+ * script). As such, remove the script reference from
+ * the dictionary.
+ */
+ CFDictionaryRemoveValue(newDict, CFSTR("execCommand"));
+ CFDictionaryRemoveValue(newDict, CFSTR("execGID"));
+ CFDictionaryRemoveValue(newDict, CFSTR("execUID"));
+ CFDictionaryRemoveValue(newDict, CFSTR("changedKeysAsArguments"));
+ target->dict = newDict;
+ CFRelease(oldDict);
+ } else {
+ /*
+ * If the target action can't be performed this time then
+ * there's not much point in trying again. As such, I close
+ * the session and the kickee target released.
+ */
+ cleanupKicker(target);
+ target = NULL;
+ }
+ }
+ if (target != NULL && target->needsKick) {
+ target->needsKick = FALSE;
+ booter(target);
+ }
+
+ return;
+}
+
+
+static void
+kicker(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg)
+{
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(changedKeys);
+ kickeeRef target = (kickeeRef)arg;
+
+ /*
+ * Start a new kicker. If a kicker was already active then flag
+ * the need for a second kick after the active one completes.
+ */
+
+ /* create (or add to) the full list of keys that have changed */
+ if (!target->changedKeys) {
+ target->changedKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ for (i = 0; i < n; i++) {
+ CFStringRef key = CFArrayGetValueAtIndex(changedKeys, i);
+
+ if (!CFArrayContainsValue(target->changedKeys,
+ CFRangeMake(0, CFArrayGetCount(target->changedKeys)),
+ key)) {
+ CFArrayAppendValue(target->changedKeys, key);
+ }
+ }
+
+ /*
+ * let 'er rip.
+ */
+ booter(target);
+
+ return;
+}
+
+
+/*
+ * startKicker()
+ *
+ * The first argument is a dictionary representing the keys
+ * which need to be monitored for a given "target" and what
+ * action should be taken if a change in one of those keys
+ * is detected.
+ */
+static void
+startKicker(const void *value, void *context)
+{
+ CFMutableStringRef name;
+ CFArrayRef keys;
+ CFArrayRef patterns;
+ kickeeRef target = CFAllocatorAllocate(NULL, sizeof(kickee), 0);
+ SCDynamicStoreContext targetContext = { 0, (void *)target, NULL, NULL, NULL };
+
+ target->active = FALSE;
+ target->needsKick = FALSE;
+ target->dict = CFRetain((CFDictionaryRef)value);
+ target->store = NULL;
+ target->rl = NULL;
+ target->rls = NULL;
+ target->changedKeys = NULL;
+
+ name = CFStringCreateMutableCopy(NULL,
+ 0,
+ CFDictionaryGetValue(target->dict, CFSTR("name")));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("Starting kicker for %@"), name);
+
+ CFStringAppend(name, CFSTR(" \"Kicker\""));
+ target->store = SCDynamicStoreCreate(NULL, name, kicker, &targetContext);
+ CFRelease(name);
+ if (!target->store) {
+ SCLog(TRUE,
+ LOG_NOTICE,
+ CFSTR("SCDynamicStoreCreate() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ keys = isA_CFArray(CFDictionaryGetValue(target->dict, CFSTR("keys")));
+ patterns = isA_CFArray(CFDictionaryGetValue(target->dict, CFSTR("regexKeys")));
+ if (!SCDynamicStoreSetNotificationKeys(target->store, keys, patterns)) {
+ SCLog(TRUE,
+ LOG_NOTICE,
+ CFSTR("SCDynamicStoreSetNotifications() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ target->rl = CFRunLoopGetCurrent();
+ target->rls = SCDynamicStoreCreateRunLoopSource(NULL, target->store, 0);
+ if (!target->rls) {
+ SCLog(TRUE,
+ LOG_NOTICE,
+ CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ CFRunLoopAddSource(target->rl, target->rls, kCFRunLoopDefaultMode);
+ return;
+
+ error :
+
+ CFRelease(target->dict);
+ if (target->store) CFRelease(target->store);
+ CFAllocatorDeallocate(NULL, target);
+ return;
+}
+
+
+static CFArrayRef
+getTargets(CFBundleRef bundle)
+{
+ Boolean ok;
+ CFArrayRef targets; /* The array of dictionaries
+ representing targets with
+ a "kick me" sign posted on
+ their backs. */
+ CFURLRef url;
+ CFStringRef xmlError;
+ CFDataRef xmlTargets = NULL;
+
+ /* locate the Kicker targets */
+ url = CFBundleCopyResourceURL(bundle, CFSTR("Kicker"), CFSTR("xml"), NULL);
+ if (url == NULL) {
+ return NULL;
+ }
+
+ /* read the resource data */
+ ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlTargets, NULL, NULL, NULL);
+ CFRelease(url);
+ if (!ok || (xmlTargets == NULL)) {
+ return NULL;
+ }
+
+ /* convert the XML data into a property list */
+ targets = CFPropertyListCreateFromXMLData(NULL,
+ xmlTargets,
+ kCFPropertyListImmutable,
+ &xmlError);
+ CFRelease(xmlTargets);
+ if (targets == NULL) {
+ if (xmlError != NULL) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("getTargets(): %@"), xmlError);
+ CFRelease(xmlError);
+ }
+ return NULL;
+ }
+
+ if (!isA_CFArray(targets)) {
+ CFRelease(targets);
+ targets = NULL;
+ }
+
+ return targets;
+}
+
+
+__private_extern__
+void
+load_Kicker(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ CFArrayRef targets; /* The array of dictionaries representing targets
+ * with a "kick me" sign posted on their backs.*/
+
+ if (bundleVerbose) {
+ _verbose = TRUE;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+ /* get the bundle's URL */
+ myBundleURL = CFBundleCopyBundleURL(bundle);
+ if (myBundleURL == NULL) {
+ return;
+ }
+
+ /* get the targets */
+ targets = getTargets(bundle);
+ if (targets == NULL) {
+ /* if nothing to do */
+ CFRelease(myBundleURL);
+ return;
+ }
+
+ /* start a kicker for each target */
+ CFArrayApplyFunction(targets,
+ CFRangeMake(0, CFArrayGetCount(targets)),
+ startKicker,
+ NULL);
+ CFRelease(targets);
+
+ return;
+}
+
+#ifdef MAIN
+int
+main(int argc, char * const argv[])
+{
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_Kicker(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>LinkConfiguration</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.LinkConfiguration</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Requires</key>
+ <array>
+ <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+ </array>
+ <key>Builtin</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2002-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * October 21, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+//#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/LinkConfiguration.h>
+#include <SystemConfiguration/SCDPlugin.h> // for _SCDPluginExecCommand
+
+
+static CFMutableDictionaryRef baseSettings = NULL;
+static SCDynamicStoreRef store = NULL;
+static CFRunLoopSourceRef rls = NULL;
+
+static Boolean _verbose = FALSE;
+
+
+/* in SystemConfiguration/LinkConfiguration.c */
+int
+__createMediaOptions(CFDictionaryRef media_options);
+
+
+__private_extern__
+Boolean
+_NetworkInterfaceSetMediaOptions(CFStringRef interface,
+ CFDictionaryRef options)
+{
+ CFArrayRef available = NULL;
+ CFDictionaryRef current = NULL;
+ struct ifmediareq ifm;
+ struct ifreq ifr;
+ Boolean ok = FALSE;
+ int newOptions;
+ CFMutableDictionaryRef requested = NULL;
+ int sock = -1;
+ CFTypeRef val;
+
+ /* get current & available options */
+ if (!NetworkInterfaceCopyMediaOptions(interface, ¤t, NULL, &available, FALSE)) {
+ return FALSE;
+ }
+
+ /* extract just the dictionary key/value pairs of interest */
+ requested = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ val = CFDictionaryGetValue(options, kSCPropNetEthernetMediaSubType);
+ if (!val) {
+ val = CFDictionaryGetValue(current, kSCPropNetEthernetMediaSubType);
+ }
+ if (isA_CFString(val)) {
+ CFDictionaryAddValue(requested, kSCPropNetEthernetMediaSubType, val);
+ } else {
+ /* if garbage */;
+ goto done;
+ }
+
+ val = CFDictionaryGetValue(options, kSCPropNetEthernetMediaOptions);
+ if (!val) {
+ val = CFDictionaryGetValue(current, kSCPropNetEthernetMediaOptions);
+ }
+ if (isA_CFArray(val)) {
+ CFDictionaryAddValue(requested, kSCPropNetEthernetMediaOptions, val);
+ } else {
+ /* if garbage */;
+ goto done;
+ }
+
+ if (current && CFEqual(current, requested)) {
+ /* if current settings are as requested */
+ ok = TRUE;
+ goto done;
+ }
+
+ if (!CFArrayContainsValue(available, CFRangeMake(0, CFArrayGetCount(available)), requested)) {
+ /* if requested settings not currently available */
+ SCLog(TRUE, LOG_DEBUG, CFSTR("requested media settings unavailable"));
+ goto done;
+ }
+
+ newOptions = __createMediaOptions(requested);
+ if (newOptions == -1) {
+ /* since we have just validated, this should never happen */
+ goto done;
+ }
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
+ goto done;
+ }
+
+ bzero((char *)&ifm, sizeof(ifm));
+ (void)_SC_cfstring_to_cstring(interface, ifm.ifm_name, sizeof(ifm.ifm_name), kCFStringEncodingASCII);
+
+ if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifm) < 0) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("ioctl(SIOCGIFMEDIA) failed: %s"), strerror(errno));
+ goto done;
+ }
+
+ bzero((char *)&ifr, sizeof(ifr));
+ bcopy(ifm.ifm_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+ ifr.ifr_media = ifm.ifm_current & ~(IFM_NMASK|IFM_TMASK|IFM_OMASK|IFM_GMASK);
+ ifr.ifr_media |= newOptions;
+
+//SCLog(TRUE, LOG_INFO, CFSTR("old media settings: 0x%8.8x (0x%8.8x)"), ifm.ifm_current, ifm.ifm_active);
+//SCLog(TRUE, LOG_INFO, CFSTR("new media settings: 0x%8.8x"), ifr.ifr_media);
+
+ if (ioctl(sock, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("ioctl(SIOCSIFMEDIA) failed: %s"), strerror(errno));
+ goto done;
+ }
+
+ ok = TRUE;
+
+ done :
+
+ if (available) CFRelease(available);
+ if (current) CFRelease(current);
+ if (requested) CFRelease(requested);
+ if (sock >= 0) (void)close(sock);
+
+ return ok;
+}
+
+
+#ifndef USE_SIOCSIFMTU
+static void
+ifconfig_exit(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+ char *if_name = (char *)context;
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("ifconfig %s failed, exit status = %d"),
+ if_name,
+ WEXITSTATUS(status));
+ }
+ } else if (WIFSIGNALED(status)) {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("ifconfig %s: terminated w/signal = %d"),
+ if_name,
+ WTERMSIG(status));
+ } else {
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("ifconfig %s: exit status = %d"),
+ if_name,
+ status);
+ }
+
+ CFAllocatorDeallocate(NULL, if_name);
+ return;
+}
+#endif /* !USE_SIOCSIFMTU */
+
+
+__private_extern__
+Boolean
+_NetworkInterfaceSetMTU(CFStringRef interface,
+ CFDictionaryRef options)
+{
+ int mtu_cur = -1;
+ int mtu_max = -1;
+ int mtu_min = -1;
+ int requested;
+ CFNumberRef val;
+
+ if (!NetworkInterfaceCopyMTU(interface, &mtu_cur, &mtu_min, &mtu_max)) {
+ /* could not get current MTU */
+ return FALSE;
+ }
+
+ val = CFDictionaryGetValue(options, kSCPropNetEthernetMTU);
+ if (val) {
+ if (isA_CFNumber(val)) {
+ CFNumberGetValue(val, kCFNumberIntType, &requested);
+ } else {
+ return FALSE;
+ }
+ } else {
+ requested = mtu_cur;
+ }
+
+ if (requested == mtu_cur) {
+ /* if current setting is as requested */
+ return TRUE;
+ }
+
+ if (((mtu_min >= 0) && (requested < mtu_min)) ||
+ ((mtu_max >= 0) && (requested > mtu_max))) {
+ /* if requested MTU outside of the valid range */
+ return FALSE;
+ }
+
+#ifdef USE_SIOCSIFMTU
+{
+ struct ifreq ifr;
+ int ret;
+ int sock;
+
+ bzero((char *)&ifr, sizeof(ifr));
+ (void)_SC_cfstring_to_cstring(interface, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII);
+ ifr.ifr_mtu = requested;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
+ return FALSE;
+ }
+
+ ret = ioctl(sock, SIOCSIFMTU, (caddr_t)&ifr);
+ (void)close(sock);
+ if (ret == -1) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("ioctl(SIOCSIFMTU) failed: %s"), strerror(errno));
+ return FALSE;
+ }
+}
+#else /* !USE_SIOCSIFMTU */
+{
+ char *ifconfig_argv[] = { "ifconfig", NULL, "mtu", NULL, NULL };
+ pid_t pid;
+
+ ifconfig_argv[1] = _SC_cfstring_to_cstring(interface, NULL, 0, kCFStringEncodingASCII);
+ (void)asprintf(&ifconfig_argv[3], "%d", requested);
+
+ pid = _SCDPluginExecCommand(ifconfig_exit, // callout,
+ ifconfig_argv[1], // context
+ 0, // uid
+ 0, // gid
+ "/sbin/ifconfig", // path
+ ifconfig_argv // argv
+ );
+
+// CFAllocatorDeallocate(NULL, ifconfig_argv[1]); // released in ifconfig_exit()
+ free(ifconfig_argv[3]);
+
+ if (pid <= 0) {
+ return FALSE;
+ }
+}
+#endif /* !USE_SIOCSIFMTU */
+
+ return TRUE;
+}
+
+
+/*
+ * Function: parse_component
+ * Purpose:
+ * Given a string 'key' and a string prefix 'prefix',
+ * return the next component in the slash '/' separated
+ * key.
+ *
+ * Examples:
+ * 1. key = "a/b/c" prefix = "a/"
+ * returns "b"
+ * 2. key = "a/b/c" prefix = "a/b/"
+ * returns "c"
+ */
+static CFStringRef
+parse_component(CFStringRef key, CFStringRef prefix)
+{
+ CFMutableStringRef comp;
+ CFRange range;
+
+ if (CFStringHasPrefix(key, prefix) == FALSE) {
+ return NULL;
+ }
+ comp = CFStringCreateMutableCopy(NULL, 0, key);
+ CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
+ range = CFStringFind(comp, CFSTR("/"), 0);
+ if (range.location == kCFNotFound) {
+ return comp;
+ }
+ range.length = CFStringGetLength(comp) - range.location;
+ CFStringDelete(comp, range);
+ return comp;
+}
+
+
+static void
+updateLink(CFStringRef ifKey, CFDictionaryRef options)
+{
+ CFStringRef interface = NULL;
+ static CFStringRef prefix = NULL;
+
+ if (!prefix) {
+ prefix = SCDynamicStoreKeyCreate(NULL,
+ CFSTR("%@/%@/%@/"),
+ kSCDynamicStoreDomainSetup,
+ kSCCompNetwork,
+ kSCCompInterface);
+ }
+
+ interface = parse_component(ifKey, prefix);
+ if (!interface) {
+ goto done;
+ }
+
+ if (options) {
+ if (!CFDictionaryContainsKey(baseSettings, interface)) {
+ CFDictionaryRef cur_media = NULL;
+ CFMutableDictionaryRef new_media = NULL;
+ int cur_mtu = -1;
+ CFNumberRef num;
+
+ if (!NetworkInterfaceCopyMediaOptions(interface, &cur_media, NULL, NULL, FALSE)) {
+ /* could not determine current settings */
+ goto done;
+ }
+
+ if (!cur_media) {
+ /* could not determine current settings */
+ goto done;
+ }
+
+ if (!NetworkInterfaceCopyMTU(interface, &cur_mtu, NULL, NULL)) {
+ /* could not determine current MTU */
+ CFRelease(cur_media);
+ goto done;
+ }
+
+ if (cur_mtu < 0) {
+ /* could not determine current MTU */
+ CFRelease(cur_media);
+ goto done;
+ }
+
+ new_media = CFDictionaryCreateMutableCopy(NULL, 0, cur_media);
+ CFRelease(cur_media);
+
+ num = CFNumberCreate(NULL, kCFNumberIntType, &cur_mtu);
+ CFDictionaryAddValue(new_media, kSCPropNetEthernetMTU, num);
+ CFRelease(num);
+
+ CFDictionarySetValue(baseSettings, interface, new_media);
+ CFRelease(new_media);
+ }
+
+ /* establish new settings */
+ (void)_NetworkInterfaceSetMediaOptions(interface, options);
+ (void)_NetworkInterfaceSetMTU (interface, options);
+ } else {
+ /* no requested settings */
+ options = CFDictionaryGetValue(baseSettings, interface);
+ if (options) {
+ /* restore original settings */
+ (void)_NetworkInterfaceSetMediaOptions(interface, options);
+ (void)_NetworkInterfaceSetMTU (interface, options);
+ CFDictionaryRemoveValue(baseSettings, interface);
+ }
+ }
+
+ done :
+
+ if (interface) CFRelease(interface);
+ return;
+}
+
+
+static void
+linkConfigChangedCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg)
+{
+ CFIndex i;
+ CFIndex n;
+ CFDictionaryRef linkInfo;
+
+ linkInfo = SCDynamicStoreCopyMultiple(store, changedKeys, NULL);
+
+ n = CFArrayGetCount(changedKeys);
+ for (i = 0; i < n; i++) {
+ CFStringRef key;
+ CFDictionaryRef link;
+
+ key = CFArrayGetValueAtIndex(changedKeys, i);
+ link = CFDictionaryGetValue(linkInfo, key);
+ updateLink(key, link);
+ }
+
+ CFRelease(linkInfo);
+
+ return;
+}
+
+
+__private_extern__
+void
+load_LinkConfiguration(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ CFStringRef key;
+ CFMutableArrayRef patterns = NULL;
+
+ if (bundleVerbose) {
+ _verbose = TRUE;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+ /* initialize a few globals */
+
+ baseSettings = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ /* open a "configd" store to allow cache updates */
+ store = SCDynamicStoreCreate(NULL,
+ CFSTR("Link Configuraton plug-in"),
+ linkConfigChangedCallback,
+ NULL);
+ if (!store) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed: %s"), SCErrorString(SCError()));
+ goto error;
+ }
+
+ /* establish notification keys and patterns */
+
+ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ /* ...watch for (per-interface) Ethernet configuration changes */
+ key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ kSCDynamicStoreDomainSetup,
+ kSCCompAnyRegex,
+ kSCEntNetEthernet);
+ CFArrayAppendValue(patterns, key);
+ CFRelease(key);
+
+ /* register the keys/patterns */
+ if (!SCDynamicStoreSetNotificationKeys(store, NULL, patterns)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+ if (!rls) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+
+ CFRelease(patterns);
+ return;
+
+ error :
+
+ if (baseSettings) CFRelease(baseSettings);
+ if (store) CFRelease(store);
+ if (patterns) CFRelease(patterns);
+ return;
+}
+
+
+#ifdef MAIN
+int
+main(int argc, char **argv)
+{
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_LinkConfiguration(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>PreferencesMonitor</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>Builtin</key>
+ <true/>
+</dict>
+</plist>
--- /dev/null
+/*
+ * Copyright (c) 2000-2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * April 2, 2004 Allan Nathanson <ajn@apple.com>
+ * - use SCPreference notification APIs
+ *
+ * June 24, 2001 Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * November 10, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+
+static SCPreferencesRef prefs = NULL;
+static SCDynamicStoreRef store = NULL;
+
+static CFMutableDictionaryRef currentPrefs; /* current prefs */
+static CFMutableDictionaryRef newPrefs; /* new prefs */
+static CFMutableArrayRef unchangedPrefsKeys; /* new prefs keys which match current */
+static CFMutableArrayRef removedPrefsKeys; /* old prefs keys to be removed */
+
+static Boolean _verbose = FALSE;
+
+
+static void
+updateCache(const void *key, const void *value, void *context)
+{
+ CFStringRef configKey = (CFStringRef)key;
+ CFPropertyListRef configData = (CFPropertyListRef)value;
+ CFPropertyListRef cacheData;
+ CFIndex i;
+
+ cacheData = CFDictionaryGetValue(currentPrefs, configKey);
+ if (cacheData) {
+ /* key exists */
+ if (CFEqual(cacheData, configData)) {
+ /*
+ * if the old & new property list values have
+ * not changed then we don't need to update
+ * the preference.
+ */
+ CFArrayAppendValue(unchangedPrefsKeys, configKey);
+ }
+ }
+
+ /* in any case, this key should not be removed */
+ i = CFArrayGetFirstIndexOfValue(removedPrefsKeys,
+ CFRangeMake(0, CFArrayGetCount(removedPrefsKeys)),
+ configKey);
+ if (i != kCFNotFound) {
+ CFArrayRemoveValueAtIndex(removedPrefsKeys, i);
+ }
+
+ return;
+}
+
+
+static void
+flatten(SCPreferencesRef prefs,
+ CFStringRef key,
+ CFDictionaryRef base)
+{
+ CFDictionaryRef subset;
+ CFStringRef link;
+ CFMutableDictionaryRef myDict;
+ CFStringRef myKey;
+ CFIndex i;
+ CFIndex nKeys;
+ const void **keys;
+ const void **vals;
+
+ if (!CFDictionaryGetValueIfPresent(base, kSCResvLink, (const void **)&link)) {
+ /* if this dictionary is not linked */
+ subset = base;
+ } else {
+ /* if __LINK__ key is present */
+ subset = SCPreferencesPathGetValue(prefs, link);
+ if (!subset) {
+ /* if error with link */
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCPreferencesPathGetValue(,%@,) failed: %s"),
+ link,
+ SCErrorString(SCError()));
+ return;
+ }
+ }
+
+ if (CFDictionaryContainsKey(subset, kSCResvInactive)) {
+ /* if __INACTIVE__ key is present */
+ return;
+ }
+
+ myKey = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("%@%@"),
+ kSCDynamicStoreDomainSetup,
+ key);
+
+ myDict = (CFMutableDictionaryRef)CFDictionaryGetValue(newPrefs, myKey);
+ if (myDict) {
+ myDict = CFDictionaryCreateMutableCopy(NULL,
+ 0,
+ (CFDictionaryRef)myDict);
+ } else {
+ myDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ nKeys = CFDictionaryGetCount(subset);
+ if (nKeys > 0) {
+ keys = CFAllocatorAllocate(NULL, nKeys * sizeof(CFStringRef) , 0);
+ vals = CFAllocatorAllocate(NULL, nKeys * sizeof(CFPropertyListRef), 0);
+ CFDictionaryGetKeysAndValues(subset, keys, vals);
+ for (i = 0; i < nKeys; i++) {
+ if (CFGetTypeID((CFTypeRef)vals[i]) != CFDictionaryGetTypeID()) {
+ /* add this key/value to the current dictionary */
+ CFDictionarySetValue(myDict, keys[i], vals[i]);
+ } else {
+ CFStringRef subKey;
+
+ /* flatten [sub]dictionaries */
+ subKey = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("%@%s%@"),
+ key,
+ CFEqual(key, CFSTR("/")) ? "" : "/",
+ keys[i]);
+ flatten(prefs, subKey, vals[i]);
+ CFRelease(subKey);
+ }
+ }
+ CFAllocatorDeallocate(NULL, keys);
+ CFAllocatorDeallocate(NULL, vals);
+ }
+
+ if (CFDictionaryGetCount(myDict) > 0) {
+ /* add this dictionary to the new preferences */
+ CFDictionarySetValue(newPrefs, myKey, myDict);
+ }
+
+ CFRelease(myDict);
+ CFRelease(myKey);
+
+ return;
+}
+
+
+static void
+updateConfiguration(SCPreferencesRef prefs,
+ SCPreferencesNotification notificationType,
+ void *info)
+{
+ CFStringRef current = NULL;
+ CFDateRef date = NULL;
+ CFMutableDictionaryRef dict = NULL;
+ CFDictionaryRef global = NULL;
+ CFIndex i;
+ CFArrayRef keys;
+ CFIndex n;
+ CFStringRef pattern;
+ CFMutableArrayRef patterns;
+ CFDictionaryRef set = NULL;
+
+ if ((notificationType & kSCPreferencesNotificationApply) != kSCPreferencesNotificationApply) {
+ return;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("updating configuration"));
+
+ /*
+ * initialize old preferences, new preferences, an array
+ * of keys which have not changed, and an array of keys
+ * to be removed (cleaned up).
+ */
+
+ patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ pattern = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("^%@.*"),
+ kSCDynamicStoreDomainSetup);
+ CFArrayAppendValue(patterns, pattern);
+ dict = (CFMutableDictionaryRef)SCDynamicStoreCopyMultiple(store, NULL, patterns);
+ CFRelease(patterns);
+ CFRelease(pattern);
+ if (dict) {
+ currentPrefs = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ CFRelease(dict);
+ } else {
+ currentPrefs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ unchangedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ i = CFDictionaryGetCount(currentPrefs);
+ if (i > 0) {
+ const void **currentKeys;
+ CFArrayRef array;
+
+ currentKeys = CFAllocatorAllocate(NULL, i * sizeof(CFStringRef), 0);
+ CFDictionaryGetKeysAndValues(currentPrefs, currentKeys, NULL);
+ array = CFArrayCreate(NULL, currentKeys, i, &kCFTypeArrayCallBacks);
+ removedPrefsKeys = CFArrayCreateMutableCopy(NULL, 0, array);
+ CFRelease(array);
+ CFAllocatorDeallocate(NULL, currentKeys);
+ } else {
+ removedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ /*
+ * The "newPrefs" dictionary will contain the new / updated
+ * configuration which will be written to the configuration cache.
+ */
+ newPrefs = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ /*
+ * create status dictionary associated with current configuration
+ * information including:
+ * - current set "name" to cache
+ * - time stamp indicating when the cache preferences were
+ * last updated.
+ */
+ dict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
+
+ /*
+ * load preferences
+ */
+ keys = SCPreferencesCopyKeyList(prefs);
+ if ((keys == NULL) || (CFArrayGetCount(keys) == 0)) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("updateConfiguration(): no preferences."));
+ goto done;
+ }
+
+ /*
+ * get "global" system preferences
+ */
+ (CFPropertyListRef)global = SCPreferencesGetValue(prefs, kSCPrefSystem);
+ if (!global) {
+ /* if no global preferences are defined */
+ goto getSet;
+ }
+
+ if (!isA_CFDictionary(global)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("updateConfiguration(): %@ is not a dictionary."),
+ kSCPrefSystem);
+ goto done;
+ }
+
+ /* flatten property list */
+ flatten(prefs, CFSTR("/"), global);
+
+ getSet :
+
+ /*
+ * get current set name
+ */
+ (CFPropertyListRef)current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+ if (!current) {
+ /* if current set not defined */
+ goto done;
+ }
+
+ if (!isA_CFString(current)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("updateConfiguration(): %@ is not a string."),
+ kSCPrefCurrentSet);
+ goto done;
+ }
+
+ /*
+ * get current set
+ */
+ (CFPropertyListRef)set = SCPreferencesPathGetValue(prefs, current);
+ if (!set) {
+ /* if error with path */
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("%@ value (%@) not valid"),
+ kSCPrefCurrentSet,
+ current);
+ goto done;
+ }
+
+ if (!isA_CFDictionary(set)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("updateConfiguration(): %@ is not a dictionary."),
+ current);
+ goto done;
+ }
+
+ /* flatten property list */
+ flatten(prefs, CFSTR("/"), set);
+
+ CFDictionarySetValue(dict, kSCDynamicStorePropSetupCurrentSet, current);
+
+ done :
+
+ /* add last updated time stamp */
+ CFDictionarySetValue(dict, kSCDynamicStorePropSetupLastUpdated, date);
+
+ /* add Setup: key */
+ CFDictionarySetValue(newPrefs, kSCDynamicStoreDomainSetup, dict);
+
+ /* compare current and new preferences */
+ CFDictionaryApplyFunction(newPrefs, updateCache, NULL);
+
+ /* remove those keys which have not changed from the update */
+ n = CFArrayGetCount(unchangedPrefsKeys);
+ for (i = 0; i < n; i++) {
+ CFStringRef key;
+
+ key = CFArrayGetValueAtIndex(unchangedPrefsKeys, i);
+ CFDictionaryRemoveValue(newPrefs, key);
+ }
+
+ /* Update the dynamic store */
+ if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
+ SCErrorString(SCError()));
+ }
+
+ /* finished with current prefs, wait for changes */
+ SCPreferencesSynchronize(prefs);
+
+ CFRelease(currentPrefs);
+ CFRelease(newPrefs);
+ CFRelease(unchangedPrefsKeys);
+ CFRelease(removedPrefsKeys);
+ if (dict) CFRelease(dict);
+ if (date) CFRelease(date);
+ if (keys) CFRelease(keys);
+ return;
+}
+
+
+__private_extern__
+void
+stop_PreferencesMonitor(CFRunLoopSourceRef stopRls)
+{
+ // cleanup
+
+ if (prefs != NULL) {
+ if (!SCPreferencesUnscheduleFromRunLoop(prefs,
+ CFRunLoopGetCurrent(),
+ kCFRunLoopDefaultMode)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCPreferencesUnscheduleFromRunLoop() failed: %s"),
+ SCErrorString(SCError()));
+ }
+ CFRelease(prefs);
+ prefs = NULL;
+ }
+
+ if (store != NULL) {
+ CFRelease(store);
+ store = NULL;
+ }
+
+ CFRunLoopSourceSignal(stopRls);
+ return;
+}
+
+
+__private_extern__
+void
+prime_PreferencesMonitor()
+{
+ SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
+
+ /* load the initial configuration from the database */
+ updateConfiguration(prefs, kSCPreferencesNotificationApply, (void *)store);
+
+ return;
+}
+
+
+__private_extern__
+void
+load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
+{
+ if (bundleVerbose) {
+ _verbose = TRUE;
+ }
+
+ SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+ SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+ /* open a SCDynamicStore session to allow cache updates */
+ store = SCDynamicStoreCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL, NULL);
+ if (store == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCDynamicStoreCreate() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ /* open a SCPreferences session */
+ prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL);
+ if (prefs == NULL) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCPreferencesCreate() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ if (!SCPreferencesSetCallback(prefs, updateConfiguration, NULL)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCPreferencesSetCallBack() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ /*
+ * register for change notifications.
+ */
+ if (!SCPreferencesScheduleWithRunLoop(prefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("SCPreferencesScheduleWithRunLoop() failed: %s"),
+ SCErrorString(SCError()));
+ goto error;
+ }
+
+ return;
+
+ error :
+
+ if (store) CFRelease(store);
+ if (prefs) CFRelease(prefs);
+
+ return;
+}
+
+
+#ifdef MAIN
+int
+main(int argc, char **argv)
+{
+ _sc_log = FALSE;
+ _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+ load_PreferencesMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+ prime_PreferencesMonitor();
+ CFRunLoopRun();
+ /* not reached */
+ exit(0);
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 1, 2003 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h> // for SCLog()
+
+#include "cache.h"
+
+
+static CFMutableDictionaryRef cached_keys = NULL;
+static CFMutableDictionaryRef cached_set = NULL;
+static CFMutableArrayRef cached_removals = NULL;
+static CFMutableArrayRef cached_notifys = NULL;
+
+
+__private_extern__
+void
+cache_open()
+{
+ cached_keys = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ cached_set = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ cached_removals = CFArrayCreateMutable(NULL,
+ 0,
+ &kCFTypeArrayCallBacks);
+ cached_notifys = CFArrayCreateMutable(NULL,
+ 0,
+ &kCFTypeArrayCallBacks);
+
+ return;
+}
+
+
+__private_extern__
+CFPropertyListRef
+cache_SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
+{
+ CFPropertyListRef value;
+
+ value = CFDictionaryGetValue(cached_set, key);
+ if (value) {
+ // if we have "set" a new value
+ return (CFRetain(value));
+ }
+
+ if (CFArrayContainsValue(cached_removals,
+ CFRangeMake(0, CFArrayGetCount(cached_removals)),
+ key)) {
+ // if we have "removed" the key
+ return NULL;
+ }
+
+ value = CFDictionaryGetValue(cached_keys, key);
+ if (value) {
+ // if we have a cached value
+ return (CFRetain(value));
+ }
+
+ value = SCDynamicStoreCopyValue(store, key);
+ if (value) {
+ CFDictionarySetValue(cached_keys, key, value);
+ }
+
+ return value;
+}
+
+
+__private_extern__
+void
+cache_SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+{
+ CFIndex i;
+
+ i = CFArrayGetFirstIndexOfValue(cached_removals,
+ CFRangeMake(0, CFArrayGetCount(cached_removals)),
+ key);
+ if (i != kCFNotFound) {
+ // if previously "removed"
+ CFArrayRemoveValueAtIndex(cached_removals, i);
+ }
+
+ CFDictionarySetValue(cached_set, key, value);
+
+ return;
+}
+
+__private_extern__
+void
+cache_SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
+{
+ CFDictionaryRemoveValue(cached_set, key);
+
+ if (!CFArrayContainsValue(cached_removals,
+ CFRangeMake(0, CFArrayGetCount(cached_removals)),
+ key)) {
+ CFArrayAppendValue(cached_removals, key);
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+cache_SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key)
+{
+ if (!CFArrayContainsValue(cached_notifys,
+ CFRangeMake(0, CFArrayGetCount(cached_notifys)),
+ key)) {
+ CFArrayAppendValue(cached_notifys, key);
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+cache_write(SCDynamicStoreRef store)
+{
+ if ((CFDictionaryGetCount(cached_set) > 0) ||
+ (CFArrayGetCount(cached_removals) > 0) ||
+ (CFArrayGetCount(cached_notifys) > 0)) {
+ if (!SCDynamicStoreSetMultiple(store,
+ cached_set,
+ cached_removals,
+ cached_notifys)) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
+ SCErrorString(SCError()));
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+cache_close()
+{
+ CFRelease(cached_keys);
+ CFRelease(cached_set);
+ CFRelease(cached_removals);
+ CFRelease(cached_notifys);
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 1, 2003 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#ifndef _CACHE_H
+#define _CACHE_H
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+
+__BEGIN_DECLS
+
+void cache_open ();
+
+CFPropertyListRef cache_SCDynamicStoreCopyValue (SCDynamicStoreRef store,
+ CFStringRef key);
+
+void cache_SCDynamicStoreSetValue (SCDynamicStoreRef store,
+ CFStringRef key,
+ CFPropertyListRef value);
+
+void cache_SCDynamicStoreRemoveValue (SCDynamicStoreRef store,
+ CFStringRef key);
+
+void cache_SCDynamicStoreNotifyValue (SCDynamicStoreRef store,
+ CFStringRef key);
+
+void cache_write (SCDynamicStoreRef store);
+
+void cache_close ();
+
+__END_DECLS
+
+#endif /* _CACHE_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * July 22, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include <SystemConfiguration/BondConfiguration.h>
+#include <SystemConfiguration/BondConfigurationPrivate.h>
+
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/ethernet.h>
+#define KERNEL_PRIVATE
+#include <net/if.h>
+#include <net/if_var.h>
+#undef KERNEL_PRIVATE
+#include <net/if_bond_var.h>
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <net/route.h>
+
+/* ---------- Bond support ---------- */
+
+static int
+inet_dgram_socket()
+{
+ int s;
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ }
+
+ return s;
+}
+
+static int
+siocgifmedia(int s, const char * ifname, int * status, int * active)
+{
+ struct ifmediareq ifmr;
+
+ *status = 0;
+ *active = 0;
+ bzero(&ifmr, sizeof(ifmr));
+ strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+ if (ioctl(s, SIOCGIFMEDIA, &ifmr) < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SIOCGIFMEDIA(%s) failed, %s\n"),
+ ifname, strerror(errno));
+ return (-1);
+ }
+ if (ifmr.ifm_count != 0) {
+ *status = ifmr.ifm_status;
+ *active = ifmr.ifm_active;
+ }
+ return (0);
+}
+
+static struct if_bond_status_req *
+if_bond_status_req_copy(int s, const char * ifname)
+{
+ void * buf = NULL;
+ struct if_bond_req ibr;
+ struct if_bond_status_req * ibsr_p;
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ bzero((char *)&ibr, sizeof(ibr));
+ ibr.ibr_op = IF_BOND_OP_GET_STATUS;
+ ibsr_p = &ibr.ibr_ibru.ibru_status;
+ ibsr_p->ibsr_version = IF_BOND_STATUS_REQ_VERSION;
+ ifr.ifr_data = (caddr_t)&ibr;
+
+ /* how many of them are there? */
+ if (ioctl(s, SIOCGIFBOND, (caddr_t)&ifr) < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SIOCGIFBOND(%s) failed: %s"),
+ ifname, strerror(errno));
+ goto failed;
+ }
+ buf = malloc(sizeof(struct if_bond_status) * ibsr_p->ibsr_total + sizeof(*ibsr_p));
+ if (buf == NULL) {
+ goto failed;
+ }
+ if (ibsr_p->ibsr_total == 0) {
+ goto done;
+ }
+ ibsr_p->ibsr_count = ibsr_p->ibsr_total;
+ ibsr_p->ibsr_buffer = buf + sizeof(*ibsr_p);
+
+ /* get the list */
+ if (ioctl(s, SIOCGIFBOND, (caddr_t)&ifr) < 0) {
+ SCLog(TRUE, LOG_ERR, CFSTR("SIOCGIFBOND(%s) failed: %s"),
+ ifname, strerror(errno));
+ goto failed;
+ }
+ done:
+ (*(struct if_bond_status_req *)buf) = *ibsr_p;
+ return ((struct if_bond_status_req *)buf);
+
+ failed:
+ if (buf != NULL) {
+ free(buf);
+ }
+ return (NULL);
+}
+
+static Boolean
+_Bond_addDevice(int s, CFStringRef interface, CFStringRef device)
+{
+ struct if_bond_req breq;
+ struct ifreq ifr;
+
+ // bond interface
+ bzero(&ifr, sizeof(ifr));
+ (void) _SC_cfstring_to_cstring(interface,
+ ifr.ifr_name,
+ sizeof(ifr.ifr_name),
+ kCFStringEncodingASCII);
+ ifr.ifr_data = (caddr_t)&breq;
+
+ // new bond member
+ bzero(&breq, sizeof(breq));
+ breq.ibr_op = IF_BOND_OP_ADD_INTERFACE;
+ (void) _SC_cfstring_to_cstring(device,
+ breq.ibr_ibru.ibru_if_name,
+ sizeof(breq.ibr_ibru.ibru_if_name),
+ kCFStringEncodingASCII);
+
+ // add new bond member
+ if (ioctl(s, SIOCSIFBOND, (caddr_t)&ifr) == -1) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("could not add interface \"%@\" to bond \"%@\": %s"),
+ device,
+ interface,
+ strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ // mark the added interface "up"
+ if (!__markInterfaceUp(s, device)) {
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static Boolean
+_Bond_removeDevice(int s, CFStringRef interface, CFStringRef device)
+{
+ struct if_bond_req breq;
+ struct ifreq ifr;
+
+ // bond interface
+ bzero(&ifr, sizeof(ifr));
+ (void) _SC_cfstring_to_cstring(interface,
+ ifr.ifr_name,
+ sizeof(ifr.ifr_name),
+ kCFStringEncodingASCII);
+ ifr.ifr_data = (caddr_t)&breq;
+
+ // bond member to remove
+ bzero(&breq, sizeof(breq));
+ breq.ibr_op = IF_BOND_OP_REMOVE_INTERFACE;
+ (void) _SC_cfstring_to_cstring(device,
+ breq.ibr_ibru.ibru_if_name,
+ sizeof(breq.ibr_ibru.ibru_if_name),
+ kCFStringEncodingASCII);
+
+ // remove bond member
+ if (ioctl(s, SIOCSIFBOND, (caddr_t)&ifr) == -1) {
+ SCLog(TRUE, LOG_ERR,
+ CFSTR("could not remove interface \"%@\" from bond \"%@\": %s"),
+ device,
+ interface,
+ strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/* ---------- Bond "device" ---------- */
+
+Boolean
+IsBondSupported(CFStringRef device)
+{
+ CFMutableDictionaryRef entity;
+ SCNetworkInterfaceRef interface;
+ Boolean isBond = FALSE;
+
+ entity = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(entity, kSCPropNetInterfaceType, kSCValNetInterfaceTypeEthernet);
+ CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, device);
+ interface = __SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
+ CFRelease(entity);
+
+ if (interface != NULL) {
+ SCNetworkInterfacePrivateRef interfacePrivate;
+
+ interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+ if (interfacePrivate->path != NULL) {
+ isBond = interfacePrivate->supportsBond;
+ }
+ CFRelease(interface);
+ }
+
+ return isBond;
+}
+
+/* ---------- BondInterface ---------- */
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* bond interface configuration */
+ CFStringRef ifname; // e.g. bond0, bond1, ...
+ CFArrayRef devices; // e.g. en0, en1, ...
+ CFDictionaryRef options; // e.g. UserDefinedName
+
+} BondInterfacePrivate, * BondInterfacePrivateRef;
+
+
+static CFStringRef __BondInterfaceCopyDescription (CFTypeRef cf);
+static void __BondInterfaceDeallocate (CFTypeRef cf);
+static Boolean __BondInterfaceEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static const CFRuntimeClass __BondInterfaceClass = {
+ 0, // version
+ "BondInterface", // className
+ NULL, // init
+ NULL, // copy
+ __BondInterfaceDeallocate, // dealloc
+ __BondInterfaceEqual, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __BondInterfaceCopyDescription // copyDebugDesc
+};
+
+
+static CFTypeID __kBondInterfaceTypeID = _kCFRuntimeNotATypeID;
+
+
+static pthread_once_t bondInterface_init = PTHREAD_ONCE_INIT;
+
+
+static CFStringRef
+__BondInterfaceCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)cf;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<BondInterface %p [%p]> {"), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR(" if = %@"), bondPrivate->ifname);
+ if (bondPrivate->devices != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ CFStringAppendFormat(result, NULL, CFSTR(", devices ="));
+
+ n = CFArrayGetCount(bondPrivate->devices);
+ for (i = 0; i < n; i++) {
+ CFStringAppendFormat(result,
+ NULL,
+ CFSTR(" %@"),
+ CFArrayGetValueAtIndex(bondPrivate->devices, i));
+ }
+ }
+ if (bondPrivate->options != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", options = %@"), bondPrivate->options);
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__BondInterfaceDeallocate(CFTypeRef cf)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)cf;
+
+ /* release resources */
+
+ CFRelease(bondPrivate->ifname);
+ if (bondPrivate->devices) CFRelease(bondPrivate->devices);
+ if (bondPrivate->options) CFRelease(bondPrivate->options);
+
+ return;
+}
+
+
+static Boolean
+__BondInterfaceEquiv(CFTypeRef cf1, CFTypeRef cf2)
+{
+ BondInterfacePrivateRef bond1 = (BondInterfacePrivateRef)cf1;
+ BondInterfacePrivateRef bond2 = (BondInterfacePrivateRef)cf2;
+
+ if (bond1 == bond2)
+ return TRUE;
+
+ if (!CFEqual(bond1->ifname, bond2->ifname))
+ return FALSE; // if not the same interface
+
+ if (!CFEqual(bond1->devices, bond2->devices))
+ return FALSE; // if not the same device
+
+ return TRUE;
+}
+
+
+static Boolean
+__BondInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+ BondInterfacePrivateRef bond1 = (BondInterfacePrivateRef)cf1;
+ BondInterfacePrivateRef bond2 = (BondInterfacePrivateRef)cf2;
+
+ if (!__BondInterfaceEquiv(bond1, bond2))
+ return FALSE; // if not the same Bond interface/devices
+
+ if (bond1->options != bond2->options) {
+ // if the options may differ
+ if ((bond1->options != NULL) && (bond2->options != NULL)) {
+ // if both Bonds have options
+ if (!CFEqual(bond1->options, bond2->options)) {
+ // if the options are not equal
+ return FALSE;
+ }
+ } else {
+ // if only one Bond has options
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+static void
+__BondInterfaceInitialize(void)
+{
+ __kBondInterfaceTypeID = _CFRuntimeRegisterClass(&__BondInterfaceClass);
+ return;
+}
+
+
+static __inline__ CFTypeRef
+isA_BondInterface(CFTypeRef obj)
+{
+ return (isA_CFType(obj, BondInterfaceGetTypeID()));
+}
+
+
+CFTypeID
+BondInterfaceGetTypeID(void)
+{
+ pthread_once(&bondInterface_init, __BondInterfaceInitialize); /* initialize runtime */
+ return __kBondInterfaceTypeID;
+}
+
+
+static BondInterfaceRef
+__BondInterfaceCreatePrivate(CFAllocatorRef allocator,
+ CFStringRef ifname)
+{
+ BondInterfacePrivateRef bondPrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&bondInterface_init, __BondInterfaceInitialize);
+
+ /* allocate bond */
+ size = sizeof(BondInterfacePrivate) - sizeof(CFRuntimeBase);
+ bondPrivate = (BondInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kBondInterfaceTypeID,
+ size,
+ NULL);
+ if (bondPrivate == NULL) {
+ return NULL;
+ }
+
+ /* establish the bond */
+
+ bondPrivate->ifname = CFStringCreateCopy(allocator, ifname);
+ bondPrivate->devices = NULL;
+ bondPrivate->options = NULL;
+
+ return (BondInterfaceRef)bondPrivate;
+}
+
+
+CFStringRef
+BondInterfaceGetInterface(BondInterfaceRef bond)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)bond;
+ CFStringRef bond_if = NULL;
+
+ if (isA_BondInterface(bond)) {
+ bond_if = bondPrivate->ifname;
+ }
+
+ return bond_if;
+}
+
+
+CFArrayRef
+BondInterfaceGetDevices(BondInterfaceRef bond)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)bond;
+ CFArrayRef bond_devices = NULL;
+
+ if (isA_BondInterface(bond)) {
+ bond_devices = bondPrivate->devices;
+ }
+
+ return bond_devices;
+}
+
+
+CFDictionaryRef
+BondInterfaceGetOptions(BondInterfaceRef bond)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)bond;
+ CFDictionaryRef bond_options = NULL;
+
+ if (isA_BondInterface(bond)) {
+ bond_options = bondPrivate->options;
+ }
+
+ return bond_options;
+}
+
+
+static void
+BondInterfaceSetDevices(BondInterfaceRef bond, CFArrayRef newDevices)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)bond;
+
+ if (isA_BondInterface(bond)) {
+ CFAllocatorRef allocator = CFGetAllocator(bond);
+
+ if (bondPrivate->devices != NULL) CFRelease(bondPrivate->devices);
+ if ((newDevices != NULL) && (CFArrayGetCount(newDevices) > 0)) {
+ bondPrivate->devices = CFArrayCreateCopy(allocator, newDevices);
+ } else {
+ bondPrivate->devices = NULL;
+ }
+ }
+
+ return;
+}
+
+
+static void
+BondInterfaceSetOptions(BondInterfaceRef bond, CFDictionaryRef newOptions)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)bond;
+
+ if (isA_BondInterface(bond)) {
+ CFAllocatorRef allocator = CFGetAllocator(bond);
+
+ if (bondPrivate->options) CFRelease(bondPrivate->options);
+ if (newOptions != NULL) {
+ bondPrivate->options = CFDictionaryCreateCopy(allocator, newOptions);
+ } else {
+ bondPrivate->options = NULL;
+ }
+ }
+
+ return;
+}
+
+
+/* ---------- BondPreferences ---------- */
+
+#define BOND_PREFERENCES_BONDS CFSTR("Bonds")
+
+#define __kBondInterface_interface CFSTR("interface") // e.g. bond0, bond1, ...
+#define __kBondInterface_devices CFSTR("devices") // e.g. en0, en1, ...
+#define __kBondInterface_options CFSTR("options") // e.g. UserDefinedName
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* lock */
+ pthread_mutex_t lock;
+
+ /* underlying preferences */
+ SCPreferencesRef prefs;
+
+ /* base Bonds (before any commits) */
+ CFArrayRef bBase;
+
+} BondPreferencesPrivate, * BondPreferencesPrivateRef;
+
+
+static CFStringRef __BondPreferencesCopyDescription (CFTypeRef cf);
+static void __BondPreferencesDeallocate (CFTypeRef cf);
+
+
+static const CFRuntimeClass __BondPreferencesClass = {
+ 0, // version
+ "BondPreferences", // className
+ NULL, // init
+ NULL, // copy
+ __BondPreferencesDeallocate, // dealloc
+ NULL, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __BondPreferencesCopyDescription // copyDebugDesc
+};
+
+
+static CFTypeID __kBondPreferencesTypeID = _kCFRuntimeNotATypeID;
+
+
+static pthread_once_t bondPreferences_init = PTHREAD_ONCE_INIT;
+
+
+static CFStringRef
+__BondPreferencesCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFIndex i;
+ CFArrayRef keys;
+ CFIndex n;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)cf;
+ CFMutableStringRef result;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<BondPreferences %p [%p]> {"), cf, allocator);
+
+ keys = SCPreferencesCopyKeyList(prefsPrivate->prefs);
+ n = CFArrayGetCount(keys);
+ for (i = 0; i < n; i++) {
+ CFStringRef key;
+ CFPropertyListRef val;
+
+ key = CFArrayGetValueAtIndex(keys, i);
+ val = SCPreferencesGetValue(prefsPrivate->prefs, key);
+
+ CFStringAppendFormat(result, NULL, CFSTR("%@ : %@"), key, val);
+ }
+ CFRelease(keys);
+
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__BondPreferencesDeallocate(CFTypeRef cf)
+{
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)cf;
+
+ /* release resources */
+
+ pthread_mutex_destroy(&prefsPrivate->lock);
+
+ if (prefsPrivate->prefs) CFRelease(prefsPrivate->prefs);
+ if (prefsPrivate->bBase) CFRelease(prefsPrivate->bBase);
+
+ return;
+}
+
+
+static void
+__BondPreferencesInitialize(void)
+{
+ __kBondPreferencesTypeID = _CFRuntimeRegisterClass(&__BondPreferencesClass);
+ return;
+}
+
+
+static __inline__ CFTypeRef
+isA_BondPreferences(CFTypeRef obj)
+{
+ return (isA_CFType(obj, BondPreferencesGetTypeID()));
+}
+
+
+CFArrayRef
+_BondPreferencesCopyActiveInterfaces()
+{
+ CFArrayCallBacks callbacks;
+ struct ifaddrs *ifap;
+ struct ifaddrs *ifp;
+ int s;
+ CFMutableArrayRef bonds = NULL;
+
+ if (getifaddrs(&ifap) == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ return NULL;
+ }
+
+ s = inet_dgram_socket();
+ if (s == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+
+ callbacks = kCFTypeArrayCallBacks;
+ callbacks.equal = __BondInterfaceEquiv;
+ bonds = CFArrayCreateMutable(NULL, 0, &callbacks);
+
+ for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) {
+ BondInterfaceRef bond;
+ CFStringRef bond_if;
+ CFMutableArrayRef devices = NULL;
+ struct if_bond_status_req *ibsr_p;
+ struct if_data *if_data;
+
+ if_data = (struct if_data *)ifp->ifa_data;
+ if (if_data == NULL
+ || ifp->ifa_addr->sa_family != AF_LINK
+ || if_data->ifi_type != IFT_IEEE8023ADLAG) {
+ continue;
+ }
+ ibsr_p = if_bond_status_req_copy(s, ifp->ifa_name);
+ if (ibsr_p == NULL) {
+ SCLog(TRUE, LOG_ERR, CFSTR("if_bond_status_req_copy(%s) failed: %s"),
+ ifp->ifa_name, strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ CFRelease(bonds);
+ goto done;
+ }
+ if (ibsr_p->ibsr_total > 0) {
+ int i;
+ struct if_bond_status * ibs_p;
+ devices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ // iterate over each member device
+ ibs_p = (struct if_bond_status *)ibsr_p->ibsr_buffer;
+ for (i = 0; i < ibsr_p->ibsr_total; i++) {
+ CFStringRef device;
+ char if_name[IFNAMSIZ+1];
+
+ strlcpy(if_name, ibs_p[i].ibs_if_name, sizeof(if_name));
+ device = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
+ CFArrayAppendValue(devices, device);
+ CFRelease(device);
+ }
+ }
+ free(ibsr_p);
+ bond_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII);
+ bond = __BondInterfaceCreatePrivate(NULL, bond_if);
+ CFRelease(bond_if);
+
+ if (devices != NULL) {
+ BondInterfaceSetDevices(bond, devices);
+ CFRelease(devices);
+ }
+ CFArrayAppendValue(bonds, bond);
+ CFRelease(bond);
+ }
+
+ done :
+
+ (void) close(s);
+ freeifaddrs(ifap);
+ return bonds;
+}
+
+
+static CFIndex
+findBond(CFArrayRef bonds, CFStringRef interface)
+{
+ CFIndex found = kCFNotFound;
+ CFIndex i;
+ CFIndex n;
+
+ n = isA_CFArray(bonds) ? CFArrayGetCount(bonds) : 0;
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef bond_dict;
+ CFStringRef bond_if;
+
+ bond_dict = CFArrayGetValueAtIndex(bonds, i);
+ if (!isA_CFDictionary(bond_dict)) {
+ break; // if the prefs are confused
+ }
+
+ bond_if = CFDictionaryGetValue(bond_dict, __kBondInterface_interface);
+ if (!isA_CFString(bond_if)) {
+ break; // if the prefs are confused
+ }
+
+ if (!CFEqual(bond_if, interface)) {
+ continue; // if not a match
+ }
+
+ // if we have found a match
+ found = i;
+ break;
+ }
+
+ return found;
+}
+
+
+static void
+setConfigurationChanged(BondPreferencesRef prefs)
+{
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ /*
+ * to facilitate device configuration we will take
+ * a snapshot of the Bond preferences before any
+ * changes are made. Then, when the changes are
+ * applied we can compare what we had to what we
+ * want and configured the system accordingly.
+ */
+ if (prefsPrivate->bBase == NULL) {
+ prefsPrivate->bBase = BondPreferencesCopyInterfaces(prefs);
+ }
+
+ return;
+}
+
+
+CFTypeID
+BondPreferencesGetTypeID(void)
+{
+ pthread_once(&bondPreferences_init, __BondPreferencesInitialize); /* initialize runtime */
+ return __kBondPreferencesTypeID;
+}
+
+
+BondPreferencesRef
+BondPreferencesCreate(CFAllocatorRef allocator)
+{
+ CFBundleRef bundle;
+ CFStringRef bundleID = NULL;
+ CFStringRef name = CFSTR("BondConfiguration");
+ BondPreferencesPrivateRef prefsPrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&bondPreferences_init, __BondPreferencesInitialize);
+
+ /* allocate preferences */
+ size = sizeof(BondPreferencesPrivate) - sizeof(CFRuntimeBase);
+ prefsPrivate = (BondPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kBondPreferencesTypeID,
+ size,
+ NULL);
+ if (prefsPrivate == NULL) {
+ return NULL;
+ }
+
+ /* establish the prefs */
+
+ pthread_mutex_init(&prefsPrivate->lock, NULL);
+
+ bundle = CFBundleGetMainBundle();
+ if (bundle) {
+ bundleID = CFBundleGetIdentifier(bundle);
+ if (bundleID) {
+ CFRetain(bundleID);
+ } else {
+ CFURLRef url;
+
+ url = CFBundleCopyExecutableURL(bundle);
+ if (url) {
+ bundleID = CFURLCopyPath(url);
+ CFRelease(url);
+ }
+ }
+ }
+
+ if (bundleID) {
+ CFStringRef fullName;
+
+ if (CFEqual(bundleID, CFSTR("/"))) {
+ CFRelease(bundleID);
+ bundleID = CFStringCreateWithFormat(allocator, NULL, CFSTR("(%d)"), getpid());
+ }
+
+ fullName = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@:%@"), bundleID, name);
+ name = fullName;
+ CFRelease(bundleID);
+ } else {
+ CFRetain(name);
+ }
+
+ prefsPrivate->prefs = SCPreferencesCreate(allocator, name, BOND_PREFERENCES_ID);
+ CFRelease(name);
+
+ prefsPrivate->bBase = NULL;
+
+ return (BondPreferencesRef)prefsPrivate;
+}
+
+
+CFArrayRef
+BondPreferencesCopyInterfaces(BondPreferencesRef prefs)
+{
+ CFAllocatorRef allocator;
+ CFArrayCallBacks callbacks;
+ CFIndex i;
+ CFIndex n;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+ CFMutableArrayRef result;
+ CFArrayRef bonds;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+ allocator = CFGetAllocator(prefs);
+ callbacks = kCFTypeArrayCallBacks;
+ callbacks.equal = __BondInterfaceEquiv;
+ result = CFArrayCreateMutable(allocator, 0, &callbacks);
+
+ bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+ if ((bonds != NULL) && !isA_CFArray(bonds)) {
+ goto error; // if the prefs are confused
+ }
+
+ n = (bonds != NULL) ? CFArrayGetCount(bonds) : 0;
+ for (i = 0; i < n; i++) {
+ BondInterfaceRef bond;
+ CFDictionaryRef bond_dict;
+ CFStringRef bond_if;
+ CFArrayRef devices;
+ CFDictionaryRef options;
+
+ bond_dict = CFArrayGetValueAtIndex(bonds, i);
+ if (!isA_CFDictionary(bond_dict)) {
+ goto error; // if the prefs are confused
+ }
+
+ bond_if = CFDictionaryGetValue(bond_dict, __kBondInterface_interface);
+ if (!isA_CFString(bond_if)) {
+ goto error; // if the prefs are confused
+ }
+
+
+ devices = CFDictionaryGetValue(bond_dict, __kBondInterface_devices);
+ if ((devices != NULL) && !isA_CFArray(devices)) {
+ goto error; // if the prefs are confused
+ }
+
+ options = CFDictionaryGetValue(bond_dict, __kBondInterface_options);
+ if ((options != NULL) && !isA_CFDictionary(options)) {
+ goto error; // if the prefs are confused
+ }
+
+ bond = __BondInterfaceCreatePrivate(allocator, bond_if);
+ BondInterfaceSetDevices(bond, devices);
+ BondInterfaceSetOptions(bond, options);
+ CFArrayAppendValue(result, bond);
+ CFRelease(bond);
+ }
+
+ return result;
+
+ error :
+
+ _SCErrorSet(kSCStatusFailed);
+ CFRelease(result);
+ return NULL;
+}
+
+
+BondInterfaceRef
+BondPreferencesCreateInterface(BondPreferencesRef prefs)
+{
+ CFArrayRef active_bonds = NULL;
+ CFAllocatorRef allocator;
+ CFArrayRef config_bonds;
+ CFIndex i;
+ CFIndex nActive;
+ CFIndex nConfig;
+ BondInterfaceRef newBond = NULL;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ /* get "configured" Bonds (and check to ensure the device is available) */
+ config_bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+ if ((config_bonds != NULL) && !isA_CFArray(config_bonds)) {
+ // if the prefs are confused
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+
+ nConfig = (config_bonds != NULL) ? CFArrayGetCount(config_bonds) : 0;
+
+ /* get "active" Bonds */
+ active_bonds = _BondPreferencesCopyActiveInterfaces();
+ nActive = isA_CFArray(active_bonds) ? CFArrayGetCount(active_bonds) : 0;
+
+ /* create a new bond using an unused interface name */
+ allocator = CFGetAllocator(prefs);
+
+ for (i = 0; newBond == NULL; i++) {
+ CFIndex j;
+ CFMutableDictionaryRef newDict;
+ CFMutableArrayRef newBonds;
+ CFStringRef bond_if;
+
+ bond_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bond%d"), i);
+
+ for (j = 0; j < nActive; j++) {
+ CFStringRef active_if;
+ BondInterfaceRef active_bond;
+
+ active_bond = CFArrayGetValueAtIndex(active_bonds, j);
+ active_if = BondInterfaceGetInterface(active_bond);
+
+ if (CFEqual(bond_if, active_if)) {
+ goto next_if; // if bond interface name not available
+ }
+ }
+
+ for (j = 0; j < nConfig; j++) {
+ CFDictionaryRef config;
+ CFStringRef config_if;
+
+ config = CFArrayGetValueAtIndex(config_bonds, j);
+ if (!isA_CFDictionary(config)) {
+ // if the prefs are confused
+ _SCErrorSet(kSCStatusFailed);
+ CFRelease(bond_if);
+ goto done;
+ }
+
+ config_if = CFDictionaryGetValue(config, __kBondInterface_interface);
+ if (!isA_CFString(config_if)) {
+ // if the prefs are confused
+ _SCErrorSet(kSCStatusFailed);
+ CFRelease(bond_if);
+ goto done;
+ }
+
+ if (CFEqual(bond_if, config_if)) {
+ goto next_if; // if bond interface name not available
+ }
+ }
+
+ /* create the bond */
+
+ newDict = CFDictionaryCreateMutable(allocator,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(newDict, __kBondInterface_interface, bond_if);
+
+ /* create the accessor handle to be returned */
+
+ newBond = __BondInterfaceCreatePrivate(allocator, bond_if);
+
+ /* save in the prefs */
+
+ if (nConfig > 0) {
+ newBonds = CFArrayCreateMutableCopy(allocator, 0, config_bonds);
+ } else {
+ newBonds = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(newBonds, newDict);
+ CFRelease(newDict);
+
+ /* yes, we're going to be changing the configuration */
+ setConfigurationChanged(prefs);
+
+ (void) SCPreferencesSetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS, newBonds);
+ CFRelease(newBonds);
+
+ next_if :
+ CFRelease(bond_if);
+ }
+
+ done :
+
+ if (active_bonds != NULL) CFRelease(active_bonds);
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return (BondInterfaceRef) newBond;
+}
+
+
+static Boolean
+_BondPreferencesUpdate(BondPreferencesRef prefs, BondInterfaceRef bond)
+{
+ CFAllocatorRef allocator;
+ CFIndex bond_index;
+ CFArrayRef devices;
+ CFStringRef interface;
+ CFMutableDictionaryRef newDict;
+ CFMutableArrayRef newBonds;
+ CFDictionaryRef options;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+ CFArrayRef bonds;
+
+ bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+ if ((bonds != NULL) && !isA_CFArray(bonds)) {
+ // if the prefs are confused
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ interface = BondInterfaceGetInterface(bond);
+ bond_index = findBond(bonds, interface);
+ if (bond_index == kCFNotFound) {
+ _SCErrorSet(kSCStatusNoKey);
+ return FALSE;
+ }
+
+ /* create the bond dictionary */
+
+ allocator = CFGetAllocator(prefs);
+ newDict = CFDictionaryCreateMutable(allocator,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionaryAddValue(newDict, __kBondInterface_interface, interface);
+
+ devices = BondInterfaceGetDevices(bond);
+ if (devices != NULL) {
+ CFDictionaryAddValue(newDict, __kBondInterface_devices, devices);
+ }
+
+ options = BondInterfaceGetOptions(bond);
+ if (options != NULL) {
+ CFDictionaryAddValue(newDict, __kBondInterface_options, options);
+ }
+
+ /* yes, we're going to be changing the configuration */
+ setConfigurationChanged(prefs);
+
+ /* update the prefs */
+
+ newBonds = CFArrayCreateMutableCopy(allocator, 0, bonds);
+ CFArraySetValueAtIndex(newBonds, bond_index, newDict);
+ CFRelease(newDict);
+ (void) SCPreferencesSetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS, newBonds);
+ CFRelease(newBonds);
+
+ return TRUE;
+}
+
+
+Boolean
+BondPreferencesAddDevice(BondPreferencesRef prefs,
+ BondInterfaceRef bond,
+ CFStringRef device)
+{
+ CFArrayRef config_bonds;
+ CFIndex i;
+ CFIndex nConfig;
+ Boolean ok = TRUE;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!isA_BondInterface(bond)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!isA_CFString(device)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!IsBondSupported(device)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ /* get "configured" bonds */
+ config_bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+ if ((config_bonds != NULL) && !isA_CFArray(config_bonds)) {
+ _SCErrorSet(kSCStatusFailed);
+ ok = FALSE;
+ goto done;
+ }
+
+ nConfig = (config_bonds != NULL) ? CFArrayGetCount(config_bonds) : 0;
+
+ /* check to ensure the requested device is available */
+ for (i = 0; ok && (i < nConfig); i++) {
+ CFDictionaryRef config_bond;
+ CFArrayRef devices;
+
+ config_bond = CFArrayGetValueAtIndex(config_bonds, i);
+ if (!isA_CFDictionary(config_bond)) {
+ ok = FALSE; // if the prefs are confused
+ break;
+ }
+
+ devices = CFDictionaryGetValue(config_bond, __kBondInterface_devices);
+ if ((devices != NULL) && !isA_CFArray(devices)) {
+ ok = FALSE; // if the prefs are confused
+ break;
+ }
+
+ if (devices == NULL) {
+ continue; // if no devices
+ }
+
+ ok = !CFArrayContainsValue(devices,
+ CFRangeMake(0, CFArrayGetCount(devices)),
+ device);
+ }
+
+ if (ok) {
+ CFArrayRef devices;
+ CFMutableArrayRef newDevices;
+
+ devices = BondInterfaceGetDevices(bond);
+ if (devices != NULL) {
+ devices = CFArrayCreateCopy(NULL, devices);
+ newDevices = CFArrayCreateMutableCopy(NULL, 0, devices);
+ } else {
+ newDevices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(newDevices, device);
+ BondInterfaceSetDevices(bond, newDevices);
+ CFRelease(newDevices);
+
+ ok = _BondPreferencesUpdate(prefs, bond);
+ if (!ok) {
+ BondInterfaceSetDevices(bond, devices);
+ }
+
+ if (devices != NULL) {
+ CFRelease(devices);
+ }
+ } else {
+ _SCErrorSet(kSCStatusKeyExists);
+ }
+
+ done :
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return ok;
+}
+
+
+Boolean
+BondPreferencesRemoveDevice(BondPreferencesRef prefs,
+ BondInterfaceRef bond,
+ CFStringRef device)
+{
+ CFIndex bond_index;
+ CFArrayRef devices;
+ Boolean ok = FALSE;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!isA_BondInterface(bond)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!isA_CFString(device)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ devices = BondInterfaceGetDevices(bond);
+ if (devices != NULL) {
+ bond_index = CFArrayGetFirstIndexOfValue(devices,
+ CFRangeMake(0, CFArrayGetCount(devices)),
+ device);
+ if (bond_index != kCFNotFound) {
+ CFMutableArrayRef newDevices;
+
+ devices = CFArrayCreateCopy(NULL, devices);
+ newDevices = CFArrayCreateMutableCopy(NULL, 0, devices);
+ CFArrayRemoveValueAtIndex(newDevices, bond_index);
+ BondInterfaceSetDevices(bond, newDevices);
+ CFRelease(newDevices);
+
+ ok = _BondPreferencesUpdate(prefs, bond);
+ if (!ok) {
+ BondInterfaceSetDevices(bond, devices);
+ }
+
+ CFRelease(devices);
+ } else {
+ _SCErrorSet(kSCStatusNoKey);
+ }
+ }
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return ok;
+}
+
+
+Boolean
+BondPreferencesSetOptions(BondPreferencesRef prefs, BondInterfaceRef bond, CFDictionaryRef newOptions)
+{
+ Boolean ok = FALSE;
+ CFDictionaryRef options;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!isA_BondInterface(bond)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ options = BondInterfaceGetOptions(bond);
+ if (options != NULL) {
+ options = CFDictionaryCreateCopy(NULL, options);
+ }
+
+ BondInterfaceSetOptions(bond, newOptions);
+ ok = _BondPreferencesUpdate(prefs, bond);
+ if (!ok) {
+ BondInterfaceSetOptions(bond, options);
+ }
+
+ if (options != NULL) {
+ CFRelease(options);
+ }
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return ok;
+}
+
+
+Boolean
+BondPreferencesRemoveInterface(BondPreferencesRef prefs,
+ BondInterfaceRef bond)
+{
+ CFIndex bond_index;
+ Boolean ok = FALSE;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+ CFArrayRef bonds;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ if (!isA_BondInterface(bond)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+ if (!isA_CFArray(bonds)) {
+ // if the prefs are confused
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+
+ bond_index = findBond(bonds, BondInterfaceGetInterface(bond));
+ if (bond_index == kCFNotFound) {
+ _SCErrorSet(kSCStatusNoKey);
+ goto done;
+ }
+
+ /* yes, we're going to be changing the configuration */
+ setConfigurationChanged(prefs);
+
+ /* remove the bond */
+
+ if (CFArrayGetCount(bonds) > 1) {
+ CFAllocatorRef allocator;
+ CFMutableArrayRef newBonds;
+
+ allocator = CFGetAllocator(prefs);
+ newBonds = CFArrayCreateMutableCopy(allocator, 0, bonds);
+ CFArrayRemoveValueAtIndex(newBonds, bond_index);
+ (void) SCPreferencesSetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS, newBonds);
+ CFRelease(newBonds);
+ } else {
+ (void) SCPreferencesRemoveValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+ }
+
+ ok = TRUE;
+
+ done :
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return ok;
+}
+
+
+Boolean
+BondPreferencesCommitChanges(BondPreferencesRef prefs)
+{
+ Boolean ok = FALSE;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ ok = SCPreferencesCommitChanges(prefsPrivate->prefs);
+ if (!ok) {
+ return ok;
+ }
+
+ if (prefsPrivate->bBase != NULL) {
+ CFRelease(prefsPrivate->bBase);
+ prefsPrivate->bBase = NULL;
+ }
+
+ return TRUE;
+}
+
+
+Boolean
+_BondPreferencesUpdateConfiguration(BondPreferencesRef prefs)
+{
+ CFArrayRef active = NULL;
+ CFArrayRef config = NULL;
+ CFIndex i;
+ CFIndex nActive;
+ CFIndex nConfig;
+ Boolean ok = FALSE;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+ int s = -1;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ /* configured Bonds */
+ if (prefsPrivate->bBase != NULL) {
+ /*
+ * updated Bond preferences have not been committed
+ * so we ignore any in-progress changes and apply the
+ * saved preferences.
+ */
+ config = CFRetain(prefsPrivate->bBase);
+ } else {
+ /*
+ * apply the saved preferences
+ */
+ config = BondPreferencesCopyInterfaces(prefs);
+ }
+ nConfig = CFArrayGetCount(config);
+
+ /* active Bonds */
+ active = _BondPreferencesCopyActiveInterfaces();
+ nActive = CFArrayGetCount(active);
+
+ /*
+ * remove any no-longer-configured bond interfaces and
+ * any devices associated with a bond that are no longer
+ * associated with a bond.
+ */
+ for (i = 0; i < nActive; i++) {
+ BondInterfaceRef a_bond;
+ CFStringRef a_bond_if;
+ CFIndex j;
+ Boolean found = FALSE;
+
+ a_bond = CFArrayGetValueAtIndex(active, i);
+ a_bond_if = BondInterfaceGetInterface(a_bond);
+
+ for (j = 0; j < nConfig; j++) {
+ BondInterfaceRef c_bond;
+ CFStringRef c_bond_if;
+
+ c_bond = CFArrayGetValueAtIndex(config, j);
+ c_bond_if = BondInterfaceGetInterface(c_bond);
+
+ if (CFEqual(a_bond_if, c_bond_if)) {
+ CFIndex a;
+ CFIndex a_count;
+ CFArrayRef a_bond_devices;
+ CFIndex c_count;
+ CFArrayRef c_bond_devices;
+
+ c_bond_devices = BondInterfaceGetDevices(c_bond);
+ c_count = (c_bond_devices != NULL) ? CFArrayGetCount(c_bond_devices) : 0;
+
+ a_bond_devices = BondInterfaceGetDevices(a_bond);
+ a_count = (a_bond_devices != NULL) ? CFArrayGetCount(a_bond_devices) : 0;
+
+ for (a = 0; a < a_count; a++) {
+ CFStringRef a_device;
+
+ a_device = CFArrayGetValueAtIndex(a_bond_devices, a);
+ if ((c_count == 0) ||
+ !CFArrayContainsValue(c_bond_devices,
+ CFRangeMake(0, c_count),
+ a_device)) {
+ /*
+ * if this device is no longer part
+ * of the bond.
+ */
+ if (s == -1) {
+ s = inet_dgram_socket();
+ }
+
+ ok = _Bond_removeDevice(s, a_bond_if, a_device);
+ if (!ok) {
+ goto done;
+ }
+ }
+ }
+
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ /*
+ * if this interface is no longer configured
+ */
+ if (s == -1) {
+ s = inet_dgram_socket();
+ }
+
+ ok = __destroyInterface(s, a_bond_if);
+ if (!ok) {
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * add any newly-configured bond interfaces and add any
+ * devices that should now be associated with the bond.
+ */
+ for (i = 0; i < nConfig; i++) {
+ BondInterfaceRef c_bond;
+ CFArrayRef c_bond_devices;
+ CFStringRef c_bond_if;
+ CFIndex c_count;
+ Boolean found = FALSE;
+ CFIndex j;
+
+ c_bond = CFArrayGetValueAtIndex(config, i);
+ c_bond_if = BondInterfaceGetInterface(c_bond);
+ c_bond_devices = BondInterfaceGetDevices(c_bond);
+ c_count = (c_bond_devices != NULL) ? CFArrayGetCount(c_bond_devices) : 0;
+
+ for (j = 0; j < nActive; j++) {
+ BondInterfaceRef a_bond;
+ CFArrayRef a_bond_devices;
+ CFStringRef a_bond_if;
+ CFIndex a_count;
+
+ a_bond = CFArrayGetValueAtIndex(active, j);
+ a_bond_if = BondInterfaceGetInterface(a_bond);
+ a_bond_devices = BondInterfaceGetDevices(a_bond);
+ a_count = (a_bond_devices != NULL) ? CFArrayGetCount(a_bond_devices) : 0;
+
+ if (CFEqual(c_bond_if, a_bond_if)) {
+ CFIndex c;
+
+ found = TRUE;
+
+ if ((c_bond_devices == NULL) &&
+ (a_bond_devices == NULL)) {
+ break; // if no change
+ }
+
+ if ((c_bond_devices != NULL) &&
+ (a_bond_devices != NULL) &&
+ CFEqual(c_bond_devices, a_bond_devices)) {
+ break; // if no change
+ }
+
+ if (s == -1) {
+ s = inet_dgram_socket();
+ }
+
+ /*
+ * ensure that the first device of the bond matches, if
+ * not then we remove all current devices and add them
+ * back in the preferred order.
+ */
+ if ((c_count > 0) &&
+ (a_count > 0) &&
+ !CFEqual(CFArrayGetValueAtIndex(c_bond_devices, 0),
+ CFArrayGetValueAtIndex(a_bond_devices, 0))) {
+ CFIndex a;
+
+ for (a = 0; a < a_count; a++) {
+ CFStringRef a_device;
+
+ a_device = CFArrayGetValueAtIndex(a_bond_devices, a);
+
+ if (!CFArrayContainsValue(c_bond_devices,
+ CFRangeMake(0, c_count),
+ a_device)) {
+ continue; // if already removed
+ }
+
+ ok = _Bond_removeDevice(s, a_bond_if, a_device);
+ if (!ok) {
+ goto done;
+ }
+ }
+
+ a_count = 0; // all active devices have been removed
+ }
+
+ /*
+ * add any devices which are not currently associated
+ * with the bond interface.
+ */
+ for (c = 0; c < c_count; c++) {
+ CFStringRef c_device;
+
+ c_device = CFArrayGetValueAtIndex(c_bond_devices, c);
+ if ((a_count == 0) ||
+ !CFArrayContainsValue(a_bond_devices,
+ CFRangeMake(0, a_count),
+ c_device)) {
+ /*
+ * check if this device can be added to
+ * a bond.
+ */
+ if (!IsBondSupported(c_device)) {
+ // if not supported
+ continue;
+ }
+
+ /*
+ * if this device is not currently part
+ * of the bond.
+ */
+
+ ok = _Bond_addDevice(s, c_bond_if, c_device);
+ if (!ok) {
+ goto done;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (!found) {
+ CFIndex c;
+
+ if (s == -1) {
+ s = inet_dgram_socket();
+ }
+
+ /*
+ * establish the new bond interface.
+ */
+ ok = __createInterface(s, c_bond_if);
+ if (!ok) {
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+
+ /*
+ * add any devices which are not currently associated
+ * with the bond interface.
+ */
+ for (c = 0; c < c_count; c++) {
+ CFStringRef c_device;
+
+ c_device = CFArrayGetValueAtIndex(c_bond_devices, c);
+
+ if (!IsBondSupported(c_device)) {
+ // if not supported
+ continue;
+ }
+
+ ok = _Bond_addDevice(s, c_bond_if, c_device);
+ if (!ok) {
+ goto done;
+ }
+ }
+ }
+
+ }
+
+ ok = TRUE;
+
+ done :
+
+ if (active != NULL) CFRelease(active);
+ if (config != NULL) CFRelease(config);
+ if (s != -1) (void) close(s);
+
+ return ok;
+}
+
+
+Boolean
+BondPreferencesApplyChanges(BondPreferencesRef prefs)
+{
+ Boolean ok = FALSE;
+ BondPreferencesPrivateRef prefsPrivate = (BondPreferencesPrivateRef)prefs;
+
+ if (!isA_BondPreferences(prefs)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ /* apply the preferences */
+ ok = SCPreferencesApplyChanges(prefsPrivate->prefs);
+ if (!ok) {
+ goto done;
+ }
+
+ /* apply the Bond configuration */
+ ok = _BondPreferencesUpdateConfiguration(prefs);
+ if (!ok) {
+ goto done;
+ }
+
+ done :
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return ok;
+}
+
+
+/* ---------- BondStatus ---------- */
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* bond interface */
+ BondInterfaceRef bond;
+
+ /* bond status */
+ CFDictionaryRef status_interface; // interface status
+ CFArrayRef devices; // per-device status
+ CFDictionaryRef status_devices;
+
+} BondStatusPrivate, * BondStatusPrivateRef;
+
+
+const CFStringRef kSCBondStatusDeviceAggregationStatus = CFSTR("AggregationStatus");
+const CFStringRef kSCBondStatusDeviceCollecting = CFSTR("Collecting");
+const CFStringRef kSCBondStatusDeviceDistributing = CFSTR("Distributing");
+
+
+static CFStringRef __BondStatusCopyDescription (CFTypeRef cf);
+static void __BondStatusDeallocate (CFTypeRef cf);
+static Boolean __BondStatusEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static const CFRuntimeClass __BondStatusClass = {
+ 0, // version
+ "BondStatus", // className
+ NULL, // init
+ NULL, // copy
+ __BondStatusDeallocate, // dealloc
+ __BondStatusEqual, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __BondStatusCopyDescription // copyDebugDesc
+};
+
+
+static CFTypeID __kBondStatusTypeID = _kCFRuntimeNotATypeID;
+
+
+static pthread_once_t bondStatus_init = PTHREAD_ONCE_INIT;
+
+
+static CFStringRef
+__BondStatusCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ BondStatusPrivateRef statusPrivate = (BondStatusPrivateRef)cf;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<BondStatus %p [%p]> {"), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR(" bond = %@"), statusPrivate->bond);
+ CFStringAppendFormat(result, NULL, CFSTR(" interface = %@"), statusPrivate->status_interface);
+ CFStringAppendFormat(result, NULL, CFSTR(" devices = %@"), statusPrivate->status_devices);
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__BondStatusDeallocate(CFTypeRef cf)
+{
+ BondStatusPrivateRef statusPrivate = (BondStatusPrivateRef)cf;
+
+ /* release resources */
+
+ CFRelease(statusPrivate->bond);
+ CFRelease(statusPrivate->status_interface);
+ if (statusPrivate->devices != NULL) CFRelease(statusPrivate->devices);
+ CFRelease(statusPrivate->status_devices);
+ return;
+}
+
+
+static Boolean
+__BondStatusEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+ BondStatusPrivateRef status1 = (BondStatusPrivateRef)cf1;
+ BondStatusPrivateRef status2 = (BondStatusPrivateRef)cf2;
+
+ if (status1 == status2)
+ return TRUE;
+
+ if (!CFEqual(status1->bond, status2->bond))
+ return FALSE; // if not the same bond
+
+ if (!CFEqual(status1->status_interface, status2->status_interface))
+ return FALSE; // if not the same interface status
+
+ if (!CFEqual(status1->status_devices, status2->status_devices))
+ return FALSE; // if not the same device status
+
+ return TRUE;
+}
+
+
+static void
+__BondStatusInitialize(void)
+{
+ __kBondStatusTypeID = _CFRuntimeRegisterClass(&__BondStatusClass);
+ return;
+}
+
+
+static __inline__ CFTypeRef
+isA_BondStatus(CFTypeRef obj)
+{
+ return (isA_CFType(obj, BondStatusGetTypeID()));
+}
+
+
+CFTypeID
+BondStatusGetTypeID(void)
+{
+ pthread_once(&bondStatus_init, __BondStatusInitialize); /* initialize runtime */
+ return __kBondStatusTypeID;
+}
+
+
+static BondStatusRef
+__BondStatusCreatePrivate(CFAllocatorRef allocator,
+ BondInterfaceRef bond,
+ CFDictionaryRef status_interface,
+ CFDictionaryRef status_devices)
+{
+ BondStatusPrivateRef statusPrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&bondStatus_init, __BondStatusInitialize);
+
+ /* allocate bond */
+ size = sizeof(BondStatusPrivate) - sizeof(CFRuntimeBase);
+ statusPrivate = (BondStatusPrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kBondStatusTypeID,
+ size,
+ NULL);
+ if (statusPrivate == NULL) {
+ return NULL;
+ }
+
+ /* establish the bond status */
+
+ statusPrivate->bond = CFRetain(bond);
+ statusPrivate->status_interface = CFDictionaryCreateCopy(allocator, status_interface);
+ statusPrivate->devices = NULL;
+ statusPrivate->status_devices = CFDictionaryCreateCopy(allocator, status_devices);
+
+ return (BondStatusRef)statusPrivate;
+}
+
+
+BondStatusRef
+BondInterfaceCopyStatus(BondInterfaceRef bond)
+{
+ BondInterfacePrivateRef bondPrivate = (BondInterfacePrivateRef)bond;
+ int bond_if_active;
+ int bond_if_status;
+ char bond_ifname[IFNAMSIZ + 1];
+ CFIndex i;
+ struct if_bond_status_req *ibsr_p = NULL;
+ CFIndex n;
+ CFNumberRef num;
+ int s;
+ struct if_bond_status * scan_p;
+ BondStatusRef status = NULL;
+ CFMutableDictionaryRef status_devices;
+ CFMutableDictionaryRef status_interface;
+
+ if (!isA_BondInterface(bond)) {
+ return NULL;
+ }
+
+ s = inet_dgram_socket();
+ if (s < 0) {
+ goto done;
+ }
+ _SC_cfstring_to_cstring(bondPrivate->ifname, bond_ifname,
+ sizeof(bond_ifname), kCFStringEncodingASCII);
+ (void)siocgifmedia(s, bond_ifname, &bond_if_status, &bond_if_active);
+ ibsr_p = if_bond_status_req_copy(s, bond_ifname);
+ if (ibsr_p == NULL) {
+ goto done;
+ }
+ status_interface = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ status_devices = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ n = ibsr_p->ibsr_total;
+ for (i = 0, scan_p = (struct if_bond_status *)ibsr_p->ibsr_buffer; i < n; i++, scan_p++) {
+ CFStringRef bond_if;
+ int collecting = 0;
+ int distributing = 0;
+ struct if_bond_partner_state * ps;
+ CFMutableDictionaryRef status_device;
+ int status_val;
+
+ ps = &scan_p->ibs_partner_state;
+
+ status_device = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (lacp_actor_partner_state_in_sync(scan_p->ibs_state)) {
+ /* we're in-sync */
+ status_val = kSCBondStatusOK;
+ if (lacp_actor_partner_state_in_sync(ps->ibps_state)) {
+ /* partner is also in-sync */
+ if (lacp_actor_partner_state_collecting(scan_p->ibs_state)
+ && lacp_actor_partner_state_distributing(ps->ibps_state)) {
+ /* we're able to collect (receive) frames */
+ collecting = 1;
+ }
+ if (lacp_actor_partner_state_distributing(scan_p->ibs_state)
+ && lacp_actor_partner_state_collecting(ps->ibps_state)) {
+ /* we're able to distribute (transmit) frames */
+ distributing = 1;
+ }
+ }
+ }
+ else {
+ int active = 0;
+ int status = 0;
+ lacp_system zeroes = {{0,0,0,0,0,0}};
+
+ (void)siocgifmedia(s, scan_p->ibs_if_name, &status, &active);
+ if ((status & IFM_AVALID) == 0 || (status & IFM_ACTIVE) == 0
+ || (active & IFM_FDX) == 0) {
+ /* link down or not full-duplex */
+ status_val = kSCBondStatusLinkInvalid;
+ }
+ else if (ps->ibps_system_priority == 0
+ && bcmp(&zeroes, &ps->ibps_system, sizeof(zeroes)) == 0) {
+ /* no one on the other end of the link */
+ status_val = kSCBondStatusNoPartner;
+ }
+ else if (active != bond_if_active) {
+ /* the link speed was different */
+ status_val = kSCBondStatusLinkInvalid;
+ }
+ else {
+ /* partner is not in the active group */
+ status_val = kSCBondStatusNotInActiveGroup;
+ }
+ }
+ num = CFNumberCreate(NULL, kCFNumberIntType, &status_val);
+ CFDictionarySetValue(status_device, kSCBondStatusDeviceAggregationStatus, num);
+ CFRelease(num);
+ num = CFNumberCreate(NULL, kCFNumberIntType, &collecting);
+ CFDictionarySetValue(status_device, kSCBondStatusDeviceCollecting, num);
+ CFRelease(num);
+ num = CFNumberCreate(NULL, kCFNumberIntType, &distributing);
+ CFDictionarySetValue(status_device, kSCBondStatusDeviceDistributing, num);
+ CFRelease(num);
+ bond_if = CFArrayGetValueAtIndex(bondPrivate->devices, i);
+ CFDictionarySetValue(status_devices, bond_if, status_device);
+ CFRelease(status_device);
+ }
+
+ status = __BondStatusCreatePrivate(NULL, bond, status_interface, status_devices);
+
+ CFRelease(status_interface);
+ CFRelease(status_devices);
+ done:
+ if (s >= 0) {
+ close(s);
+ }
+ if (ibsr_p != NULL) {
+ free(ibsr_p);
+ }
+ return status;
+}
+
+
+#define N_QUICK 16
+
+
+CFArrayRef
+BondStatusGetDevices(BondStatusRef bondStatus)
+{
+ BondStatusPrivateRef statusPrivate = (BondStatusPrivateRef)bondStatus;
+
+ if (!isA_BondStatus(bondStatus)) {
+ return NULL;
+ }
+
+ if (statusPrivate->devices == NULL) {
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+ CFIndex n;
+
+ n = CFDictionaryGetCount(statusPrivate->status_devices);
+ if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(statusPrivate->status_devices, keys, NULL);
+ statusPrivate->devices = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ }
+ }
+
+ return statusPrivate->devices;
+}
+
+
+CFDictionaryRef
+BondStatusGetInterfaceStatus(BondStatusRef bondStatus)
+{
+ BondStatusPrivateRef statusPrivate = (BondStatusPrivateRef)bondStatus;
+
+ if (!isA_BondStatus(bondStatus)) {
+ return NULL;
+ }
+
+ return statusPrivate->status_interface;
+}
+
+
+CFDictionaryRef
+BondStatusGetDeviceStatus(BondStatusRef bondStatus, CFStringRef device)
+{
+ BondStatusPrivateRef statusPrivate = (BondStatusPrivateRef)bondStatus;
+
+ if (!isA_BondStatus(bondStatus)) {
+ return NULL;
+ }
+
+ return CFDictionaryGetValue(statusPrivate->status_devices, device);
+}
--- /dev/null
+/*
+ * Copyright (c) 2003 Apple Computer, 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@
+ */
+
+#ifndef _BONDCONFIGURATION_H
+#define _BONDCONFIGURATION_H
+
+/*!
+ @header BONDCONFIGURATION
+*/
+
+#include <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+
+
+typedef const struct __BondInterface * BondInterfaceRef;
+
+typedef const struct __BondPreferences * BondPreferencesRef;
+
+typedef const struct __BondStatus * BondStatusRef;
+
+
+enum {
+ kSCBondStatusOK = 0, /* enabled, active, running, ... */
+ kSCBondStatusLinkInvalid = 1, /* The link state was not valid (i.e. down, half-duplex, wrong speed) */
+ kSCBondStatusNoPartner = 2, /* The port on the switch that the device is connected doesn't seem to have 802.3ad Link Aggregation enabled */
+ kSCBondStatusNotInActiveGroup = 3, /* We're talking to a partner, but the link aggregation group is different from the one that's active */
+ kSCBondStatusUnknown = 999 /* Non-specific failure */
+};
+
+extern const CFStringRef kSCBondStatusDeviceAggregationStatus /* CFNumber */ AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern const CFStringRef kSCBondStatusDeviceCollecting /* CFNumber (0 or 1) */ AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern const CFStringRef kSCBondStatusDeviceDistributing /* CFNumber (0 or 1) */ AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+__BEGIN_DECLS
+
+// ----------
+
+extern const CFStringRef kSCNetworkInterfaceTypeBOND;
+
+Boolean
+SCNetworkInterfaceSupportsBonding (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithBond (BondInterfaceRef bond) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+// ----------
+
+Boolean
+IsBondSupported (CFStringRef device) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // e.g. "en0", "en1", ...
+
+// ----------
+
+CFTypeID
+BondInterfaceGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFStringRef
+BondInterfaceGetInterface (BondInterfaceRef bond) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // returns "bond0", "bond1", ...
+
+CFArrayRef /* of CFStringRef's */
+BondInterfaceGetDevices (BondInterfaceRef bond) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFDictionaryRef
+BondInterfaceGetOptions (BondInterfaceRef bond) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // e.g. UserDefinedName, ...
+
+// ----------
+
+CFTypeID
+BondPreferencesGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+BondPreferencesRef
+BondPreferencesCreate (CFAllocatorRef allocator) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFArrayRef /* of BondInterfaceRef's */
+BondPreferencesCopyInterfaces (BondPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+BondInterfaceRef
+BondPreferencesCreateInterface (BondPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesRemoveInterface (BondPreferencesRef prefs,
+ BondInterfaceRef bond) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesAddDevice (BondPreferencesRef prefs,
+ BondInterfaceRef bond,
+ CFStringRef device) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // e.g. "en0", "en1", ...
+
+Boolean
+BondPreferencesRemoveDevice (BondPreferencesRef prefs,
+ BondInterfaceRef bond,
+ CFStringRef device) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // e.g. "en0", "en1", ...
+
+Boolean
+BondPreferencesSetOptions (BondPreferencesRef prefs,
+ BondInterfaceRef bond,
+ CFDictionaryRef newOptions) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesCommitChanges (BondPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesApplyChanges (BondPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+// ----------
+
+CFTypeID
+BondStatusGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+BondStatusRef
+BondInterfaceCopyStatus (BondInterfaceRef bond) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFArrayRef
+BondStatusGetDevices (BondStatusRef bondStatus) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFDictionaryRef
+BondStatusGetInterfaceStatus (BondStatusRef bondStatus) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFDictionaryRef
+BondStatusGetDeviceStatus (BondStatusRef bondStatus,
+ CFStringRef device) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+__END_DECLS
+
+#endif /* _BONDCONFIGURATION_H */
--- /dev/null
+/*
+ * Copyright (c) 2003 Apple Computer, 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@
+ */
+
+#ifndef _BONDCONFIGURATIONPRIVATE_H
+#define _BONDCONFIGURATIONPRIVATE_H
+
+
+#include <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <SystemConfiguration/BondConfiguration.h>
+
+
+/*!
+ @header BONDConfigurationPrivate
+ */
+
+
+#define BOND_PREFERENCES_ID CFSTR("VirtualNetworkInterfaces.plist")
+
+
+__BEGIN_DECLS
+
+CFArrayRef
+_BondPreferencesCopyActiveInterfaces ();
+
+Boolean
+_BondPreferencesUpdateConfiguration (BondPreferencesRef prefs);
+
+__END_DECLS
+
+#endif /* _BONDCONFIGURATIONPRIVATE_H */
+++ /dev/null
-{
- CFBundleName = "SystemConfiguration";
- CFBundleIdentifier = "com.apple.SystemConfiguration";
- CFBundleShortVersionString = "1.7.1";
-}
{
CFMutableDictionaryRef dict = NULL;
CFStringRef path = NULL;
- SCPreferencesRef session = NULL;
+ SCPreferencesRef prefs = NULL;
Boolean success = FALSE;
if (applicationID == NULL) {
if (path == NULL) {
goto done;
}
- session = SCPreferencesCreate(NULL, CFSTR("DHCPClientSetAppReqParams"),
- CFSTR(DHCPCLIENT_PREFERENCES_ID));
- if (session == NULL) {
+ prefs = SCPreferencesCreate(NULL, CFSTR("DHCPClientSetAppReqParams"),
+ CFSTR(DHCPCLIENT_PREFERENCES_ID));
+ if (prefs == NULL) {
goto done;
}
- dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(session, path);
+ dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(prefs, path);
if (dict == NULL) {
dict = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
else {
CFDictionaryRemoveValue(dict, CFSTR(DHCP_REQUESTED_PARAMETER_LIST));
}
- if (SCPreferencesLock(session, TRUE)) {
- success = SCPreferencesPathSetValue(session, path, dict);
+ if (SCPreferencesLock(prefs, TRUE)) {
+ success = SCPreferencesPathSetValue(prefs, path, dict);
if (success) {
- success = SCPreferencesCommitChanges(session);
+ success = SCPreferencesCommitChanges(prefs);
if (success) {
- (void)SCPreferencesApplyChanges(session);
+ (void)SCPreferencesApplyChanges(prefs);
}
}
- (void)SCPreferencesUnlock(session);
+ (void)SCPreferencesUnlock(prefs);
}
done:
- if (session) {
- CFRelease(session);
+ if (prefs) {
+ CFRelease(prefs);
}
if (path) {
CFRelease(path);
UInt8 * options = NULL;
CFArrayRef parms;
CFStringRef path = NULL;
- SCPreferencesRef session = NULL;
+ SCPreferencesRef prefs = NULL;
if (applicationID == NULL) {
goto done;
if (path == NULL) {
goto done;
}
- session = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"),
- CFSTR(DHCPCLIENT_PREFERENCES_ID));
- if (session == NULL) {
+ prefs = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"),
+ CFSTR(DHCPCLIENT_PREFERENCES_ID));
+ if (prefs == NULL) {
goto done;
}
- dict = SCPreferencesPathGetValue(session, path);
+ dict = SCPreferencesPathGetValue(prefs, path);
if (dict == NULL) {
goto done;
}
options = S_get_char_array(parms, count);
done:
- if (session) {
- CFRelease(session);
+ if (prefs) {
+ CFRelease(prefs);
}
if (path) {
CFRelease(path);
#include <CoreFoundation/CFString.h>
/*!
- @header DHCPClientPreferences.h
+ @header DHCPClientPreferences
+ @discussion The DHCPClientPreferences API allows applications to get and update DHCP preferences.
+ DHCP preferences are in the form of DHCP option codes, which are defined in RFC 2132.
*/
__BEGIN_DECLS
/*!
@function DHCPClientPreferencesSetApplicationOptions
@discussion Updates the DHCP client preferences to include the
- given list of options for the given "applicationID".
+ given list of options for the given application ID.
@param applicationID The application's preference ID, for example:
"com.apple.SystemPreferences".
@param options An array of 8-bit values containing the
- DHCP option codes (see RFC 2132) for this applicationID.
+ DHCP option codes (see RFC 2132) for this application ID.
A NULL value will clear the list of options for this
application ID.
- @param count The number of elements in "options".
- @result TRUE if the operation succeeded, FALSE otherwise.
+ @param count The number of elements in the options parameter.
+ @result Returns TRUE if the operation succeeded, FALSE otherwise.
*/
Boolean
/*!
@function DHCPClientPreferencesCopyApplicationOptions
@discussion Copies the requested DHCP options for the
- given "applicationID".
+ given application ID.
@param applicationID The application's preference ID, for example
"com.apple.SystemPreferences".
@param count The number of elements in the returned array.
- @result The list of options for the given "applicationID", or
+ @result Returns the list of options for the given application ID, or
NULL if no options are defined or an error occurred.
- When done, use free() to release a non-NULL return value.
+ When you are finished, use free() to release a non-NULL return value.
*/
UInt8 *
{
DeviceOnHoldPrivateRef DeviceOnHoldPrivate = (DeviceOnHoldPrivateRef)cf;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__DeviceOnHoldDeallocate:"));
-
/* release resources */
if (DeviceOnHoldPrivate->name) CFRelease(DeviceOnHoldPrivate->name);
if (DeviceOnHoldPrivate->sock != -1) {
CFMutableDictionaryRef deviceToMatch;
uint32_t deviceSupportsHoldValue;
kern_return_t kr;
- mach_port_t masterPort;
- io_iterator_t matchingServices;
+ static mach_port_t masterPort = MACH_PORT_NULL;
+ io_iterator_t matchingServices;
CFNumberRef num;
CFMutableDictionaryRef properties;
Boolean result = FALSE;
io_service_t service;
- if (CFStringCompare(deviceName, CFSTR("modem"), NULL) == kCFCompareEqualTo) {
- kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
- if (kr != KERN_SUCCESS) {
- goto errorExit;
+ if (CFStringCompare(deviceName, CFSTR("modem"), 0) == kCFCompareEqualTo) {
+ if (masterPort == MACH_PORT_NULL) {
+ kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+ if (kr != KERN_SUCCESS) {
+ return FALSE;
+ }
}
deviceToMatch = IOServiceMatching("InternalModemSupport");
- if (!deviceToMatch) {
- goto errorExit;
+ if (deviceToMatch == NULL) {
+ return FALSE;
}
kr = IOServiceGetMatchingServices(masterPort, deviceToMatch, &matchingServices);
if (kr != KERN_SUCCESS) {
- goto errorExit;
+ return FALSE;
}
for ( ; (service = IOIteratorNext(matchingServices)) ; IOObjectRelease(service)) {
// to know the exact driver they are searching for.
return result;
-
- errorExit:
-
- return FALSE;
}
DeviceOnHoldPrivateRef devicePrivate;
int status;
- if (CFStringCompare(deviceName, CFSTR("modem"), NULL) != kCFCompareEqualTo) {
+ if (CFStringCompare(deviceName, CFSTR("modem"), 0) != kCFCompareEqualTo) {
return NULL;
}
#include <CoreFoundation/CoreFoundation.h>
+/*!
+ @header DeviceOnHold
+ */
+
+
/*!
@enum
@discussion Returned status codes from DeviceOnHoldGetStatus()
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundleGetInfoString</key>
+ <string>1.8.0</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.SystemConfiguration</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>SystemConfiguration</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.8.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.8.0</string>
+</dict>
+</plist>
io_registry_entry_t io_interface = 0;
io_registry_entry_t io_controller = 0;
kern_return_t kr;
- mach_port_t masterPort = MACH_PORT_NULL;
+ static mach_port_t masterPort = MACH_PORT_NULL;
CFMutableDictionaryRef matchingDict;
/* look for a matching interface in the IORegistry */
+ if (masterPort == MACH_PORT_NULL) {
+ kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+ if (kr != KERN_SUCCESS) {
+ return FALSE;
+ }
+ }
+
matchingDict = IOBSDNameMatching(masterPort, 0, ifr_name);
if (matchingDict) {
/* Note: IOServiceGetMatchingServices consumes a reference on the 'matchingDict' */
bzero((void *)&ifr, sizeof(ifr));
if (_SC_cfstring_to_cstring(interface, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII) == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("could not convert inteface name"));
+ SCLog(TRUE, LOG_ERR, CFSTR("could not convert interface name"));
goto done;
}
/* get valid MTU range */
- if (mtu_min || mtu_max) {
- ok = __getMTULimits(ifr.ifr_name, mtu_min, mtu_max);
- if (!ok) {
- struct ifreq vifr;
- struct vlanreq vreq;
-
- // check if this is a vlan
-
- bzero(&vifr, sizeof(vifr));
- bzero(&vreq, sizeof(vreq));
- strncpy(vifr.ifr_name, ifr.ifr_name, sizeof(vifr.ifr_name));
- vifr.ifr_data = (caddr_t)&vreq;
+ if (mtu_min != NULL || mtu_max != NULL) {
+ if (ioctl(sock, SIOCGIFDEVMTU, (caddr_t)&ifr) == 0) {
+ struct ifdevmtu * devmtu_p;
- if (ioctl(sock, SIOCGETVLAN, (caddr_t)&vifr) == 0) {
- /*
- * yes, pass parent device MTU settings
- *
- * min == parent device minimum MTU
- * max == parent device current MTU
- */
- if (mtu_min) {
- (void) __getMTULimits(vreq.vlr_parent, mtu_min, NULL);
- }
- if (mtu_max) {
- bzero(&vifr, sizeof(vifr));
- strncpy(vifr.ifr_name, vreq.vlr_parent, sizeof(vifr.ifr_name));
- if (ioctl(sock, SIOCGIFMTU, (caddr_t)&vifr) == 0) {
- *mtu_max = vifr.ifr_mtu;
- }
- }
+ devmtu_p = &ifr.ifr_devmtu;
+ if (mtu_min != NULL) {
+ *mtu_min = (devmtu_p->ifdm_min > IF_MINMTU)
+ ? devmtu_p->ifdm_min : IF_MINMTU;
+ }
+ if (mtu_max != NULL) {
+ *mtu_max = devmtu_p->ifdm_max;
}
}
+ else {
+ (void)__getMTULimits(ifr.ifr_name, mtu_min, mtu_max);
+ }
}
ok = TRUE;
#include <sys/cdefs.h>
#include <CoreFoundation/CoreFoundation.h>
+/*!
+ @header LinkConfiguration
+*/
__BEGIN_DECLS
#
-# Generated by the Apple Project Builder.
+# Makefile for generating the SCSchemaDefinitions.[ch] files
#
-# 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 = SystemConfiguration
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Framework
-
-HFILES = SystemConfiguration.h SCPrivate.h SCDPlugin.h config_types.h\
- SCDynamicStoreInternal.h SCDynamicStore.h\
- SCDynamicStorePrivate.h SCDynamicStoreKey.h\
- SCDynamicStoreCopySpecific.h SCDynamicStoreCopySpecificPrivate.h\
- SCDynamicStoreSetSpecificPrivate.h SCPreferencesInternal.h\
- SCPreferences.h SCPreferencesPrivate.h SCPreferencesPath.h\
- SCPreferencesSetSpecific.h SCNetwork.h SCNetworkConnection.h\
- SCNetworkReachability.h SCValidation.h ppp.h\
- DHCPClientPreferences.h SCDynamicStoreCopyDHCPInfo.h moh_msg.h\
- moh.h DeviceOnHold.h LinkConfiguration.h dy_framework.h\
- VLANConfiguration.h VLANConfigurationPrivate.h
-
-CFILES = SCD.c SCDKeys.c SCDPrivate.c SCDPlugin.c SCDOpen.c SCDLock.c\
- SCDUnlock.c SCDList.c SCDAdd.c SCDAddSession.c SCDGet.c\
- SCDSet.c SCDRemove.c SCDTouch.c SCDNotify.c\
- SCDNotifierSetKeys.c SCDNotifierAdd.c SCDNotifierRemove.c\
- SCDNotifierGetChanges.c SCDNotifierWait.c\
- SCDNotifierInformViaCallback.c SCDNotifierInformViaMachPort.c\
- SCDNotifierInformViaFD.c SCDNotifierInformViaSignal.c\
- SCDNotifierCancel.c SCDSnapshot.c SCP.c SCPOpen.c SCPLock.c\
- SCPUnlock.c SCPList.c SCPGet.c SCPAdd.c SCPSet.c SCPRemove.c\
- SCPCommit.c SCPApply.c SCPPath.c SCDConsoleUser.c\
- SCDHostName.c SCLocation.c SCNetwork.c SCNetworkConnection.c\
- SCNetworkReachability.c SCProxies.c ppp.c DHCP.c moh.c\
- DeviceOnHold.c LinkConfiguration.c dy_framework.c\
- VLANConfiguration.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
- h.template config.defs genSCPreferences.c CustomInfo.plist
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CURRENTLY_ACTIVE_VERSION = YES
-DEPLOY_WITH_VERSION_NAME = A
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = framework.make
-NEXTSTEP_INSTALLDIR = $(SYSTEM_LIBRARY_DIR)/Frameworks
-WINDOWS_INSTALLDIR = /Library/Frameworks
-PDO_UNIX_INSTALLDIR = /Library/Frameworks
-LIBS =
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-HEADER_PATHS =\
- -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
-NEXTSTEP_PB_CFLAGS = -fconstant-cfstrings -DBIND_8_COMPAT -DCHECK_IPV6_REACHABILITY
-FRAMEWORKS = -framework CoreFoundation
-PUBLIC_HEADERS = SystemConfiguration.h SCDynamicStore.h\
- SCDynamicStoreKey.h SCDynamicStoreCopySpecific.h\
- SCPreferences.h SCPreferencesPath.h\
- SCPreferencesSetSpecific.h SCNetwork.h\
- SCNetworkConnection.h SCNetworkReachability.h\
- DHCPClientPreferences.h SCDynamicStoreCopyDHCPInfo.h
-
-PROJECT_HEADERS = SystemConfiguration.h SCPrivate.h config_types.h\
- SCDynamicStoreInternal.h SCDynamicStore.h\
- SCDynamicStorePrivate.h SCDynamicStoreKey.h\
- SCDynamicStoreCopySpecific.h\
- SCDynamicStoreCopySpecificPrivate.h\
- SCDynamicStoreSetSpecificPrivate.h\
- SCPreferencesInternal.h SCPreferences.h\
- SCPreferencesPrivate.h SCPreferencesPath.h\
- SCPreferencesSetSpecific.h SCNetwork.h\
- SCNetworkConnection.h SCNetworkReachability.h\
- SCValidation.h VLANConfigurationPrivate.h
-
-
-
-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 $(MAKEFILEDIR)/platform.make
--include Makefile.preamble
+all: SCSchemaDefinitions.h SCSchemaDefinitions.c
-include $(MAKEFILEDIR)/$(MAKEFILE)
+/tmp/genSCPreferences: genSCPreferences.c Makefile
+ cc -g -o /tmp/genSCPreferences genSCPreferences.c
--include Makefile.postamble
+SCSchemaDefinitions.h: /tmp/genSCPreferences
+ /tmp/genSCPreferences header > SCSchemaDefinitions.h
--include Makefile.dependencies
+SCSchemaDefinitions.c: /tmp/genSCPreferences
+ /tmp/genSCPreferences cfile > SCSchemaDefinitions.c
+++ /dev/null
-###############################################################################
-# Makefile.postamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile, which is imported after all other makefiles, to
-# override attributes for a project's Makefile environment. This allows you
-# to take advantage of the environment set up by the other Makefiles.
-# You can also define custom rules at the end of this file.
-#
-###############################################################################
-#
-# These variables are exported by the standard makefiles and can be
-# used in any customizations you make. They are *outputs* of
-# the Makefiles and should be used, not set.
-#
-# PRODUCTS: products to install. All of these products will be placed in
-# the directory $(DSTROOT)$(INSTALLDIR)
-# GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-# OFILE_DIR: Directory into which .o object files are generated.
-# DERIVED_SRC_DIR: Directory used for all other derived files
-#
-# ALL_CFLAGS: flags to pass when compiling .c files
-# ALL_MFLAGS: flags to pass when compiling .m files
-# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files
-# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files
-# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files
-# ALL_LDFLAGS: flags to pass when linking object files
-# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files
-# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files
-# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files
-# ALL_YFLAGS: flags to pass when processing .y (yacc) files
-# ALL_LFLAGS: flags to pass when processing .l (lex) files
-#
-# NAME: name of application, bundle, subproject, palette, etc.
-# LANGUAGES: langages in which the project is written (default "English")
-# English_RESOURCES: localized resources (e.g. nib's, images) of project
-# GLOBAL_RESOURCES: non-localized resources of project
-#
-# SRCROOT: base directory in which to place the new source files
-# SRCPATH: relative path from SRCROOT to present subdirectory
-#
-# INSTALLDIR: Directory the product will be installed into by 'install' target
-# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-#
-# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost)
-# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults
-# to -g)
-# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG)
-# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults
-# to -O)
-# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults
-# to -pg -DPROFILE)
-# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to
-# the include path (defaults to -I.)
-# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-# passed to ld/libtool (defaults to nothing)
-WARNING_CFLAGS=-Wall
-
-
-# Library and Framework projects only:
-# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked
-# against the framework will run against the correct version even if
-# the current version of the framework changes. You may override this
-# to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-# development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
- # User/group ownership
-#INSTALL_AS_GROUP = wheel
- # (probably want to set both of these)
-#INSTALL_PERMISSIONS =
- # If set, 'install' chmod's executable to this
-
-
-# Options to strip. Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here. Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where
-# derived files should go.
-#
-
-#
-# Additional options to create generated headers, source
-#
-before_installhdrs: $(OFILE_DIR)
-
-$(OFILE_DIR)/genSCPreferences: genSCPreferences.o
- $(CC) -o $@ $(ARCHITECTURE_FLAGS) $<
-
-SCSchemaDefinitions_10_1.h: $(OFILE_DIR)/genSCPreferences
- $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences header-x > $@
-
-SCSchemaDefinitions.h: $(OFILE_DIR)/genSCPreferences
- $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences header > $@
-
-SCSchemaDefinitions.c: $(OFILE_DIR)/genSCPreferences
- $(CD) $(SFILE_DIR) && $(OFILE_DIR)/genSCPreferences cfile > $@
-
-genSCFiles:
- cc -o /tmp/genSCFiles genSCPreferences.c -framework CoreFoundation
- /tmp/genSCFiles header > /tmp/SCSchemaDefinitions.h
- /tmp/genSCFiles header-x > /tmp/SCSchemaDefinitions_10_1.h
- /tmp/genSCFiles cfile > /tmp/SCSchemaDefinitions.c
-
-dhcp: DHCP.c
- cc -Wall -DTEST_DHCPCLIENT_PREFERENCES -g -o dhcp DHCP.c -framework CoreFoundation -framework SystemConfiguration
+++ /dev/null
-###############################################################################
-# Makefile.preamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile for configuring the standard application makefiles
-# associated with ProjectBuilder. It is included before the main makefile.
-# In Makefile.preamble you set attributes for a project, so they are available
-# to the project's makefiles. In contrast, you typically write additional rules or
-# override built-in behavior in the Makefile.postamble.
-#
-# Each directory in a project tree (main project plus subprojects) should
-# have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-# MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults: The OTHER_* variables will be
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible. To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler
-# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-# .cc, .cxx, .C, and .M files. There is no need to respecify the
-# flags in OTHER_MFLAGS, etc.
-# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files
-# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files
-# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files
-# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when
-# precompiling header files
-# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool
-# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap
-# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen
-# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc
-# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every
-# stage of the make:
-#
-# BEFORE_PREBUILD: targets to build before installing headers for a subproject
-# AFTER_PREBUILD: targets to build after installing headers for a subproject
-# BEFORE_BUILD_RECURSION: targets to make before building subprojects
-# BEFORE_BUILD: targets to make before a build, but after subprojects
-# AFTER_BUILD: targets to make after a build
-#
-# BEFORE_INSTALL: targets to build before installing the product
-# AFTER_INSTALL: targets to build after installing the product
-# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-# AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-# BEFORE_INSTALLHDRS: targets to build before installing headers for a
-# subproject
-# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-# BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-# AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-# BEFORE_DEPEND: targets to build before building dependencies for a
-# subproject
-# AFTER_DEPEND: targets to build after building dependencies for a
-# subproject
-#
-# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-# updated every time the project is built. If NO, the dependency
-# file is only built when the depend target is invoked.
-
-# Framework-related variables:
-# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the framework's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-# PUBLIC_HEADER_DIR: Determines where public exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically. For library projects you should
-# set this to something like /Developer/Headers/$(NAME). Do not set
-# this variable for framework projects unless you do not want the
-# header files included in the framework.
-# PRIVATE_HEADER_DIR: Determines where private exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically.
-# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines
-# whether the libraries produced are statically linked when they
-# are used or if they are dynamically loadable. This defaults to
-# DYNAMIC.
-# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the library's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-#
-# INSTALL_AS_USER: owner of the intalled products (default root)
-# INSTALL_AS_GROUP: group of the installed products (default wheel)
-# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-# passed on the command line to recursive invocations of make. Note that
-# the values in OTHER_*FLAGS are inherited by subprojects automatically --
-# you do not have to (and shouldn't) add OTHER_*FLAGS to
-# OTHER_RECURSIVE_VARIABLES.
-
-# Additional headers to export beyond those in the PB.project:
-# OTHER_PUBLIC_HEADERS
-# OTHER_PROJECT_HEADERS
-# OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-# OTHER_RESOURCES: (non-localized) resources for this project
-# OTHER_OFILES: relocatables to be linked into this project
-# OTHER_LIBS: more libraries to link against
-# OTHER_PRODUCT_DEPENDS: other dependencies of this project
-# OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-# OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-# BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed. By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object). Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-# DSTROOT = $(HOME)
-
-# Additional flags for MiG generated files
-OTHER_PRIVATE_HEADERS += config.defs config.h
-
-OTHER_PRIVATE_HEADERS += SCPrivate.h
-OTHER_PRIVATE_HEADERS += SCDynamicStorePrivate.h
-OTHER_PRIVATE_HEADERS += SCDynamicStoreCopySpecificPrivate.h
-OTHER_PRIVATE_HEADERS += SCDynamicStoreSetSpecificPrivate.h
-OTHER_PRIVATE_HEADERS += SCPreferencesPrivate.h
-OTHER_PRIVATE_HEADERS += SCValidation.h
-OTHER_PRIVATE_HEADERS += SCDPlugin.h
-OTHER_PRIVATE_HEADERS += DeviceOnHold.h
-OTHER_PRIVATE_HEADERS += LinkConfiguration.h
-OTHER_PRIVATE_HEADERS += VLANConfiguration.h
-OTHER_PRIVATE_HEADERS += VLANConfigurationPrivate.h
-
-#
-# MiG generated files
-#
-OTHER_OFILES += configUser.o
-
-# Additional options to create generated headers, source
-BEFORE_INSTALLHDRS = before_installhdrs
-OTHER_SOURCEFILES += genSCPreferences.c
-OTHER_GENERATED_SRCFILES += SCSchemaDefinitions_10_1.h
-OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.h
-OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.c
-OTHER_PUBLIC_HEADERS += SCSchemaDefinitions_10_1.h
-OTHER_PUBLIC_HEADERS += SCSchemaDefinitions.h
-OTHER_OFILES += SCSchemaDefinitions.o
-
-# Additional build flags
-ifeq "$(PLATFORM_OS)" "macos"
-ifneq "$(RC_RELEASE)" "Darwin"
- APPLE_INTERNAL_DIR ?= /AppleInternal
- APPLE_INTERNAL_DEVELOPER_DIR ?= /AppleInternal/Developer
- OTHER_LDFLAGS += -seg_addr_table $(APPLE_INTERNAL_DEVELOPER_DIR)/seg_addr_table
- SECTORDER_FLAGS = -sectorder __TEXT __text $(APPLE_INTERNAL_DIR)/OrderFiles/SystemConfiguration.order
-endif
-endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Interface</key>
+ <dict>
+ <key>6to4-IPv4</key>
+ <dict/>
+ <key>Bluetooth</key>
+ <dict/>
+ <key>Bond</key>
+ <dict/>
+ <key>Ethernet</key>
+ <dict/>
+ <key>FireWire</key>
+ <dict/>
+ <key>IEEE80211</key>
+ <dict/>
+ <key>IrDA</key>
+ <dict/>
+ <key>L2TP-IPv4</key>
+ <dict/>
+ <key>Modem</key>
+ <dict>
+ <key>ConnectionScript</key>
+ <string>Apple Internal 56K Modem (v.92)</string>
+ <key>DataCompression</key>
+ <integer>1</integer>
+ <key>DialMode</key>
+ <string>WaitForDialTone</string>
+ <key>ErrorCorrection</key>
+ <integer>1</integer>
+ <key>HoldCallWaitingAudibleAlert</key>
+ <integer>1</integer>
+ <key>HoldDisconnectOnAnswer</key>
+ <integer>0</integer>
+ <key>HoldEnabled</key>
+ <integer>0</integer>
+ <key>HoldReminder</key>
+ <integer>1</integer>
+ <key>HoldReminderTime</key>
+ <integer>10</integer>
+ <key>PulseDial</key>
+ <integer>0</integer>
+ <key>Speaker</key>
+ <integer>1</integer>
+ </dict>
+ <key>PPP-Bluetooth</key>
+ <dict/>
+ <key>PPP-Ethernet</key>
+ <dict>
+ <key>ACSPEnabled</key>
+ <integer>0</integer>
+ <key>CommDisplayTerminalWindow</key>
+ <integer>0</integer>
+ <key>CommRedialCount</key>
+ <integer>1</integer>
+ <key>CommRedialEnabled</key>
+ <integer>1</integer>
+ <key>CommRedialInterval</key>
+ <integer>5</integer>
+ <key>CommUseTerminalScript</key>
+ <integer>0</integer>
+ <key>DialOnDemand</key>
+ <integer>0</integer>
+ <key>DisconnectOnIdle</key>
+ <integer>0</integer>
+ <key>DisconnectOnIdleTimer</key>
+ <integer>1800</integer>
+ <key>DisconnectOnLogout</key>
+ <integer>1</integer>
+ <key>DisconnectOnSleep</key>
+ <integer>1</integer>
+ <key>IPCPCompressionVJ</key>
+ <integer>1</integer>
+ <key>IdleReminder</key>
+ <integer>0</integer>
+ <key>IdleReminderTimer</key>
+ <integer>1800</integer>
+ <key>LCPEchoEnabled</key>
+ <integer>1</integer>
+ <key>LCPEchoFailure</key>
+ <integer>4</integer>
+ <key>LCPEchoInterval</key>
+ <integer>10</integer>
+ <key>Logfile</key>
+ <string>/var/log/ppp.log</string>
+ <key>VerboseLogging</key>
+ <integer>0</integer>
+ </dict>
+ <key>PPP-IrDA</key>
+ <dict/>
+ <key>PPP-L2TP</key>
+ <dict/>
+ <key>PPP-Modem</key>
+ <dict>
+ <key>ACSPEnabled</key>
+ <integer>0</integer>
+ <key>CommDisplayTerminalWindow</key>
+ <integer>0</integer>
+ <key>CommRedialCount</key>
+ <integer>1</integer>
+ <key>CommRedialEnabled</key>
+ <integer>1</integer>
+ <key>CommRedialInterval</key>
+ <integer>5</integer>
+ <key>CommUseTerminalScript</key>
+ <integer>0</integer>
+ <key>DialOnDemand</key>
+ <integer>0</integer>
+ <key>DisconnectOnIdle</key>
+ <integer>1</integer>
+ <key>DisconnectOnIdleTimer</key>
+ <integer>600</integer>
+ <key>DisconnectOnLogout</key>
+ <integer>1</integer>
+ <key>DisconnectOnSleep</key>
+ <integer>1</integer>
+ <key>IPCPCompressionVJ</key>
+ <integer>1</integer>
+ <key>IdleReminder</key>
+ <integer>0</integer>
+ <key>IdleReminderTimer</key>
+ <integer>1800</integer>
+ <key>LCPEchoEnabled</key>
+ <integer>1</integer>
+ <key>LCPEchoFailure</key>
+ <integer>4</integer>
+ <key>LCPEchoInterval</key>
+ <integer>10</integer>
+ <key>Logfile</key>
+ <string>/var/log/ppp.log</string>
+ <key>VerboseLogging</key>
+ <integer>0</integer>
+ </dict>
+ <key>PPP-PPTP</key>
+ <dict/>
+ <key>PPP-Serial</key>
+ <dict/>
+ <key>PPTP-IPv4</key>
+ <dict/>
+ <key>Serial</key>
+ <dict/>
+ <key>VLAN</key>
+ <dict/>
+ </dict>
+ <key>Protocol</key>
+ <dict>
+ <key>6to4-IPv4</key>
+ <dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>6to4</string>
+ </dict>
+ </dict>
+ <key>Bond</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>DHCP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>Ethernet</key>
+ <dict>
+ <key>AppleTalk</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Node</string>
+ </dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>DHCP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>FireWire</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>DHCP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>IEEE80211</key>
+ <dict>
+ <key>AppleTalk</key>
+ <dict/>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>DHCP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict/>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-Bluetooth</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-Ethernet</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-IrDA</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-L2TP</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-Modem</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-PPTP</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPP-Serial</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>PPP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>PPTP-IPv4</key>
+ <dict/>
+ <key>PPTP-L2TP</key>
+ <dict/>
+ <key>VLAN</key>
+ <dict>
+ <key>DNS</key>
+ <dict/>
+ <key>IPv4</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>DHCP</string>
+ </dict>
+ <key>IPv6</key>
+ <dict>
+ <key>ConfigMethod</key>
+ <string>Automatic</string>
+ </dict>
+ <key>Proxies</key>
+ <dict>
+ <key>FTPPassive</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ </dict>
+</dict>
+</plist>
+++ /dev/null
-{
- "CURRENTLY_ACTIVE_VERSION" = YES;
- "DEPLOY_WITH_VERSION_NAME" = A;
- "DYNAMIC_CODE_GEN" = YES;
- FILESTABLE = {
- FRAMEWORKS = ("CoreFoundation.framework");
- FRAMEWORKSEARCH = ();
- HEADERSEARCH = (
- "$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders"
- );
- "H_FILES" = (
- "SystemConfiguration.h",
- "SCPrivate.h",
- "SCDPlugin.h",
- "config_types.h",
- "SCDynamicStoreInternal.h",
- "SCDynamicStore.h",
- "SCDynamicStorePrivate.h",
- "SCDynamicStoreKey.h",
- "SCDynamicStoreCopySpecific.h",
- "SCDynamicStoreCopySpecificPrivate.h",
- "SCDynamicStoreSetSpecificPrivate.h",
- "SCPreferencesInternal.h",
- "SCPreferences.h",
- "SCPreferencesPrivate.h",
- "SCPreferencesPath.h",
- "SCPreferencesSetSpecific.h",
- "SCNetwork.h",
- "SCNetworkConnection.h",
- "SCNetworkReachability.h",
- "SCValidation.h",
- "ppp.h",
- "DHCPClientPreferences.h",
- "SCDynamicStoreCopyDHCPInfo.h",
- "moh_msg.h",
- "moh.h",
- "DeviceOnHold.h",
- "LinkConfiguration.h",
- "dy_framework.h",
- "VLANConfiguration.h",
- "VLANConfigurationPrivate.h"
- );
- "OTHER_LIBS" = ();
- "OTHER_LINKED" = (
- "SCD.c",
- "SCDKeys.c",
- "SCDPrivate.c",
- "SCDPlugin.c",
- "SCDOpen.c",
- "SCDLock.c",
- "SCDUnlock.c",
- "SCDList.c",
- "SCDAdd.c",
- "SCDAddSession.c",
- "SCDGet.c",
- "SCDSet.c",
- "SCDRemove.c",
- "SCDTouch.c",
- "SCDNotify.c",
- "SCDNotifierSetKeys.c",
- "SCDNotifierAdd.c",
- "SCDNotifierRemove.c",
- "SCDNotifierGetChanges.c",
- "SCDNotifierWait.c",
- "SCDNotifierInformViaCallback.c",
- "SCDNotifierInformViaMachPort.c",
- "SCDNotifierInformViaFD.c",
- "SCDNotifierInformViaSignal.c",
- "SCDNotifierCancel.c",
- "SCDSnapshot.c",
- "SCP.c",
- "SCPOpen.c",
- "SCPLock.c",
- "SCPUnlock.c",
- "SCPList.c",
- "SCPGet.c",
- "SCPAdd.c",
- "SCPSet.c",
- "SCPRemove.c",
- "SCPCommit.c",
- "SCPApply.c",
- "SCPPath.c",
- "SCDConsoleUser.c",
- "SCDHostName.c",
- "SCLocation.c",
- "SCNetwork.c",
- "SCNetworkConnection.c",
- "SCNetworkReachability.c",
- "SCProxies.c",
- "ppp.c",
- "DHCP.c",
- "moh.c",
- "DeviceOnHold.c",
- "LinkConfiguration.c",
- "dy_framework.c",
- "VLANConfiguration.c"
- );
- "OTHER_SOURCES" = (
- "Makefile.preamble",
- Makefile,
- "Makefile.postamble",
- "m.template",
- "h.template",
- "config.defs",
- "genSCPreferences.c",
- "CustomInfo.plist"
- );
- "PRECOMPILED_HEADERS" = ();
- "PROJECT_HEADERS" = (
- "SystemConfiguration.h",
- "SCPrivate.h",
- "config_types.h",
- "SCDynamicStoreInternal.h",
- "SCDynamicStore.h",
- "SCDynamicStorePrivate.h",
- "SCDynamicStoreKey.h",
- "SCDynamicStoreCopySpecific.h",
- "SCDynamicStoreCopySpecificPrivate.h",
- "SCDynamicStoreSetSpecificPrivate.h",
- "SCPreferencesInternal.h",
- "SCPreferences.h",
- "SCPreferencesPrivate.h",
- "SCPreferencesPath.h",
- "SCPreferencesSetSpecific.h",
- "SCNetwork.h",
- "SCNetworkConnection.h",
- "SCNetworkReachability.h",
- "SCValidation.h",
- "VLANConfigurationPrivate.h"
- );
- "PUBLIC_HEADERS" = (
- "SystemConfiguration.h",
- "SCDynamicStore.h",
- "SCDynamicStoreKey.h",
- "SCDynamicStoreCopySpecific.h",
- "SCPreferences.h",
- "SCPreferencesPath.h",
- "SCPreferencesSetSpecific.h",
- "SCNetwork.h",
- "SCNetworkConnection.h",
- "SCNetworkReachability.h",
- "DHCPClientPreferences.h",
- "SCDynamicStoreCopyDHCPInfo.h"
- );
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
- "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake";
- "NEXTSTEP_COMPILEROPTIONS" = "-fconstant-cfstrings -DBIND_8_COMPAT -DCHECK_IPV6_REACHABILITY";
- "NEXTSTEP_INSTALLDIR" = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
- "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac";
- "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc";
- "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make";
- "PDO_UNIX_INSTALLDIR" = "/Library/Frameworks";
- "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac";
- "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = SystemConfiguration;
- PROJECTTYPE = Framework;
- PROJECTVERSION = "2.8";
- "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make";
- "WINDOWS_INSTALLDIR" = "/Library/Frameworks";
- "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe";
- "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc";
-}
static pthread_once_t tsKeyInitialized = PTHREAD_ONCE_INIT;
-static pthread_key_t tsDataKey = NULL;
+static pthread_key_t tsDataKey;
static void
#include "config.h" /* MiG generated file */
Boolean
-SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
kern_return_t status;
int newInstance;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value);
+ if (store == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoStoreSession);
+ }
+
+ if (storePrivate->server == MACH_PORT_NULL) {
+ /* sorry, you must have an open session to play */
+ _SCErrorSet(kSCStatusNoStoreServer);
+ return FALSE;
+ }
+
+ /* serialize the key */
+ if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ /* serialize the data */
+ if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) {
+ CFRelease(utfKey);
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ /* send the key & data to the server */
+ status = configadd_s(storePrivate->server,
+ myKeyRef,
+ myKeyLen,
+ myDataRef,
+ myDataLen,
+ &newInstance,
+ (int *)&sc_status);
+
+ /* clean up */
+ CFRelease(utfKey);
+ CFRelease(xmlData);
+
+ if (status != KERN_SUCCESS) {
+#ifdef DEBUG
+ if (status != MACH_SEND_INVALID_DEST)
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue configadd_s(): %s"), mach_error_string(status));
+#endif /* DEBUG */
+ (void) mach_port_destroy(mach_task_self(), storePrivate->server);
+ storePrivate->server = MACH_PORT_NULL;
+ _SCErrorSet(status);
+ return FALSE;
}
- if (!store) {
+ if (sc_status != kSCStatusOK) {
+ _SCErrorSet(sc_status);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Boolean
+SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+{
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+ kern_return_t status;
+ CFDataRef utfKey; /* serialized key */
+ xmlData_t myKeyRef;
+ CFIndex myKeyLen;
+ CFDataRef xmlData; /* serialized data */
+ xmlData_t myDataRef;
+ CFIndex myDataLen;
+ int newInstance;
+ int sc_status;
+
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(xmlData);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configadd(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue configadd(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * October 17, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCDynamicStoreInternal.h"
-#include "config.h" /* MiG generated file */
-
-Boolean
-SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- kern_return_t status;
- CFDataRef utfKey; /* serialized key */
- xmlData_t myKeyRef;
- CFIndex myKeyLen;
- CFDataRef xmlData; /* serialized data */
- xmlData_t myDataRef;
- CFIndex myDataLen;
- int newInstance;
- int sc_status;
-
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value);
- }
-
- if (!store) {
- /* sorry, you must provide a session */
- _SCErrorSet(kSCStatusNoStoreSession);
- return FALSE;
- }
-
- if (storePrivate->server == MACH_PORT_NULL) {
- /* sorry, you must have an open session to play */
- _SCErrorSet(kSCStatusNoStoreServer);
- return FALSE;
- }
-
- /* serialize the key */
- if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
- }
-
- /* serialize the data */
- if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) {
- CFRelease(utfKey);
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
- }
-
- /* send the key & data to the server */
- status = configadd_s(storePrivate->server,
- myKeyRef,
- myKeyLen,
- myDataRef,
- myDataLen,
- &newInstance,
- (int *)&sc_status);
-
- /* clean up */
- CFRelease(utfKey);
- CFRelease(xmlData);
-
- if (status != KERN_SUCCESS) {
- if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configadd_s(): %s"), mach_error_string(status));
- (void) mach_port_destroy(mach_task_self(), storePrivate->server);
- storePrivate->server = MACH_PORT_NULL;
- _SCErrorSet(status);
- return FALSE;
- }
-
- if (sc_status != kSCStatusOK) {
- _SCErrorSet(sc_status);
- return FALSE;
- }
-
- return TRUE;
-}
#endif
-const CFStringRef kSCConsoleSessionID = CFSTR("kCGSSessionIDKey"); /* value is CFNumber */
-const CFStringRef kSCConsoleSessionUserName = CFSTR("kCGSSessionUserNameKey"); /* value is CFString */
-const CFStringRef kSCConsoleSessionUID = CFSTR("kCGSSessionUserIDKey"); /* value is CFNumber */
-const CFStringRef kSCConsoleSessionConsoleSet = CFSTR("kCGSSessionConsoleSetKey"); /* value is CFNumber */
-const CFStringRef kSCConsoleSessionOnConsole = CFSTR("kCGSSessionOnConsoleKey"); /* value is CFBoolean */
+// from CoreGraphics (CGSession.h)
+const CFStringRef kSCConsoleSessionUserName = CFSTR("kCGSSessionUserNameKey"); /* value is CFString */
+const CFStringRef kSCConsoleSessionUID = CFSTR("kCGSSessionUserIDKey"); /* value is CFNumber (a uid_t) */
+const CFStringRef kSCConsoleSessionConsoleSet = CFSTR("kCGSSessionConsoleSetKey"); /* value is CFNumber */
+const CFStringRef kSCConsoleSessionOnConsole = CFSTR("kCGSSessionOnConsoleKey"); /* value is CFBoolean */
+const CFStringRef kSCConsoleSessionLoginDone = CFSTR("kCGSessionLoginDoneKey"); /* value is CFBoolean */
+
+// from CoreGraphics (CGSSession.h)
+const CFStringRef kSCConsoleSessionID = CFSTR("kCGSSessionIDKey"); /* value is CFNumber */
+
+// from loginwindow
+const CFStringRef kSCConsoleSessionSystemSafeBoot = CFSTR("kCGSSessionSystemSafeBoot"); /* value is CFBoolean */
+const CFStringRef kSCConsoleSessionLoginwindowSafeLogin = CFSTR("kCGSSessionLoginwindowSafeLogin"); /* value is CFBoolean */
CFStringRef
CFStringRef key;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyConsoleUser"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return NULL;
}
tempSession = TRUE;
CFStringRef key;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyConsoleUser"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return NULL;
}
tempSession = TRUE;
CFStringRef consoleUser;
CFMutableDictionaryRef dict = NULL;
CFStringRef key = SCDynamicStoreKeyCreateConsoleUser(NULL);
- CFNumberRef num;
Boolean ok = TRUE;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreSetConsoleUser"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return FALSE;
}
tempSession = TRUE;
}
- if (user == NULL) {
- ok = SCDynamicStoreRemoveValue(store, key);
+ if ((user == NULL) && (sessions == NULL)) {
+ (void) SCDynamicStoreRemoveValue(store, key);
goto done;
}
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman);
- CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser);
- CFRelease(consoleUser);
+ if (user != NULL) {
+ CFNumberRef num;
- num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid);
- CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num);
- CFRelease(num);
+ consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman);
+ CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser);
+ CFRelease(consoleUser);
- num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid);
- CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num);
- CFRelease(num);
+ num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid);
+ CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num);
+ CFRelease(num);
+
+ num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid);
+ CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num);
+ CFRelease(num);
+ }
- CFDictionarySetValue(dict, kSCPropUsersConsoleSessionInfo, sessions);
+ if (sessions != NULL) {
+ CFDictionarySetValue(dict, kSCPropUsersConsoleSessionInfo, sessions);
+ }
ok = SCDynamicStoreSetValue(store, key, dict);
Boolean ok = TRUE;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreSetConsoleUser"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return FALSE;
}
tempSession = TRUE;
}
if (user == NULL) {
- ok = SCDynamicStoreRemoveValue(store, key);
+ (void) SCDynamicStoreRemoveValue(store, key);
goto done;
}
CFDictionaryRef expDict = NULL; /* dict (un-serialized / expanded) */
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return NULL;
if (xmlPatterns) CFRelease(xmlPatterns);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configget_m(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple configget_m(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
if (sc_status != kSCStatusOK) {
status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDictRef, xmlDictLen);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple vm_deallocate(): %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
+#endif /* DEBUG */
_SCErrorSet(sc_status);
return NULL;
}
expDict = _SCUnserializeMultiple(dict);
CFRelease(dict);
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), expDict);
-
return expDict;
}
int newInstance;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return NULL;
CFRelease(utfKey);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configget(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue configget(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
if (sc_status != kSCStatusOK) {
status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue vm_deallocate(): %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
+#endif /* DEBUG */
_SCErrorSet(sc_status);
return NULL;
}
return NULL;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), data);
-
return data;
}
/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
SCDynamicStoreCopyComputerName(SCDynamicStoreRef store,
CFStringEncoding *nameEncoding)
{
- CFDictionaryRef dict = NULL;
+ CFDictionaryRef dict;
CFStringRef key;
CFStringRef name = NULL;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyComputerName"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return NULL;
}
tempSession = TRUE;
key = SCDynamicStoreKeyCreateComputerName(NULL);
dict = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
- if (!dict) {
+ if (dict == NULL) {
goto done;
}
if (!isA_CFDictionary(dict)) {
}
name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
- if (!name) {
+ if (name == NULL) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
CFRetain(name);
- if (nameEncoding) {
+ if (nameEncoding != NULL) {
CFNumberRef num;
num = CFDictionaryGetValue(dict,
done :
if (tempSession) CFRelease(store);
- if (dict) CFRelease(dict);
+ if (dict != NULL) CFRelease(dict);
return name;
}
Boolean
-SCPreferencesSetComputerName(SCPreferencesRef session,
+SCPreferencesSetComputerName(SCPreferencesRef prefs,
CFStringRef name,
CFStringEncoding encoding)
{
CFDictionaryRef dict;
- CFMutableDictionaryRef newDict = NULL;
+ CFMutableDictionaryRef newDict;
CFNumberRef num;
- Boolean ok = FALSE;
- CFStringRef path = NULL;
+ Boolean ok;
+ CFStringRef path;
if (!isA_CFString(name)) {
_SCErrorSet(kSCStatusInvalidArgument);
kSCPrefSystem,
kSCCompSystem);
- dict = SCPreferencesPathGetValue(session, path);
- if (dict) {
+ dict = SCPreferencesPathGetValue(prefs, path);
+ if (dict != NULL) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
} else {
newDict = CFDictionaryCreateMutable(NULL,
CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
CFRelease(num);
- ok = SCPreferencesPathSetValue(session, path, newDict);
- if (!ok) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed"));
+ ok = SCPreferencesPathSetValue(prefs, path, newDict);
+
+ CFRelease(path);
+ CFRelease(newDict);
+
+ return ok;
+}
+
+
+#ifndef kSCPropNetHostName
+#define kSCPropNetHostName CFSTR("HostName")
+#endif
+
+
+CFStringRef
+SCPreferencesGetHostName(SCPreferencesRef prefs)
+{
+ CFDictionaryRef dict;
+ CFStringRef name;
+ CFStringRef path;
+
+ path = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("/%@/%@"),
+ kSCPrefSystem,
+ kSCCompSystem);
+ dict = SCPreferencesPathGetValue(prefs, path);
+ CFRelease(path);
+
+ if (!isA_CFDictionary(dict)) {
+ _SCErrorSet(kSCStatusNoKey);
+ return NULL;
}
- if (path) CFRelease(path);
- if (newDict) CFRelease(newDict);
+ name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetHostName));
+ if (name == NULL) {
+ _SCErrorSet(kSCStatusNoKey);
+ return NULL;
+ }
+
+ return name;
+}
+
+
+Boolean
+SCPreferencesSetHostName(SCPreferencesRef prefs,
+ CFStringRef name)
+{
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict;
+ Boolean ok;
+ CFStringRef path;
+
+ if (name != NULL) {
+ CFIndex len;
+
+ if (!isA_CFString(name)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ len = CFStringGetLength(name);
+ if (len == 0) {
+ name = NULL;
+ }
+ }
+
+ path = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("/%@/%@"),
+ kSCPrefSystem,
+ kSCCompSystem);
+
+ dict = SCPreferencesPathGetValue(prefs, path);
+ if (dict != NULL) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ } else {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ if (name != NULL) {
+ CFDictionarySetValue(newDict, kSCPropNetHostName, name);
+ } else {
+ CFDictionaryRemoveValue(newDict, kSCPropNetHostName);
+ }
+
+ if (CFDictionaryGetCount(newDict) > 0) {
+ ok = SCPreferencesPathSetValue(prefs, path, newDict);
+ } else {
+ ok = SCPreferencesPathRemoveValue(prefs, path);
+ }
+
+ CFRelease(path);
+ CFRelease(newDict);
return ok;
}
CFStringRef
SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
{
- CFDictionaryRef dict = NULL;
+ CFDictionaryRef dict;
CFStringRef key;
CFStringRef name = NULL;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyLocalHostName"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return NULL;
}
tempSession = TRUE;
key = SCDynamicStoreKeyCreateHostNames(NULL);
dict = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
- if (!dict) {
+ if (dict == NULL) {
goto done;
}
if (!isA_CFDictionary(dict)) {
}
name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
- if (!name) {
+ if (name == NULL) {
_SCErrorSet(kSCStatusNoKey);
goto done;
}
done :
if (tempSession) CFRelease(store);
- if (dict) CFRelease(dict);
+ if (dict != NULL) CFRelease(dict);
return name;
}
clean = _SC_stringIsValidDNSName(str);
- if (str) CFAllocatorDeallocate(NULL, str);
+ if (str != NULL) CFAllocatorDeallocate(NULL, str);
return clean;
}
Boolean
-SCPreferencesSetLocalHostName(SCPreferencesRef session,
+SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
CFStringRef name)
{
CFDictionaryRef dict;
- CFMutableDictionaryRef newDict = NULL;
- Boolean ok = FALSE;
- CFStringRef path = NULL;
+ CFMutableDictionaryRef newDict;
+ Boolean ok;
+ CFStringRef path;
- if (name) {
+ if (name != NULL) {
CFIndex len;
if (!isA_CFString(name)) {
kSCCompNetwork,
kSCCompHostNames);
- dict = SCPreferencesPathGetValue(session, path);
- if (dict) {
+ dict = SCPreferencesPathGetValue(prefs, path);
+ if (dict != NULL) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
} else {
newDict = CFDictionaryCreateMutable(NULL,
&kCFTypeDictionaryValueCallBacks);
}
- if (name) {
+ if (name != NULL) {
CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
} else {
CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
}
if (CFDictionaryGetCount(newDict) > 0) {
- ok = SCPreferencesPathSetValue(session, path, newDict);
- if (!ok) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed"));
- }
+ ok = SCPreferencesPathSetValue(prefs, path, newDict);
} else {
- ok = SCPreferencesPathRemoveValue(session, path);
- if (!ok) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathRemoveValue() failed"));
- }
+ ok = SCPreferencesPathRemoveValue(prefs, path);
}
- if (path) CFRelease(path);
- if (newDict) CFRelease(newDict);
+ CFRelease(path);
+ CFRelease(newDict);
return ok;
}
int sc_status;
CFArrayRef allKeys;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" pattern = %@"), pattern);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return NULL;
CFRelease(utfPattern);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configlist(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList configlist(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
if (sc_status != kSCStatusOK) {
status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList vm_deallocate(): %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
+#endif /* DEBUG */
_SCErrorSet(sc_status);
return NULL;
}
kern_return_t status;
int sc_status;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreLock:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
status = configlock(storePrivate->server, (int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configlock(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreLock configlock(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
CFIndex myKeyLen;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(utfKey);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyadd(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey notifyadd(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
kern_return_t status;
int sc_status;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCancel:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRunLoopSourceInvalidate(storePrivate->rls);
return TRUE;
case Using_NotifierInformViaCallback :
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" cancel callback runloop source"));
-
- /* remove the run loop source */
- CFRunLoopRemoveSource(storePrivate->callbackRunLoop,
- storePrivate->callbackRunLoopSource,
- kCFRunLoopDefaultMode);
- CFRelease(storePrivate->callbackRunLoopSource);
- storePrivate->callbackRunLoop = NULL;
- storePrivate->callbackRunLoopSource = NULL;
+ /* invalidate and release the run loop source */
+ CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+ CFRelease(storePrivate->callbackRLS);
+ storePrivate->callbackRLS = NULL;
- /* invalidate port */
+ /* invalidate and release the callback mach port */
CFMachPortInvalidate(storePrivate->callbackPort);
CFRelease(storePrivate->callbackPort);
storePrivate->callbackPort = NULL;
storePrivate->notifyStatus = NotifierNotRegistered;
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCancel notifycancel(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
int sc_status;
CFArrayRef allKeys;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return NULL;
(int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifychanges(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys notifychanges(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
if (sc_status != kSCStatusOK) {
status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys vm_deallocate(): %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
+#endif /* DEBUG */
_SCErrorSet(sc_status);
return NULL;
}
if (msgid == MACH_NOTIFY_NO_SENDERS) {
/* the server died, disable additional callbacks */
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" notifier port closed, disabling notifier"));
+#endif /* DEBUG */
} else if (cbFunc == NULL) {
/* there is no (longer) a callback function, disable additional callbacks */
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" no callback function, disabling notifier"));
+#endif /* DEBUG */
} else {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notifiction function"));
+#ifdef DEBUG
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notification function"));
+#endif /* DEBUG */
if ((*cbFunc)(store, cbArg)) {
/*
* callback function returned success.
*/
return;
} else {
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" callback returned error, disabling notifier"));
+#endif /* DEBUG */
}
}
}
#endif /* DEBUG */
- /* remove the run loop source */
- CFRunLoopRemoveSource(storePrivate->callbackRunLoop,
- storePrivate->callbackRunLoopSource,
- kCFRunLoopDefaultMode);
- CFRelease(storePrivate->callbackRunLoopSource);
- storePrivate->callbackRunLoop = NULL;
- storePrivate->callbackRunLoopSource = NULL;
+ /* invalidate the run loop source */
+ CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+ CFRelease(storePrivate->callbackRLS);
+ storePrivate->callbackRLS = NULL;
/* invalidate port */
CFMachPortInvalidate(storePrivate->callbackPort);
, NULL
};
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback mach_port_request_notification(): %s"), mach_error_string(status));
CFMachPortInvalidate(storePrivate->callbackPort);
CFRelease(storePrivate->callbackPort);
_SCErrorSet(status);
return FALSE;
}
+#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback(): why is oldNotify != MACH_PORT_NULL?"));
}
+#endif /* DEBUG */
/* Requesting notification via mach port */
status = notifyviaport(storePrivate->server,
(int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
CFMachPortInvalidate(storePrivate->callbackPort);
CFRelease(storePrivate->callbackPort);
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->notifyStatus = Using_NotifierInformViaCallback;
/* Creating/adding a run loop source for the port */
- storePrivate->callbackArgument = arg;
- storePrivate->callbackFunction = func;
- storePrivate->callbackRunLoop = runLoop;
- storePrivate->callbackRunLoopSource =
- CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
-
- CFRunLoopAddSource(storePrivate->callbackRunLoop,
- storePrivate->callbackRunLoopSource,
- kCFRunLoopDefaultMode);
+ storePrivate->callbackArgument = arg;
+ storePrivate->callbackFunction = func;
+ storePrivate->callbackRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
+ CFRunLoopAddSource(runLoop, storePrivate->callbackRLS, kCFRunLoopDefaultMode);
return TRUE;
}
if (msgid == MACH_NOTIFY_NO_SENDERS) {
/* the server died, disable additional callbacks */
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_INFO, CFSTR(" rlsCallback(), notifier port closed"));
+#endif /* DEBUG */
#ifdef DEBUG
if (port != storePrivate->callbackPort) {
}
#endif /* DEBUG */
- /* remove the run loop source(s) */
- CFRunLoopSourceInvalidate(storePrivate->callbackRunLoopSource);
- CFRelease(storePrivate->callbackRunLoopSource);
- storePrivate->callbackRunLoopSource = NULL;
+ /* invalidate the run loop source(s) */
+ CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+ CFRelease(storePrivate->callbackRLS);
+ storePrivate->callbackRLS = NULL;
/* invalidate port */
CFMachPortInvalidate(storePrivate->callbackPort);
mach_port_t port = CFMachPortGetPort(mp);
// A simple deallocate won't get rid of all the references we've accumulated
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" invalidate = %d"), port);
+#endif /* DEBUG */
(void)mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
}
SCDynamicStoreRef store = (SCDynamicStoreRef)info;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("schedule notifications for mode %@"), mode);
+#endif /* DEBUG */
if (storePrivate->rlsRefs++ == 0) {
CFMachPortContext context = { 0
int sc_status;
kern_return_t status;
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" activate callback runloop source"));
+#endif /* DEBUG */
/* Allocating port (for server response) */
status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
return;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), port);
status = mach_port_insert_right(mach_task_self(),
port,
port,
MACH_MSG_TYPE_MAKE_SEND);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), port);
return;
}
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), port);
return;
}
+#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("rlsSchedule(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule(): why is oldNotify != MACH_PORT_NULL?"));
}
+#endif /* DEBUG */
status = notifyviaport(storePrivate->server, port, 0, (int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), port);
port = MACH_PORT_NULL;
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->callbackPort = CFMachPortCreateWithPort(NULL, port, rlsCallback, &context, NULL);
CFMachPortSetInvalidationCallBack(storePrivate->callbackPort, rlsPortInvalidate);
- storePrivate->callbackRunLoopSource = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
+ storePrivate->callbackRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
}
- if (storePrivate->callbackRunLoopSource) {
- CFRunLoopAddSource(rl, storePrivate->callbackRunLoopSource, mode);
+ if (storePrivate->callbackRLS != NULL) {
+ CFRunLoopAddSource(rl, storePrivate->callbackRLS, mode);
}
return;
SCDynamicStoreRef store = (SCDynamicStoreRef)info;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR("cancel notifications for mode %@"), mode);
+#endif /* DEBUG */
- if (storePrivate->callbackRunLoopSource) {
- CFRunLoopRemoveSource(rl, storePrivate->callbackRunLoopSource, mode);
+ if (storePrivate->callbackRLS != NULL) {
+ CFRunLoopRemoveSource(rl, storePrivate->callbackRLS, mode);
}
if (--storePrivate->rlsRefs == 0) {
int sc_status;
kern_return_t status;
+#ifdef DEBUG
SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" cancel callback runloop source"));
+#endif /* DEBUG */
- if (storePrivate->callbackRunLoopSource) {
- /* remove the run loop source */
- CFRelease(storePrivate->callbackRunLoopSource);
- storePrivate->callbackRunLoopSource = NULL;
+ if (storePrivate->callbackRLS != NULL) {
+ /* invalidate & remove the run loop source */
+ CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+ CFRelease(storePrivate->callbackRLS);
+ storePrivate->callbackRLS = NULL;
}
- if (storePrivate->callbackPort) {
+ if (storePrivate->callbackPort != NULL) {
/* invalidate port */
CFMachPortInvalidate(storePrivate->callbackPort);
CFRelease(storePrivate->callbackPort);
storePrivate->callbackPort = NULL;
}
- if (storePrivate->server) {
+ if (storePrivate->server != MACH_PORT_NULL) {
status = notifycancel(storePrivate->server, (int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_INFO, CFSTR("notifycancel(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("notifycancel(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
return;
SCDynamicStoreRef store = (SCDynamicStoreRef)info;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notifiction function"));
+#ifdef DEBUG
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notification function"));
+#endif /* DEBUG */
changedKeys = SCDynamicStoreCopyNotifiedKeys(store);
- if (!changedKeys) {
- /* something happened to the server */
+ if (changedKeys == NULL) {
+ /* if no changes or something happened to the server */
return;
}
+ if (CFArrayGetCount(changedKeys) == 0) {
+ goto done;
+ }
+
rlsFunction = storePrivate->rlsFunction;
if (NULL != storePrivate->rlsContext.retain) {
context_release(context_info);
}
+ done :
+
CFRelease(changedKeys);
return;
}
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreateRunLoopSource:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return NULL;
return NULL;
}
- if (storePrivate->rls) {
+ if (storePrivate->rls != NULL) {
CFRetain(storePrivate->rls);
} else {
CFRunLoopSourceContext context = { 0 // version
storePrivate->rls = CFRunLoopSourceCreate(allocator, order, &context);
}
- if (!storePrivate->rls) {
+ if (storePrivate->rls == NULL) {
_SCErrorSet(kSCStatusFailed);
return NULL;
}
struct sockaddr_un un;
int sock;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyFileDescriptor:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_NOTICE, CFSTR("socket: %s"), strerror(errno));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor socket(): %s"), strerror(errno));
return FALSE;
}
if (bind(sock, (struct sockaddr *)&un, sizeof(un)) == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_NOTICE, CFSTR("bind: %s"), strerror(errno));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor bind(): %s"), strerror(errno));
(void) close(sock);
return FALSE;
}
if (listen(sock, 0) == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_NOTICE, CFSTR("listen: %s"), strerror(errno));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor listen(): %s"), strerror(errno));
(void) close(sock);
return FALSE;
}
(int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviafd(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyFileDescriptor notifyviafd(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
*fd = accept(sock, 0, 0);
if (*fd == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_NOTICE, CFSTR("accept: %s"), strerror(errno));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor accept(): %s"), strerror(errno));
(void) close(sock);
return FALSE;
}
mach_port_t oldNotify;
int sc_status;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
/* Allocating port (for server response) */
status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, port);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort mach_port_allocate(): %s"), mach_error_string(status));
_SCErrorSet(status);
return FALSE;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), *port);
status = mach_port_insert_right(mach_task_self(),
*port,
*port,
MACH_MSG_TYPE_MAKE_SEND);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort mach_port_insert_right(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), *port);
*port = MACH_PORT_NULL;
_SCErrorSet(status);
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort mach_port_request_notification(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), *port);
*port = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
+#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): why is oldNotify != MACH_PORT_NULL?"));
}
+#endif /* DEBUG */
status = notifyviaport(storePrivate->server,
*port,
(int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), *port);
*port = MACH_PORT_NULL;
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
int sc_status;
task_t task;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal:"));
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" pid = %d"), pid);
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" sig = %d"), sig);
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
status = task_for_pid(mach_task_self(), pid, &task);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_for_pid(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal task_for_pid(): %s"), mach_error_string(status));
_SCErrorSet(status);
return FALSE;
}
status = notifyviasignal(storePrivate->server, task, sig, (int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviasignal(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal notifyviasignal(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
CFIndex myKeyLen;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(utfKey);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyremove(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey notifyremove(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
CFIndex myPatternsLen = 0;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
if (xmlPatterns) CFRelease(xmlPatterns);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyset(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys notifyset(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
status = vm_allocate(mach_task_self(), (vm_address_t *)&buf, size, TRUE);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("waitForMachMessage vm_allocate(): %s"), mach_error_string(status));
return -1;
}
MACH_MSG_TIMEOUT_NONE, /* timeout */
MACH_PORT_NULL); /* notify */
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_msg(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("waitForMachMessage mach_msg(): %s"), mach_error_string(status));
return -1;
}
int sc_status;
mach_msg_id_t msgid;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
/* Allocating port (for server response) */
status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait mach_port_allocate(): %s"), mach_error_string(status));
_SCErrorSet(status);
return FALSE;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" port = %d"), port);
status = mach_port_insert_right(mach_task_self(),
port,
port,
MACH_MSG_TYPE_MAKE_SEND);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait mach_port_insert_right(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), port);
_SCErrorSet(status);
return FALSE;
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait mach_port_request_notification(): %s"), mach_error_string(status));
(void) mach_port_destroy(mach_task_self(), port);
_SCErrorSet(status);
return FALSE;
}
+#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait(): why is oldNotify != MACH_PORT_NULL?"));
}
+#endif /* DEBUG */
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Requesting notification via mach port %d"), port);
status = notifyviaport(storePrivate->server,
port,
0,
(int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
/* set notifier active */
storePrivate->notifyStatus = Using_NotifierWait;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Waiting..."));
-
msgid = waitForMachMessage(port);
/* set notifier inactive */
if (msgid == MACH_NOTIFY_NO_SENDERS) {
/* the server closed the notifier port */
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" notifier port closed, destroying port %d"), port);
+#ifdef DEBUG
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait notifier port closed, destroying port %d"), port);
+#endif /* DEBUG */
_SCErrorSet(kSCStatusNoStoreServer);
return FALSE;
}
if (msgid == -1) {
/* one of the mach routines returned an error */
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" communication with server failed, destroying port %d"), port);
+#ifdef DEBUG
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait communication with server failed, destroying port %d"), port);
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), port);
_SCErrorSet(kSCStatusNoStoreServer);
return FALSE;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Something changed, cancelling notification request"));
+ // something changed, cancelling notification request
status = notifycancel(storePrivate->server,
(int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait notifycancel(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
CFIndex myKeyLen;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(utfKey);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("confignotify(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue confignotify(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*/
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include "SCDynamicStoreInternal.h"
#include "config.h" /* MiG generated file */
+
+static int _sc_active = 0;
+static CFStringRef _sc_bundleID = NULL;
+static pthread_mutex_t _sc_lock = PTHREAD_MUTEX_INITIALIZER;
+static mach_port_t _sc_server = MACH_PORT_NULL;
+
+
static CFStringRef
__SCDynamicStoreCopyDescription(CFTypeRef cf) {
- CFAllocatorRef allocator = CFGetAllocator(cf);
- CFMutableStringRef result;
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)cf;
result = CFStringCreateMutable(allocator, 0);
- CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf, allocator);
- CFStringAppendFormat(result, NULL, CFSTR("}"));
+ CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> { "), cf, allocator);
+ if (storePrivate->server != MACH_PORT_NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR("server port=%d"), storePrivate->server);
+ } else {
+ CFStringAppendFormat(result, NULL, CFSTR("server not (no longer) available"));
+ }
+ if (storePrivate->locked) {
+ CFStringAppendFormat(result, NULL, CFSTR(", locked"));
+ }
+ switch (storePrivate->notifyStatus) {
+ case Using_NotifierWait :
+ CFStringAppendFormat(result, NULL, CFSTR(", waiting for a notification"));
+ break;
+ case Using_NotifierInformViaMachPort :
+ CFStringAppendFormat(result, NULL, CFSTR(", mach port notifications"));
+ break;
+ case Using_NotifierInformViaFD :
+ CFStringAppendFormat(result, NULL, CFSTR(", FD notifications"));
+ break;
+ case Using_NotifierInformViaSignal :
+ CFStringAppendFormat(result, NULL, CFSTR(", BSD signal notifications"));
+ break;
+ case Using_NotifierInformViaRunLoop :
+ case Using_NotifierInformViaCallback :
+ if (storePrivate->notifyStatus == Using_NotifierInformViaRunLoop) {
+ CFStringAppendFormat(result, NULL, CFSTR(", runloop notifications"));
+ CFStringAppendFormat(result, NULL, CFSTR(" (func=0x%8.8x"), storePrivate->rlsFunction);
+ CFStringAppendFormat(result, NULL, CFSTR(", info=0x%8.8x"), storePrivate->rlsContext.info);
+ CFStringAppendFormat(result, NULL, CFSTR(", rls=0x%8.8x" ), storePrivate->rls);
+ CFStringAppendFormat(result, NULL, CFSTR(", refs=%d" ), storePrivate->rlsRefs);
+ } else {
+ CFStringAppendFormat(result, NULL, CFSTR(", mach port/callback notifications"));
+ CFStringAppendFormat(result, NULL, CFSTR(" (func=0x%8.8x"), storePrivate->callbackFunction);
+ CFStringAppendFormat(result, NULL, CFSTR(", info=0x%8.8x"), storePrivate->callbackArgument);
+ }
+ if (storePrivate->callbackRLS != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", notify rls=%@" ), storePrivate->callbackRLS);
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(")"));
+ break;
+ default :
+ CFStringAppendFormat(result, NULL, CFSTR(", notification delivery not requested%s"),
+ storePrivate->rlsFunction ? " (yet)" : "");
+ break;
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
return result;
}
SCDynamicStoreRef store = (SCDynamicStoreRef)cf;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate:"));
-
(void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState);
/* Remove/cancel any outstanding notification requests. */
(void) SCDynamicStoreNotifyCancel(store);
- if (storePrivate->server && storePrivate->locked) {
+ if ((storePrivate->server != MACH_PORT_NULL) && storePrivate->locked) {
(void) SCDynamicStoreUnlock(store); /* release the lock */
}
if (storePrivate->server != MACH_PORT_NULL) {
status = configclose(storePrivate->server, (int *)&sc_status);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate configclose(): %s"), mach_error_string(status));
}
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
pthread_testcancel();
/* release any callback context info */
- if (storePrivate->rlsContext.release) {
- storePrivate->rlsContext.release(storePrivate->rlsContext.info);
+ if (storePrivate->rlsContext.release != NULL) {
+ (*storePrivate->rlsContext.release)(storePrivate->rlsContext.info);
}
/* release any keys being watched */
CFRelease(storePrivate->keys);
CFRelease(storePrivate->patterns);
+ /* cleanup */
+ pthread_mutex_lock(&_sc_lock);
+ _sc_active--; /* drop the number of active dynamic store sessions */
+ if ((_sc_active == 0) && (_sc_server != MACH_PORT_NULL)) {
+ /* release the [last] reference to the server */
+ (void)mach_port_deallocate(mach_task_self(), _sc_server);
+ _sc_server = MACH_PORT_NULL;
+ }
+ pthread_mutex_unlock(&_sc_lock);
+
return;
}
};
+static void
+childForkHandler()
+{
+ /* the process has forked (and we are the child process) */
+
+ _sc_active = 0;
+ _sc_server = MACH_PORT_NULL;
+
+ return;
+}
+
+
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
static void
__SCDynamicStoreInitialize(void) {
+ CFBundleRef bundle;
+
+ /* register with CoreFoundation */
__kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass);
+
+ /* add handler to cleanup after fork() */
+ (void) pthread_atfork(NULL, NULL, childForkHandler);
+
+ /* get the application/executable/bundle name */
+ bundle = CFBundleGetMainBundle();
+ if (bundle != NULL) {
+ _sc_bundleID = CFBundleGetIdentifier(bundle);
+ if (_sc_bundleID != NULL) {
+ CFRetain(_sc_bundleID);
+ } else {
+ CFURLRef url;
+
+ url = CFBundleCopyExecutableURL(bundle);
+ if (url != NULL) {
+ _sc_bundleID = CFURLCopyPath(url);
+ CFRelease(url);
+ }
+ }
+
+ if (_sc_bundleID != NULL) {
+ if (CFEqual(_sc_bundleID, CFSTR("/"))) {
+ CFRelease(_sc_bundleID);
+ _sc_bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%d)"), getpid());
+ }
+ }
+ }
+
return;
}
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context)
{
+ int sc_status = kSCStatusOK;
uint32_t size;
SCDynamicStorePrivateRef storePrivate;
__kSCDynamicStoreTypeID,
size,
NULL);
- if (!storePrivate) {
+ if (storePrivate == NULL) {
+ _SCErrorSet(kSCStatusFailed);
return NULL;
}
/* server side of the "configd" session */
- storePrivate->server = MACH_PORT_NULL;
+ storePrivate->server = MACH_PORT_NULL;
/* flags */
- storePrivate->locked = FALSE;
+ storePrivate->locked = FALSE;
+ storePrivate->useSessionKeys = FALSE;
/* Notification status */
storePrivate->notifyStatus = NotifierNotRegistered;
storePrivate->rlsContext.copyDescription = NULL;
if (context) {
bcopy(context, &storePrivate->rlsContext, sizeof(SCDynamicStoreContext));
- if (context->retain) {
- storePrivate->rlsContext.info = (void *)context->retain(context->info);
+ if (context->retain != NULL) {
+ storePrivate->rlsContext.info = (void *)(*context->retain)(context->info);
}
}
storePrivate->callbackFunction = NULL;
storePrivate->callbackArgument = NULL;
storePrivate->callbackPort = NULL;
- storePrivate->callbackRunLoop = NULL;
- storePrivate->callbackRunLoopSource = NULL;
+ storePrivate->callbackRLS = NULL;
/* "server" information associated with SCDynamicStoreSetNotificationKeys() */
storePrivate->keys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
storePrivate->notifySignal = 0;
storePrivate->notifySignalTask = TASK_NULL;
+ /* initialize global state */
+
+ pthread_mutex_lock(&_sc_lock);
+
+ /* get the server port */
+ if (_sc_server == MACH_PORT_NULL) {
+ char *server_name;
+ kern_return_t status;
+
+ server_name = getenv("SCD_SERVER");
+ if (!server_name) {
+ server_name = SCD_SERVER;
+ }
+
+ status = bootstrap_look_up(bootstrap_port, server_name, &_sc_server);
+ switch (status) {
+ case BOOTSTRAP_SUCCESS :
+ /* service currently registered, "a good thing" (tm) */
+ break;
+ case BOOTSTRAP_UNKNOWN_SERVICE :
+ /* service not currently registered, try again later */
+ sc_status = status;
+ goto done;
+ default :
+#ifdef DEBUG
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate[WithOptions] bootstrap_look_up() failed: status=%d"), status);
+#endif /* DEBUG */
+ sc_status = status;
+ goto done;
+ }
+ }
+
+ /* bump the number of active dynamic store sessions */
+ _sc_active++;
+
+ done :
+
+ pthread_mutex_unlock(&_sc_lock);
+
+ if (sc_status != kSCStatusOK) {
+ _SCErrorSet(sc_status);
+ CFRelease(storePrivate);
+ storePrivate = NULL;
+ }
+
return storePrivate;
}
+const CFStringRef kSCDynamicStoreUseSessionKeys = CFSTR("UseSessionKeys"); /* CFBoolean */
+
+
SCDynamicStoreRef
-SCDynamicStoreCreate(CFAllocatorRef allocator,
- CFStringRef name,
- SCDynamicStoreCallBack callout,
- SCDynamicStoreContext *context)
+SCDynamicStoreCreateWithOptions(CFAllocatorRef allocator,
+ CFStringRef name,
+ CFDictionaryRef storeOptions,
+ SCDynamicStoreCallBack callout,
+ SCDynamicStoreContext *context)
{
SCDynamicStorePrivateRef storePrivate;
kern_return_t status;
- mach_port_t bootstrap_port;
- CFBundleRef bundle;
- CFStringRef bundleID = NULL;
- mach_port_t server;
- char *server_name;
CFDataRef utfName; /* serialized name */
xmlData_t myNameRef;
CFIndex myNameLen;
- int sc_status;
-
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name);
- }
+ CFDataRef xmlOptions = NULL; /* serialized options */
+ xmlData_t myOptionsRef = NULL;
+ CFIndex myOptionsLen = 0;
+ int sc_status = kSCStatusFailed;
/*
* allocate and initialize a new session
*/
storePrivate = __SCDynamicStoreCreatePrivate(allocator, name, callout, context);
-
- status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
- if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
- CFRelease(storePrivate);
- _SCErrorSet(status);
+ if (storePrivate == NULL) {
return NULL;
}
- server_name = getenv("SCD_SERVER");
- if (!server_name) {
- server_name = SCD_SERVER;
- }
-
- status = bootstrap_look_up(bootstrap_port, server_name, &server);
- switch (status) {
- case BOOTSTRAP_SUCCESS :
- /* service currently registered, "a good thing" (tm) */
- break;
- case BOOTSTRAP_UNKNOWN_SERVICE :
- /* service not currently registered, try again later */
- CFRelease(storePrivate);
- _SCErrorSet(status);
- return NULL;
- break;
- default :
-#ifdef DEBUG
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_look_up() failed: status=%d"), status);
-#endif /* DEBUG */
- CFRelease(storePrivate);
- _SCErrorSet(status);
- return NULL;
- }
-
- /* serialize the name */
- bundle = CFBundleGetMainBundle();
- if (bundle) {
- bundleID = CFBundleGetIdentifier(bundle);
- if (bundleID) {
- CFRetain(bundleID);
- } else {
- CFURLRef url;
-
- url = CFBundleCopyExecutableURL(bundle);
- if (url) {
- bundleID = CFURLCopyPath(url);
- CFRelease(url);
- }
- }
- }
-
- if (bundleID) {
+ if (_sc_bundleID != NULL) {
CFStringRef fullName;
- if (CFEqual(bundleID, CFSTR("/"))) {
- CFRelease(bundleID);
- bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%d)"), getpid());
- }
-
- fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), bundleID, name);
+ fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), _sc_bundleID, name);
name = fullName;
- CFRelease(bundleID);
} else {
CFRetain(name);
}
if (!_SCSerializeString(name, &utfName, (void **)&myNameRef, &myNameLen)) {
CFRelease(name);
- _SCErrorSet(kSCStatusFailed);
- return NULL;
+ goto done;
}
CFRelease(name);
+ /* serialize the options */
+ if (storeOptions) {
+ if (!_SCSerialize(storeOptions, &xmlOptions, (void **)&myOptionsRef, &myOptionsLen)) {
+ CFRelease(utfName);
+ goto done;
+ }
+ }
+
/* open a new session with the server */
- status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status);
+ status = configopen(_sc_server,
+ myNameRef,
+ myNameLen,
+ myOptionsRef,
+ myOptionsLen,
+ &storePrivate->server,
+ (int *)&sc_status);
/* clean up */
CFRelease(utfName);
+ if (xmlOptions) CFRelease(xmlOptions);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status));
- CFRelease(storePrivate);
- _SCErrorSet(status);
- return NULL;
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate[WithOptions] configopen(): %s"), mach_error_string(status));
+#endif /* DEBUG */
+ sc_status = status;
+ goto done;
}
+ done :
+
if (sc_status != kSCStatusOK) {
- CFRelease(storePrivate);
_SCErrorSet(sc_status);
- return NULL;
+ CFRelease(storePrivate);
+ storePrivate = NULL;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" server port = %d"), storePrivate->server);
return (SCDynamicStoreRef)storePrivate;
}
+SCDynamicStoreRef
+SCDynamicStoreCreate(CFAllocatorRef allocator,
+ CFStringRef name,
+ SCDynamicStoreCallBack callout,
+ SCDynamicStoreContext *context)
+{
+ return SCDynamicStoreCreateWithOptions(allocator, name, NULL, callout, context);
+}
+
+
CFTypeID
SCDynamicStoreGetTypeID(void) {
pthread_once(&initialized, __SCDynamicStoreInitialize); /* initialize runtime */
/*
- * Copyright (c) 2001-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
MACH_PORT_NULL, /* rcv_name */
0, /* timeout */
MACH_PORT_NULL); /* notify */
+ if (status == MACH_SEND_TIMED_OUT) {
+ mach_msg_destroy(&msg.header);
+ }
return;
}
case 0 : { /* if child */
- uid_t curUID = geteuid();
- gid_t curGID = getegid();
int i;
int status;
- if (curUID != uid) {
- (void) setuid(uid);
- }
-
- if (curGID != gid) {
- (void) setgid(gid);
- }
-
if (setup) {
(setup)(pid, setupContext);
} else {
dup(0);
}
+ if (gid != getegid()) {
+ (void) setgid(gid);
+ }
+
+ if (uid != geteuid()) {
+ (void) setuid(uid);
+ }
+
/* ensure that our PATH environment variable is somewhat reasonable */
if (setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin", 0) == -1) {
printf("setenv() failed: %s\n", strerror(errno));
/*
- @define kSCBundleRequires
+ @defined kSCBundleRequiresKey
*/
-#define kSCBundleRequires CFSTR("Requires")
+#define kSCBundleRequiresKey CFSTR("Requires")
/*
- @define kSCBundleVerbose
+ @defined kSCBundleVerboseKey
*/
-#define kSCBundleVerbose CFSTR("Verbose")
+#define kSCBundleVerboseKey CFSTR("Verbose")
+
+
+/*
+ @defined kSCBundleIsBuiltinKey
+ */
+#define kSCBundleIsBuiltinKey CFSTR("Builtin")
/*!
initialize any variables, open any sessions with "configd",
and register any needed notifications.
@param bundle The CFBundle being loaded.
- @param verbose A boolean value indicating whether verbose logging has
+ @param bundleVerbose A boolean value indicating whether verbose logging has
been enabled for this bundle.
*/
typedef void (*SCDynamicStoreBundleLoadFunction) (CFBundleRef bundle,
typedef void (*SCDynamicStoreBundlePrimeFunction) ();
+/*!
+ @typedef SCDynamicStoreBundleStopFunction
+ @discussion Type of the stop() termination function that will be
+ called when configd has been requested to shut down.
+ @param stopRls A run loop source which should be signaled using
+ CFRunLoopSourceSignal() when the plugin has been shut down.
+
+ Note: a plugin can delay shut down of the daemon by no more than
+ 30 seconds.
+ */
+typedef void (*SCDynamicStoreBundleStopFunction) (CFRunLoopSourceRef stopRls);
+
+
/*!
@typedef SCDPluginExecCallBack
@discussion Type of the callback function used when a child process
@param context The callback argument specified on the call
to _SCDPluginExecCommand().
*/
-typedef void (*SCDPluginExecCallBack) (pid_t pid,
- int status,
- struct rusage *rusage,
- void *context);
+typedef void (*SCDPluginExecCallBack) (pid_t pid,
+ int status,
+ struct rusage *rusage,
+ void *context);
/*!
@param setupContext The setup argument specified on the call
to _SCDPluginExecCommand2().
*/
-typedef void (*SCDPluginExecSetup) (pid_t pid,
- void *setupContext);
+typedef void (*SCDPluginExecSetup) (pid_t pid,
+ void *setupContext);
__BEGIN_DECLS
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCPrivate.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include <mach/mach.h>
#include <mach/notify.h>
#include <mach/mach_error.h>
0,
&len);
- if (!buf) {
+ if (buf) {
+ /* check the size of the provided buffer */
+ if (bufLen < (len + 1)) {
+ return NULL; /* if too small */
+ }
+ } else {
+ /* allocate a buffer */
bufLen = len + 1;
buf = CFAllocatorAllocate(NULL, bufLen, 0);
if (!buf) {
}
}
- if (len >= bufLen) {
- len = bufLen - 1;
- }
-
(void)CFStringGetBytes(cfstr,
CFRangeMake(0, len),
encoding,
}
+void
+_SC_sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
+{
+ bzero(buf, bufLen);
+ switch (address->sa_family) {
+ case AF_INET :
+ (void)inet_ntop(((struct sockaddr_in *)address)->sin_family,
+ &((struct sockaddr_in *)address)->sin_addr,
+ buf,
+ bufLen);
+ break;
+ case AF_INET6 : {
+ (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family,
+ &((struct sockaddr_in6 *)address)->sin6_addr,
+ buf,
+ bufLen);
+ if (((struct sockaddr_in6 *)address)->sin6_scope_id != 0) {
+ int n;
+
+ n = strlen(buf);
+ if ((n+IF_NAMESIZE+1) <= (int)bufLen) {
+ buf[n++] = '%';
+ if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]);
+ }
+ }
+ break;
+ }
+ case AF_LINK :
+ if (((struct sockaddr_dl *)address)->sdl_len < bufLen) {
+ bufLen = ((struct sockaddr_dl *)address)->sdl_len;
+ } else {
+ bufLen = bufLen - 1;
+ }
+
+ bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen);
+ break;
+ default :
+ snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
+ break;
+ }
+
+ return;
+}
+
+
Boolean
_SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dataLen)
{
CFDataRef myXml;
+ CFWriteStreamRef stream;
if (!xml && !(dataRef && dataLen)) {
/* if not keeping track of allocated space */
return FALSE;
}
- myXml = CFPropertyListCreateXMLData(NULL, obj);
+ stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL);
+ CFWriteStreamOpen(stream);
+ CFPropertyListWriteToStream(obj, stream, kCFPropertyListBinaryFormat_v1_0, NULL);
+ CFWriteStreamClose(stream);
+ myXml = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten);
+ CFRelease(stream);
if (!myXml) {
- SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCSerialize() failed"));
if (xml) *xml = NULL;
if (dataRef) *dataRef = NULL;
if (dataLen) *dataLen = 0;
*dataLen = CFDataGetLength(myXml);
status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE);
if (status != KERN_SUCCESS) {
- SCLog(TRUE,
- LOG_ERR,
- CFSTR("vm_allocate(): %s"),
- mach_error_string(status));
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCSerialize(): %s"), mach_error_string(status));
CFRelease(myXml);
*dataRef = NULL;
*dataLen = 0;
status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserialize(): %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
} else {
if (*obj == NULL) {
if (xmlError) {
- SCLog(TRUE,
- LOG_ERR,
- CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
- xmlError);
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserialize(): %@"), xmlError);
CFRelease(xmlError);
}
_SCErrorSet(kSCStatusFailed);
myData = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
if (!myData) {
- SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateExternalRepresentation() failed"));
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeString() failed"));
if (data) *data = NULL;
if (dataRef) *dataRef = NULL;
if (dataLen) *dataLen = 0;
*dataLen = CFDataGetLength(myData);
status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE);
if (status != KERN_SUCCESS) {
- SCLog(TRUE,
- LOG_ERR,
- CFSTR("vm_allocate(): %s"),
- mach_error_string(status));
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeString(): %s"), mach_error_string(status));
CFRelease(myData);
*dataRef = NULL;
*dataLen = 0;
status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserializeString(): %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
} else {
}
if (*str == NULL) {
- SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateFromExternalRepresentation() failed"));
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserializeString() failed"));
return FALSE;
}
*dataLen = CFDataGetLength(data);
status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE);
if (status != KERN_SUCCESS) {
- SCLog(TRUE,
- LOG_ERR,
- CFSTR("vm_allocate(): %s"),
- mach_error_string(status));
+ SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeData(): %s"), mach_error_string(status));
*dataRef = NULL;
*dataLen = 0;
return FALSE;
*data = CFDataCreate(NULL, dataRef, dataLen);
status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
if (status != KERN_SUCCESS) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserializeData(): %s"), mach_error_string(status));
_SCErrorSet(kSCStatusFailed);
return FALSE;
}
CFDictionaryGetKeysAndValues(dict, keys, values);
for (i = 0; i < nElements; i++) {
- if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, NULL)) {
+ if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, 0)) {
goto done;
}
}
}
+__private_extern__ void
+_SC_signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList)
+{
+ CFRunLoopRef rl = NULL;
+ CFRunLoopRef rl1 = NULL;
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(rlList);
+
+ if (n == 0) {
+ return;
+ }
+
+ /* get first runLoop for this object */
+ for (i = 0; i < n; i += 3) {
+ if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+ continue;
+ }
+
+ rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
+ break;
+ }
+
+ if (!rl1) {
+ /* if not scheduled */
+ return;
+ }
+
+ /* check if we have another runLoop for this object */
+ rl = rl1;
+ for (i = i+3; i < n; i += 3) {
+ CFRunLoopRef rl2;
+
+ if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+ continue;
+ }
+
+ rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
+ if (!CFEqual(rl1, rl2)) {
+ /* we've got more than one runLoop */
+ rl = NULL;
+ break;
+ }
+ }
+
+ if (rl) {
+ /* if we only have one runLoop */
+ CFRunLoopWakeUp(rl);
+ return;
+ }
+
+ /* more than one different runLoop, so we must pick one */
+ for (i = 0; i < n; i+=3) {
+ CFStringRef rlMode;
+
+ if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+ continue;
+ }
+
+ rl = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
+ rlMode = CFRunLoopCopyCurrentMode(rl);
+ if (rlMode && CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode)) {
+ /* we've found a runLoop that's "ready" */
+ CFRelease(rlMode);
+ CFRunLoopWakeUp(rl);
+ return;
+ }
+ if (rlMode) CFRelease(rlMode);
+ }
+
+ /* didn't choose one above, so choose first */
+ CFRunLoopWakeUp(rl1);
+ return;
+}
+
+
+__private_extern__ Boolean
+_SC_isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
+{
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(rlList);
+
+ for (i = 0; i < n; i += 3) {
+ if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+ continue;
+ }
+ if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
+ continue;
+ }
+ if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
+ continue;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+__private_extern__ void
+_SC_schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
+{
+ CFArrayAppendValue(rlList, obj);
+ CFArrayAppendValue(rlList, runLoop);
+ CFArrayAppendValue(rlList, runLoopMode);
+
+ return;
+}
+
+
+__private_extern__ Boolean
+_SC_unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
+{
+ CFIndex i = 0;
+ Boolean found = FALSE;
+ CFIndex n = CFArrayGetCount(rlList);
+
+ while (i < n) {
+ if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+ i += 3;
+ continue;
+ }
+ if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
+ i += 3;
+ continue;
+ }
+ if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
+ i += 3;
+ continue;
+ }
+
+ found = TRUE;
+
+ CFArrayRemoveValueAtIndex(rlList, i + 2);
+ CFArrayRemoveValueAtIndex(rlList, i + 1);
+ CFArrayRemoveValueAtIndex(rlList, i);
+
+ if (!all) {
+ return found;
+ }
+
+ n -= 3;
+ }
+
+ return found;
+}
+
+
void
__showMachPortStatus()
{
CFIndex myKeyLen;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(utfKey);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configremove(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue configremove(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
CFIndex myNotifyLen = 0;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToSet = %@"), keysToSet);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToRemove = %@"), keysToRemove);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToNotify = %@"), keysToNotify);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
- return NULL;
+ return FALSE;
}
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
- return NULL; /* you must have an open session to play */
+ return FALSE; /* you must have an open session to play */
}
/* serialize the key/value pairs to set*/
newInfo = _SCSerializeMultiple(keysToSet);
if (!newInfo) {
_SCErrorSet(kSCStatusFailed);
- return NULL;
+ return FALSE;
}
ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen);
if (!ok) {
_SCErrorSet(kSCStatusFailed);
- return NULL;
+ return FALSE;
}
}
if (!_SCSerialize(keysToRemove, &xmlRemove, (void **)&myRemoveRef, &myRemoveLen)) {
if (xmlSet) CFRelease(xmlSet);
_SCErrorSet(kSCStatusFailed);
- return NULL;
+ return FALSE;
}
}
if (xmlSet) CFRelease(xmlSet);
if (xmlRemove) CFRelease(xmlRemove);
_SCErrorSet(kSCStatusFailed);
- return NULL;
+ return FALSE;
}
}
if (xmlNotify) CFRelease(xmlNotify);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configset_m(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple configset_m(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
int sc_status;
int newInstance;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(xmlData);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configset(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetValue configset(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
kern_return_t status;
int sc_status;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSnapshot:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
status = snapshot(storePrivate->server, (int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("snapshot(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSnapshot snapshot(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
CFIndex myKeyLen;
int sc_status;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
CFRelease(utfKey);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configtouch(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue configtouch(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
kern_return_t status;
int sc_status;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreUnlock:"));
-
- if (!store) {
+ if (store == NULL) {
/* sorry, you must provide a session */
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
/* (attempt to) release the servers lock */
status = configunlock(storePrivate->server, (int *)&sc_status);
if (status != KERN_SUCCESS) {
+#ifdef DEBUG
if (status != MACH_SEND_INVALID_DEST)
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configunlock(): %s"), mach_error_string(status));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreUnlock configunlock(): %s"), mach_error_string(status));
+#endif /* DEBUG */
(void) mach_port_destroy(mach_task_self(), storePrivate->server);
storePrivate->server = MACH_PORT_NULL;
_SCErrorSet(status);
#define _SCDYNAMICSTORE_H
#include <sys/cdefs.h>
-#include <sys/syslog.h>
-#include <mach/message.h>
#include <CoreFoundation/CoreFoundation.h>
-
/*!
@header SCDynamicStore
- The SystemConfiguration framework provides access to the
- data used to configure a running system. The APIs provided
- by this framework communicate with the "configd" daemon.
-
- The "configd" daemon manages a "dynamic store" reflecting the
- desired configuration settings as well as the current state
- of the system. The daemon provides a notification mechanism
- for user-level processes that need to be aware of changes
- made to the data. Lastly, the daemon loads a number of
- bundles (or plug-ins) that monitor low-level kernel events
- and, via a set of policy modules, keep the state data up
- to date.
+ @discussion The SCDynamicStore API provides access to the key-value
+ pairs in the dynamic store of a running system. The dynamic
+ store contains, among other items, a copy of the configuration
+ settings for the currently active set (which is sometimes
+ refered to as the location) and information about the current
+ network state.
+
+ The functions in the SCDynamicStore API allow you to find
+ key-value pairs, add or remove key-value pairs, add or change
+ values, and request notifications.
+
+ To use the functions of the SCDynamicStore API, you must first
+ establish a dynamic store session using the SCDynamicStoreCreate
+ function. When you are finished with the session, use CFRelease
+ to close it.
*/
/*!
@typedef SCDynamicStoreRef
- @discussion This is the handle to an open "dynamic store" session
+ @discussion This is the handle to an open a dynamic store session
with the system configuration daemon.
*/
typedef const struct __SCDynamicStore * SCDynamicStoreRef;
/*!
@typedef SCDynamicStoreContext
+ Structure containing user-specified data and callbacks for an
+ SCDynamicStore session.
+ @field version The version number of the structure type being passed
+ in as a parameter to the SCDynamicStore creation function.
+ This structure is version 0.
+ @field info A C pointer to a user-specified block of data.
+ @field retain The callback used to add a retain for the info field.
+ If this parameter is not a pointer to a function of the correct
+ prototype, the behavior is undefined. The value may be NULL.
+ @field release The calllback used to remove a retain previously added
+ for the info field. If this parameter is not a pointer to a
+ function of the correct prototype, the behavior is undefined.
+ The value may be NULL.
+ @field copyDescription The callback used to provide a description of
+ the info field.
*/
typedef struct {
CFIndex version;
/*!
@typedef SCDynamicStoreCallBack
- @discussion Type of the callback function used when a
- dynamic store change is delivered.
- @param store The "dynamic store" session.
+ @discussion Type of callback function used when notification of
+ changes to the dynamic store is delivered.
+ @param store The dynamic store session.
@param changedKeys The list of changed keys.
- @param info ....
+ @param info A C pointer to a user-specified block of data.
*/
typedef void (*SCDynamicStoreCallBack) (
SCDynamicStoreRef store,
/*!
@function SCDynamicStoreGetTypeID
- Returns the type identifier of all SCDynamicStore instances.
+ @discussion Returns the type identifier of all SCDynamicStore instances.
*/
CFTypeID
SCDynamicStoreGetTypeID (void);
/*!
@function SCDynamicStoreCreate
@discussion Creates a new session used to interact with the dynamic
- store maintained by the SystemConfiguration server.
- @param allocator The CFAllocator which should be used to allocate
- memory for the local "dynamic store" and its storage for
- values.
+ store maintained by the System Configuration server.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for the local dynamic store object.
This parameter may be NULL in which case the current
default CFAllocator is used. If this reference is not
a valid CFAllocator, the behavior is undefined.
@param name A string that describes the name of the calling
process or plug-in of the caller.
@param callout The function to be called when a watched value
- in the "dynamic store" is changed.
+ in the dynamic store is changed.
A NULL value can be specified if no callouts are
desired.
@param context The SCDynamicStoreContext associated with the callout.
- @result A reference to the new SCDynamicStore.
+ @result Returns a reference to the new SCDynamicStore session.
+ You must release the returned value.
*/
SCDynamicStoreRef
SCDynamicStoreCreate (
);
/*!
- @function SCDynamicStoreCreateRunLoopSource
+ @function SCDynamicStoreCreateWithOptions
@discussion Creates a new session used to interact with the dynamic
- store maintained by the SystemConfiguration server.
- @param allocator The CFAllocator which should be used to allocate
- memory for the local "dynamic store" and its storage for
- values.
+ store maintained by the System Configuration server.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for the local dynamic store object.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @param name A string that describes the name of the calling
+ process or plug-in of the caller.
+ @param storeOptions A CFDictionary containing options for the
+ dynamic store session (such as whether all keys added or set
+ into the dynamic store should be per-session keys).
+
+ Currently available options include:
+
+ <TABLE BORDER>
+ <TR>
+ <TH>key</TD>
+ <TH>value</TD>
+ </TR>
+ <TR>
+ <TD>kSCDynamicStoreUseSessionKeys</TD>
+ <TD>CFBooleanRef</TD>
+ </TR>
+ </TABLE>
+
+ A NULL value can be specified if no options are desired.
+ @param callout The function to be called when a watched value
+ in the dynamic store is changed.
+ A NULL value can be specified if no callouts are
+ desired.
+ @param context The SCDynamicStoreContext associated with the callout.
+ @result Returns a reference to the new SCDynamicStore session.
+ You must release the returned value.
+ */
+SCDynamicStoreRef
+SCDynamicStoreCreateWithOptions (
+ CFAllocatorRef allocator,
+ CFStringRef name,
+ CFDictionaryRef storeOptions,
+ SCDynamicStoreCallBack callout,
+ SCDynamicStoreContext *context
+ );
+
+extern const CFStringRef kSCDynamicStoreUseSessionKeys; /* CFBoolean */
+
+/*!
+ @function SCDynamicStoreCreateRunLoopSource
+ @discussion Creates a CFRunLoopSource object that can be added to the
+ application's run loop. All dynamic store notifications are
+ delivered using this run loop source.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this run loop source.
This parameter may be NULL in which case the current
default CFAllocator is used. If this reference is not
a valid CFAllocator, the behavior is undefined.
- @param store The "dynamic store" session.
- @param order On platforms which support it, this parameter
- determines the order in which the sources which are
- ready to be processed are handled. A lower order
- number causes processing before higher order number
- sources. It is inadvisable to depend on the order
- number for any architectural or design aspect of
- code. In the absence of any reason to do otherwise,
+ @param store A reference to the dynamic store session.
+ @param order On platforms which support it, for source versions
+ which support it, this parameter determines the order in
+ which the sources which are ready to be processed are
+ handled. A lower order number causes processing before
+ higher order number sources. It is inadvisable to depend
+ on the order number for any architectural or design aspect
+ of code. In the absence of any reason to do otherwise,
zero should be used.
@result A reference to the new CFRunLoopSource.
You must release the returned value.
/*!
@function SCDynamicStoreCopyKeyList
@discussion Returns an array of CFString keys representing the
- configuration "dynamic store" entries that match a
- specified pattern.
- @param store The "dynamic store" session.
- @param pattern A regex(3) regular expression pattern that
- will be used to match the "dynamic store" keys.
- @result The list of matching keys.
+ current dynamic store entries that match a specified pattern.
+ @param store The dynamic store session.
+ @param pattern A regex(3) regular expression pattern
+ used to match the dynamic store keys.
+ @result Returns the list of matching keys; NULL if an error was
+ encountered.
You must release the returned value.
- A NULL value will be returned if the list could not be obtained.
*/
CFArrayRef
SCDynamicStoreCopyKeyList (
/*!
@function SCDynamicStoreAddValue
- @discussion Adds the key-value pair to the "dynamic store" if no
+ @discussion Adds the key-value pair to the dynamic store if no
such key already exists.
- @param store The "dynamic store" session.
- @param key The key of the value to add to the "dynamic store".
- @param value The value to add to the "dynamic store".
- @result TRUE if the key was added; FALSE if the key was already
- present in the "dynamic store" or if an error was encountered.
+ @param store The dynamic store session.
+ @param key The key of the value to add to the dynamic store.
+ @param value The value to add to the dynamic store.
+ @result Returns TRUE if the key was added; FALSE if the key was already
+ present in the dynamic store or if an error was encountered.
*/
Boolean
SCDynamicStoreAddValue (
/*!
@function SCDynamicStoreAddTemporaryValue
- @discussion Adds the key-value pair on a temporary basis to the
- "dynamic store" if no such key already exists. This entry
- will, unless updated by another session, automatically be
- removed when the session is closed.
- @param store The "dynamic store" session.
- @param key The key of the value to add to the "dynamic store".
- @param value The value to add to the "dynamic store".
- @result TRUE if the key was added; FALSE if the key was already
- present in the "dynamic store" or if an error was encountered.
+ @discussion Temporarily adds the key-value pair to the dynamic store
+ if no such key already exists. Unless the key is updated by another
+ session, the key-value pair will be removed automatically when the
+ session is closed.
+ @param store The dynamic store session.
+ @param key The key of the value to add to the dynamic store.
+ @param value The value to add to the dynamic store.
+ @result Returns TRUE if the key was added; FALSE if the key was already
+ present in the dynamic store or if an error was encountered.
*/
Boolean
SCDynamicStoreAddTemporaryValue (
/*!
@function SCDynamicStoreCopyValue
- @discussion Obtains a value from the "dynamic store" for the
- specified key.
- @param store The "dynamic store" session.
- @param key The key you wish to obtain.
- @result The value from the store that is associated with the
- given key. The value is returned as a Core Foundation
- Property List data type.
+ @discussion Gets the value of the specified key from the dynamic store.
+ @param store The dynamic store session.
+ @param key The key associated with the value you want to get.
+ @result Returns the value from the dynamic store that is associated with the given
+ key; NULL if no value was located or an error was encountered.
You must release the returned value.
- If no value was located, NULL is returned.
*/
CFPropertyListRef
SCDynamicStoreCopyValue (
/*!
@function SCDynamicStoreCopyMultiple
- @discussion Fetches multiple values in the "dynamic store".
- @param store The "dynamic store" session.
- @param keys The keys to be fetched; NULL if no specific keys
- are requested.
- @param patterns The regex(3) pattern strings to be fetched; NULL
+ @discussion Gets the values of multiple keys in the dynamic store.
+ @param store The dynamic store session.
+ @param keys The keys associated with the values you want to get; NULL if no specific
+ keys are requested.
+ @param patterns An array of regex(3) pattern strings used to match the keys; NULL
if no key patterns are requested.
- @result A dictionary containing the specific keys which were found
- in the "dynamic store" and any keys which matched the specified
- patterns; NULL is returned if an error was encountered.
+ @result Returns a dictionary containing the key-value pairs of specific keys and the
+ key-value pairs of keys that matched the specified patterns;
+ NULL if an error was encountered.
You must release the returned value.
*/
CFDictionaryRef
/*!
@function SCDynamicStoreSetValue
- @discussion Adds or replaces a value in the "dynamic store" for
+ @discussion Adds or replaces a value in the dynamic store for
the specified key.
- @param store The "dynamic store" session.
- @param key The key you wish to set.
- @param value The value to add to or replace in the "dynamic store".
- @result TRUE if the key was updated; FALSE if an error was encountered.
+ @param store The dynamic store session.
+ @param key The key you want to set.
+ @param value The value to add to or replace in the dynamic store.
+ @result Returns TRUE if the key was updated; FALSE if an error was encountered.
*/
Boolean
SCDynamicStoreSetValue (
/*!
@function SCDynamicStoreSetMultiple
- @discussion Updates multiple values in the "dynamic store".
- @param store The "dynamic store" session.
- @param keysToSet Key/value pairs you wish to set into the "dynamic store".
- @param keysToRemove A list of keys you wish to remove from the "dynamic store".
- @param keysToNotify A list of keys to flag as changed (without actually changing the data).
- @result TRUE if the dynamic store updates were successful; FALSE if an error was encountered.
+ @discussion Updates multiple values in the dynamic store.
+ @param store The dynamic store session.
+ @param keysToSet A dictionary of key-value pairs you want to set into the dynamic store.
+ @param keysToRemove An array of keys you want to remove from the dynamic store.
+ @param keysToNotify An array of keys to flag as changed (without changing their values).
+ @result Returns TRUE if the dynamic store updates were successful; FALSE if an error was encountered.
*/
Boolean
SCDynamicStoreSetMultiple (
/*!
@function SCDynamicStoreRemoveValue
@discussion Removes the value of the specified key from the
- "dynamic store".
- @param store The "dynamic store" session.
- @param key The key of the value you wish to remove.
- @result TRUE if the key was removed; FALSE if no value was
+ dynamic store.
+ @param store The dynamic store session.
+ @param key The key of the value you want to remove.
+ @result Returns TRUE if the key was removed; FALSE if no value was
located or an error was encountered.
*/
Boolean
@function SCDynamicStoreNotifyValue
@discussion Triggers a notification to be delivered for the
specified key in the dynamic store.
- @param store The "dynamic store" session.
- @param key The key which should be flagged as changed (without actually changing the data).
- @result TRUE if the value was updated; FALSE if an error was encountered.
+ @param store The dynamic store session.
+ @param key The key that should be flagged as changed. Any dynamic store sessions
+ that are monitoring this key will received a notification. Note that the
+ key's value is not updated.
+ @result Returns TRUE if the notification was processed; FALSE if an error was encountered.
*/
Boolean
SCDynamicStoreNotifyValue (
/*!
@function SCDynamicStoreSetNotificationKeys
@discussion Specifies a set of specific keys and key patterns
- which should be monitored for changes.
- @param store The "dynamic store" session being watched.
- @param keys The keys to be monitored; NULL if no specific keys
+ that should be monitored for changes.
+ @param store The dynamic store session being watched.
+ @param keys An array of keys to be monitored; NULL if no specific keys
are to be monitored.
- @param patterns The regex(3) pattern strings to be monitored; NULL
- if no key patterns are to be monitored.
- @result TRUE if the monitored keys were set; FALSE if an error
- was encountered.
+ @param patterns An array of regex(3) pattern strings used to match keys to be monitored;
+ NULL if no key patterns are to be monitored.
+ @result Returns TRUE if the set of notification keys and patterns was successfully
+ updated; FALSE if an error was encountered.
*/
Boolean
SCDynamicStoreSetNotificationKeys (
/*!
@function SCDynamicStoreCopyNotifiedKeys
@discussion Returns an array of CFString keys representing the
- "dynamic store" entries that have changed since this
- function was last called.
- @param store The "dynamic store" session.
- @result The list of changed keys.
+ dynamic store entries that have changed since this
+ function was last called. If possible, your application should
+ use the notification functions instead of polling for the list
+ of changed keys returned by this function.
+ @param store The dynamic store session.
+ @result Returns the list of changed keys;
+ NULL if an error was encountered.
You must release the returned value.
- A NULL value will be returned if the list could not be obtained.
*/
CFArrayRef
SCDynamicStoreCopyNotifiedKeys (
/*!
- @header SCDynamicStoreCopyDHCPInfo.h
- The following APIs allow an application to retrieve DHCP/BOOTP
- information, in particular DHCP/BOOTP options.
+ @header SCDynamicStoreCopyDHCPInfo
+ @discussion The functions of the SCDynamicStoreCopyDHCPInfo API
+ provide access to information returned by the DHCP or
+ BOOTP server.
*/
/*!
@function SCDynamicStoreCopyDHCPInfo
- @discussion Copies the DHCP/BOOTP information dictionary for the
- requested serviceID, or the primary service if
- serviceID == NULL.
- @param store An SCDynamicStoreRef that should be used for communication
- with the server.
+ @discussion Copies the DHCP information for the requested serviceID,
+ or the primary service if serviceID == NULL.
+ @param store An SCDynamicStoreRef representing the dynamic store session
+ that should be used for communication with the server.
If NULL, a temporary session will be used.
@param serviceID A CFStringRef containing the requested service.
If NULL, returns information for the primary service.
- @result A dictionary containing DHCP/BOOTP information if successful,
+ @result Returns a dictionary containing DHCP information if successful;
NULL otherwise.
- Use the DHCPInfoGetOption() to retrieve
+ Use the DHCPInfoGetOption function to retrieve
individual options from the returned dictionary.
A non-NULL return value must be released using CFRelease().
/*!
@function DHCPInfoGetOptionData
- @discussion Returns a non-NULL CFDataRef containing the BOOTP/DHCP
- option data if present, NULL otherwise.
+ @discussion Returns a non-NULL CFDataRef containing the DHCP
+ option data, if present.
@param info The non-NULL DHCP information dictionary returned by
calling SCDynamicStoreCopyDHCPInfo.
- @param code The DHCP/BOOTP option code (see RFC 2132) to return
+ @param code The DHCP option code (see RFC 2132) to return
data for.
- @result A non-NULL CFDataRef containing the option data,
- NULL otherwise.
+ @result Returns a non-NULL CFDataRef containing the option data;
+ NULL if the requested option data is not present.
The return value must NOT be released.
*/
/*!
@function DHCPInfoGetLeaseStartTime
@discussion Returns a CFDateRef corresponding to the lease start time,
- if present, NULL otherwise. A NULL return value is returned
- if the configuration method is BOOTP.
+ if present.
@param info The non-NULL DHCP information dictionary returned by
calling SCDynamicStoreCopyDHCPInfo.
- @result A non-NULL CFDateRef if present, NULL otherwise.
+ @result Returns a non-NULL CFDateRef if lease start time information is
+ present; NULL if the information is not present or if the
+ configuration method is not DHCP.
The return value must NOT be released.
*/
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define _SCDYNAMICSTORECOPYSPECIFIC_H
#include <sys/cdefs.h>
+#include <sys/types.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCDynamicStore.h>
/*!
@header SCDynamicStoreCopySpecific
- The following APIs allow an application to determine specific
- configuration information about the current system (e.g. the
- computer/sharing name, the currently logged in user, etc).
+ @discussion The functions of the SCDynamicStoreCopySpecific API
+ allow an application to determine specific configuration
+ information about the current system (for example, the
+ computer or sharing name, the currently logged-in user, etc.).
*/
/*!
@function SCDynamicStoreCopyComputerName
- @discussion Gets the current computer/host name.
- @param store An SCDynamicStoreRef that should be used for communication
- with the server.
+ @discussion Gets the current computer name.
+ @param store An SCDynamicStoreRef representing the dynamic store
+ session that should be used for communication with the server.
If NULL, a temporary session will be used.
@param nameEncoding A pointer to memory that, if non-NULL, will be
- filled with the encoding associated with the computer/host name.
- @result The current computer/host name;
+ filled with the encoding associated with the computer or
+ host name.
+ @result Returns the current computer name;
NULL if the name has not been set or if an error was encountered.
You must release the returned value.
*/
/*!
@function SCDynamicStoreCopyConsoleUser
@discussion Gets the name, user ID, and group ID of the currently
- logged in user.
- @param store An SCDynamicStoreRef that should be used for communication
- with the server.
+ logged-in user.
+
+ Note: this function only provides information about the
+ primary console. It does not provide any details
+ about console sessions that have fast user switched
+ out or about other consoles.
+ @param store An SCDynamicStoreRef representing the dynamic store
+ session that should be used for communication with the server.
If NULL, a temporary session will be used.
@param uid A pointer to memory that will be filled with the user ID
- of the current "Console" user. If NULL, this value will not
+ of the current console user. If NULL, this value will not
be returned.
@param gid A pointer to memory that will be filled with the group ID
- of the current "Console" user. If NULL, this value will not be
+ of the current console user. If NULL, this value will not be
returned.
- @result The current user logged into the system;
+ @result Returns the user currently logged into the system;
NULL if no user is logged in or if an error was encountered.
You must release the returned value.
*/
/*!
@function SCDynamicStoreCopyLocalHostName
@discussion Gets the current local host name.
-
- See SCDynamicStoreKeyCreateHostNames() for notification
- key information.
- @param store An SCDynamicStoreRef that should be used for communication
- with the server.
+ @param store An SCDynamicStoreRef representing the dynamic store
+ session that should be used for communication with the server.
If NULL, a temporary session will be used.
- @result The current local host name;
+ @result Returns the current local host name;
NULL if the name has not been set or if an error was encountered.
You must release the returned value.
*/
/*!
@function SCDynamicStoreCopyLocation
- @discussion Gets the current "location" identifier.
- @param store An SCDynamicStoreRef that should be used for communication
- with the server.
+ @discussion Gets the current location identifier.
+ @param store An SCDynamicStoreRef representing the dynamic store
+ session that should be used for communication with the server.
If NULL, a temporary session will be used.
- @result A string representing the current "location" identifier;
- NULL if no "location" identifier has been defined or if an error
+ @result Returns a string representing the current location identifier;
+ NULL if no location identifier has been defined or if an error
was encountered.
You must release the returned value.
*/
/*!
@function SCDynamicStoreCopyProxies
@discussion Gets the current internet proxy settings.
- @param store An SCDynamicStoreRef that should be used for communication
- with the server.
+ The returned proxy settings dictionary includes:
+
+ <TABLE BORDER>
+ <TR>
+ <TH>key</TD>
+ <TH>type</TD>
+ <TH>description</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesExceptionsList</TD>
+ <TD>CFArray[CFString]</TD>
+ <TD>Host name patterns which should bypass the proxy</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesHTTPEnable</TD>
+ <TD>CFNumber (0 or 1)</TD>
+ <TD>Enables/disables the use of an HTTP proxy</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesHTTPProxy</TD>
+ <TD>CFString</TD>
+ <TD>The proxy host</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesHTTPPort</TD>
+ <TD>CFNumber</TD>
+ <TD>The proxy port number</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesHTTPSEnable</TD>
+ <TD>CFNumber (0 or 1)</TD>
+ <TD>Enables/disables the use of an HTTPS proxy</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesHTTPSProxy</TD>
+ <TD>CFString</TD>
+ <TD>The proxy host</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesHTTPSPort</TD>
+ <TD>CFNumber</TD>
+ <TD>The proxy port number</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesFTPEnable</TD>
+ <TD>CFNumber (0 or 1)</TD>
+ <TD>Enables/disables the use of an FTP proxy</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesFTPProxy</TD>
+ <TD>CFString</TD>
+ <TD>The proxy host</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesFTPPort</TD>
+ <TD>CFNumber</TD>
+ <TD>The proxy port number</TD>
+ </TR>
+ <TR>
+ <TD>kSCPropNetProxiesFTPPassive</TD>
+ <TD>CFNumber (0 or 1)</TD>
+ <TD>Enable passive mode operation for use behind connection
+ filter-ing firewalls.</TD>
+ </TR>
+ </TABLE>
+
+ Other key-value pairs are defined in the SCSchemaDefinitions.h
+ header file.
+ @param store An SCDynamicStoreRef representing the dynamic store
+ session that should be used for communication with the server.
If NULL, a temporary session will be used.
- @result A dictionary with key/value pairs representing the current
- internet proxy settings (HTTP, FTP, etc);
- NULL if no proxy settings have been defined or if an error was encountered.
+ @result Returns a dictionary containing key-value pairs that represent
+ the current internet proxy settings;
+ NULL if no proxy settings have been defined or if an error
+ was encountered.
You must release the returned value.
*/
CFDictionaryRef
/*!
- @header SCDynamicStoreCopySpecificPrivate.h
- The following APIs allow an application to retrieve console
- information.
+ @header SCDynamicStoreCopySpecificPrivate
+ @discussion The following APIs allow an application to retrieve
+ console information.
*/
/*
* Predefined keys for the console session dictionaries
*/
-extern const CFStringRef kSCConsoleSessionID; /* value is CFNumber */
-extern const CFStringRef kSCConsoleSessionUserName; /* value is CFString */
-extern const CFStringRef kSCConsoleSessionUID; /* value is CFNumber */
-extern const CFStringRef kSCConsoleSessionConsoleSet; /* value is CFNumber */
-extern const CFStringRef kSCConsoleSessionOnConsole; /* value is CFBoolean */
+extern const CFStringRef kSCConsoleSessionID; /* value is CFNumber */
+extern const CFStringRef kSCConsoleSessionUserName; /* value is CFString */
+extern const CFStringRef kSCConsoleSessionUID; /* value is CFNumber (a uid_t) */
+extern const CFStringRef kSCConsoleSessionConsoleSet; /* value is CFNumber */
+extern const CFStringRef kSCConsoleSessionOnConsole; /* value is CFBoolean */
+extern const CFStringRef kSCConsoleSessionLoginDone; /* value is CFBoolean */
+extern const CFStringRef kSCConsoleSessionSystemSafeBoot; /* value is CFBoolean */
+extern const CFStringRef kSCConsoleSessionLoginwindowSafeLogin; /* value is CFBoolean */
/*!
@function SCDynamicStoreCopyConsoleInformation
/* per-session flags */
Boolean locked;
-
- /* SCDynamicStoreKeys being watched */
- CFMutableSetRef keys;
- CFMutableSetRef patterns;
+ Boolean useSessionKeys;
/* current status of notification requests */
__SCDynamicStoreNotificationStatus notifyStatus;
SCDynamicStoreCallBack_v1 callbackFunction;
void *callbackArgument;
CFMachPortRef callbackPort;
- CFRunLoopRef callbackRunLoop;
- CFRunLoopSourceRef callbackRunLoopSource;
+ CFRunLoopSourceRef callbackRLS;
+
+ /* "server" SCDynamicStoreKeys being watched */
+ CFMutableSetRef keys;
+ CFMutableSetRef patterns;
/* "server" information associated with SCDynamicStoreNotifyMachPort() */
mach_port_t notifyPort;
/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*!
@header SCDynamicStoreKey
+ @discussion The SCDynamicStoreKey API provides convenience functions
+ that an application can use to create a correctly formatted
+ dynamic store key for accessing specific items in the dynamic
+ store. An application can then use the resulting string in
+ any function that requires a dynamic store key.
*/
__BEGIN_DECLS
/*
- * SCDynamicStoreKeyCreate*
+ * SCDynamicStoreKeyCreate
* - convenience routines that create a CFString key for an item in the store
*/
/*!
@function SCDynamicStoreKeyCreate
- @discussion Creates a store key using the given format.
+ @discussion Creates a dynamic store key using the given format.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @param fmt A CFStringRef describing the format for this key.
+ @result Returns a string containing the formatted key.
*/
CFStringRef
SCDynamicStoreKeyCreate (
/*!
@function SCDynamicStoreKeyCreateNetworkGlobalEntity
+ @discussion Creates a dynamic store key that can be used to access
+ a specific global (as opposed to a per-service or per-interface)
+ network configuration entity.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @param domain A string specifying the desired domain, such as the
+ requested configuration (kSCDynamicStoreDomainSetup) or the
+ actual state (kSCDynamicStoreDomainState).
+ @param entity A string containing the specific global entity, such
+ as IPv4 (kSCEntNetIPv4) or DNS (kSCEntNetDNS).
+ @result Returns a string containing the formatted key.
+
*/
CFStringRef
SCDynamicStoreKeyCreateNetworkGlobalEntity (
/*!
@function SCDynamicStoreKeyCreateNetworkInterface
+ @discussion Creates a dynamic store key that can be used to access
+ the network interface configuration information stored in
+ the dynamic store.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @param domain A string specifying the desired domain, such as the
+ requested configuration (kSCDynamicStoreDomainSetup) or the
+ actual state (kSCDynamicStoreDomainState).
+ @result Returns a string containing the formatted key.
+
*/
CFStringRef
SCDynamicStoreKeyCreateNetworkInterface (
/*!
@function SCDynamicStoreKeyCreateNetworkInterfaceEntity
+ @discussion Creates a dynamic store key that can be used to access
+ the per-interface network configuration information stored in
+ the dynamic store.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @param domain A string specifying the desired domain, such as the
+ requested configuration (kSCDynamicStoreDomainSetup) or the
+ actual state (kSCDynamicStoreDomainState).
+ @param ifname A string containing the interface name or a regular
+ expression pattern.
+ @param entity A string containing the specific global entity, such
+ as IPv4 (kSCEntNetIPv4) or DNS (kSCEntNetDNS).
+ @result Returns a string containing the formatted key.
+
*/
CFStringRef
SCDynamicStoreKeyCreateNetworkInterfaceEntity (
/*!
@function SCDynamicStoreKeyCreateNetworkServiceEntity
+ @discussion Creates a dynamic store key that can be used to access
+ the per-service network configuration information stored in
+ the dynamic store.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @param domain A string specifying the desired domain, such as the
+ requested configuration (kSCDynamicStoreDomainSetup) or the
+ actual state (kSCDynamicStoreDomainState).
+ @param serviceID A string containing the service ID or a regular
+ expression pattern.
+ @param entity A string containing the specific global entity, such
+ as IPv4 (kSCEntNetIPv4) or DNS (kSCEntNetDNS).
+ @result Returns a string containing the formatted key.
+
+
*/
CFStringRef
SCDynamicStoreKeyCreateNetworkServiceEntity (
/*!
@function SCDynamicStoreKeyCreateComputerName
- @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
- function to receive notifications when the current
- computer/host name changes.
- @result A notification string for the current computer/host name.
+ @discussion Creates a key that can be used in conjuntion with
+ SCDynamicStoreSetNotificationKeys function to receive
+ notifications when the current computer name changes.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @result Returns a notification string for the current computer or
+ host name.
*/
CFStringRef
SCDynamicStoreKeyCreateComputerName (
/*!
@function SCDynamicStoreKeyCreateConsoleUser
- @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
- function to receive notifications when the current "Console"
- user changes.
- @result A notification string for the current "Console" user.
+ @discussion Creates a key that can be used in conjunction with
+ SCDynamicStoreSetNotificationKeys function to receive
+ notifications when the current console user changes.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @result Returns a notification string for the current console user.
*/
CFStringRef
SCDynamicStoreKeyCreateConsoleUser (
/*!
@function SCDynamicStoreKeyCreateHostNames
- @discussion Creates a key that can be used in conjunction with
- SCDynamicStoreSetNotificationKeys() to receive
+ @discussion Creates a key that can be used in conjunction with the
+ SCDynamicStoreSetNotificationKeys function to receive
notifications when the HostNames entity changes. The
- HostNames entity contains the LocalHostName.
- @result A notification string for the HostNames entity.
+ HostNames entity includes the local host name.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @result Returns a notification string for the HostNames entity.
*/
CFStringRef
SCDynamicStoreKeyCreateHostNames (
/*!
@function SCDynamicStoreKeyCreateLocation
- @discussion Creates a key that can be used in conjunction with
- SCDynamicStoreSetNotificationKeys() to receive
- notifications when the "location" identifier changes.
- @result A notification string for the current "location" identifier.
+ @discussion Creates a key that can be used in conjunction with the
+ SCDynamicStoreSetNotificationKeys function to receive
+ notifications when the location identifier changes.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @result Returns a notification string for the current location
+ identifier.
*/
CFStringRef
SCDynamicStoreKeyCreateLocation (
/*!
@function SCDynamicStoreKeyCreateProxies
- @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
- function to receive notifications when the current network proxy
- settings (HTTP, FTP, ...) are changed.
- @result A notification string for the current proxy settings.
+ @discussion Creates a key that can be used in conjunction with
+ the SCDynamicStoreSetNotificationKeys function to receive
+ notifications when the current network proxy settings
+ (such as HTTP or FTP) are changed.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this key.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used. If this reference is not
+ a valid CFAllocator, the behavior is undefined.
+ @result Returns a notification string for the current proxy settings.
*/
CFStringRef
SCDynamicStoreKeyCreateProxies (
#define _SCDYNAMICSTOREPRIVATE_H
#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <regex.h>
+#include <mach/message.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCDynamicStore.h>
+/*!
+ @header SCDynamicStorePrivate
+ */
+
/*!
@typedef SCDynamicStoreCallBack
@discussion Type of the callback function used when a
dynamic store change is delivered.
@param store The "dynamic store" session.
- @param changedKeys The list of changed keys.
@param info ....
*/
typedef boolean_t (*SCDynamicStoreCallBack_v1) (
@param store The "dynamic store" session.
@param runLoop A pointer to the run loop.
- @param funct The callback function to call for each notification.
+ @param func The callback function to call for each notification.
If this parameter is not a pointer to a function of the
correct prototype, the behavior is undefined.
@param context A pointer-sized user-defined value, that is passed as
#include <SystemConfiguration/SCDynamicStore.h>
+/*!
+ @header SCDynamicStoreSetSpecificPrivate
+ */
+
__BEGIN_DECLS
/*!
CFStringRef location = NULL;
Boolean tempSession = FALSE;
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyLocation"),
NULL,
NULL);
- if (!store) {
+ if (store == NULL) {
SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
return NULL;
}
SCNetworkConnectionFlags *flags)
{
SCNetworkReachabilityRef networkAddress;
- Boolean ok;
+ Boolean ok;
if (!nodename) {
_SCErrorSet(kSCStatusInvalidArgument);
SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
{
CFStringRef key;
- Boolean ret = FALSE;
- SCDynamicStoreRef store = NULL;
+ Boolean ret = FALSE;
+ SCDynamicStoreRef store;
store = SCDynamicStoreCreate(NULL,
CFSTR("SCNetworkInterfaceRefreshConfiguration"),
NULL, NULL);
if (store == NULL) {
- goto done;
+ return FALSE;
}
+
key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
ifName,
kSCEntNetRefreshConfiguration);
ret = SCDynamicStoreNotifyValue(store, key);
CFRelease(key);
-
- done:
- if (store != NULL) {
- CFRelease(store);
- }
+ CFRelease(store);
return (ret);
}
/*!
@header SCNetwork
-
- SCNetworkCheckReachabilityXXX()
-
- The SCNetworkCheckReachabilityXXX() APIs allow an application to
- determine the status of the system's current network configuration
- and the accessibility of a target host/address.
-
- The term "reachable" reflects whether a data packet, sent by
- an application into the network stack, can be sent to the
- the target host/address. Please note that their is no
- guarantee that the data packet will actually be received by
- the host.
-
-
- SCNetworkInterfaceRefreshConfiguration()
-
- This API sends a notification to interested network configuration
- agents to retry their configuraton immediately. For example, calling
- this API will cause the DHCP client to contact the DHCP server
- immediately rather than waiting until its timeout has expired.
- The utility of this API is to allow the caller to give a hint to
- the system that the network infrastructure/configuration has changed.
+ @discussion The SCNetwork API contains functions an application can
+ use to determine remote host reachability and notify the
+ system of configuration changes.
+
+ The two SCNetworkCheckReachability functions allow an
+ application to determine the status of the system's current
+ network configuration and the reachability of a target host
+ or address.
+
+ "Reachability" reflects whether a data packet, sent by an
+ application into the network stack, can leave the local
+ computer. Note that reachability does <i>not</i> guarantee
+ that the data packet will actually be received by the host.
+
+ The SCNetworkInterfaceRefreshConfiguration function sends a
+ notification to interested network configuration agents to
+ retry their configuration immediately. For example, calling
+ this function will cause the DHCP client to contact the DHCP
+ server immediately rather than waiting until its timeout has
+ expired. The utility of this function is to allow the caller
+ to give a hint to the system that the network infrastructure
+ or configuration has changed.
*/
/*!
@enum SCNetworkConnectionFlags
@discussion Flags that indicate whether the specified network
- nodename/address is reachable, requires a connection,
- requires some user intervention in establishing the
- connection, and whether the calling application must
- initiate the connection using the (TBD???) API.
-
+ nodename or address is reachable, whether a connection is
+ required, and whether some user intervention may be required
+ when establishing a connection.
@constant kSCNetworkFlagsTransientConnection
- This flag indicates that the specified nodename/address can
- be reached via a transient (e.g. PPP) connection.
-
+ This flag indicates that the specified nodename or address can
+ be reached via a transient connection, such as PPP.
@constant kSCNetworkFlagsReachable
- This flag indicates that the specified nodename/address can
+ This flag indicates that the specified nodename or address can
be reached using the current network configuration.
-
@constant kSCNetworkFlagsConnectionRequired
- This flag indicates that the specified nodename/address can
- be reached using the current network configuration but a
+ This flag indicates that the specified nodename or address can
+ be reached using the current network configuration, but a
connection must first be established.
As an example, this status would be returned for a dialup
- connection that was not currently active but could handle
+ connection that was not currently active, but could handle
network traffic for the target system.
-
@constant kSCNetworkFlagsConnectionAutomatic
- This flag indicates that the specified nodename/address can
- be reached using the current network configuration but a
+ This flag indicates that the specified nodename or address can
+ be reached using the current network configuration, but a
connection must first be established. Any traffic directed
- to the specified name/address will initiate the connection.
-
+ to the specified name or address will initiate the connection.
@constant kSCNetworkFlagsInterventionRequired
- This flag indicates that the specified nodename/address can
- be reached using the current network configuration but a
+ This flag indicates that the specified nodename or address can
+ be reached using the current network configuration, but a
connection must first be established. In addition, some
- form of user intervention will be required to establish
- this connection (e.g. providing a password, authentication
- token, etc.).
-
+ form of user intervention will be required to establish this
+ connection, such as providing a password, an authentication
+ token, etc.
+
+ Note: At the present time, this flag will only be returned
+ in the case where you have a dial-on-traffic configuration
+ (ConnectionAutomatic), where an attempt to connect has
+ already been made, and where some error (e.g. no dial tone,
+ no answer, bad password, ...) was encountered during the
+ automatic connection attempt. In this case the PPP controller
+ will stop attempting to establish a connection until the user
+ has intervened.
@constant kSCNetworkFlagsIsLocalAddress
- This flag indicates that the specified nodename/address
+ This flag indicates that the specified nodename or address
is one associated with a network interface on the current
system.
-
@constant kSCNetworkFlagsIsDirect
This flag indicates that network traffic to the specified
- nodename/address will not go through a gateway but is routed
- directly to one of the interfaces in the system.
+ nodename or address will not go through a gateway, but is
+ routed directly to one of the interfaces in the system.
*/
enum {
kSCNetworkFlagsTransientConnection = 1<<0,
@param flags A pointer to memory that will be filled with a
set of SCNetworkConnectionFlags detailing the reachability
of the specified address.
- @result TRUE if the network connection flags are valid; FALSE if the
- status could not be determined.
+ @result Returns TRUE if the network connection flags are valid;
+ FALSE if the status could not be determined.
*/
Boolean
SCNetworkCheckReachabilityByAddress (
/*!
@function SCNetworkCheckReachabilityByName
- @discussion Determines if the given network host/node name is
+ @discussion Determines if the given network host or node name is
reachable using the current network configuration.
@param nodename The node name of the desired host. This name would
- be the same as that passed to gethostbyname() or getaddrinfo().
+ be the same as that passed to the gethostbyname(3) or
+ getaddrinfo(3) functions.
@param flags A pointer to memory that will be filled with a
set of SCNetworkConnectionFlags detailing the reachability
of the specified node name.
- @result TRUE if the network connection flags are valid; FALSE if the
- status could not be determined.
+ @result Returns TRUE if the network connection flags are valid;
+ FALSE if the status could not be determined.
*/
Boolean
SCNetworkCheckReachabilityByName (
const char *nodename,
SCNetworkConnectionFlags *flags
);
+
/*!
@function SCNetworkInterfaceRefreshConfiguration
@discussion Sends a notification to interested configuration agents
to have them immediately retry their configuration over a
particular network interface.
- Note: This API must be invoked by root (uid == 0).
- @param ifName The BSD name of the network interface e.g. CFSTR("en0").
- @result TRUE if the notification was sent; FALSE otherwise.
+ Note: This function must be invoked by root (uid == 0).
+ @param ifName The BSD name of the network interface, such as
+ CFSTR("en0").
+ @result Returns TRUE if the notification was sent; FALSE otherwise.
*/
Boolean
SCNetworkInterfaceRefreshConfiguration (
CFStringRef ifName
);
+
__END_DECLS
#endif /* _SCNETWORK_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef _SCNETWORKCONFIGURATION_H
+#define _SCNETWORKCONFIGURATION_H
+
+
+#include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+
+/*!
+ @header SCNetworkConfiguration
+ @discussion The SCNetworkConfiguration API provides access to the
+ stored network configuration. The functions include
+ providing access to the network capable devices on the
+ system, the network sets, network services, and network
+ protocols.
+
+ Note: When using the SCNetworkConfiguraiton APIs you must
+ keep in mind that in order for any of your changes to be
+ committed to permanent storage a call must be made to the
+ SCPreferencesCommitChanges function.
+ */
+
+/*!
+ @group Interface configuration
+ */
+
+/*!
+ @typedef SCNetworkInterfaceRef
+ @discussion This is the type of a reference to an object that represents
+ a network interface.
+ */
+typedef const struct __SCNetworkInterface * SCNetworkInterfaceRef;
+
+/*!
+ @const kSCNetworkInterfaceType6to4
+ */
+extern const CFStringRef kSCNetworkInterfaceType6to4 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeBluetooth
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeBluetooth AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeBond
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeBond AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeEthernet
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeEthernet AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeFireWire
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeFireWire AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeIEEE80211
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeIEEE80211 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // IEEE 802.11, AirPort
+
+/*!
+ @const kSCNetworkInterfaceTypeIrDA
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeIrDA AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeL2TP
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeL2TP AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeModem
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeModem AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypePPP
+ */
+extern const CFStringRef kSCNetworkInterfaceTypePPP AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypePPTP
+ */
+extern const CFStringRef kSCNetworkInterfaceTypePPTP AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeSerial
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeSerial AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceTypeVLAN
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeVLAN AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* special network interfaces (and types) */
+
+/*!
+ @const kSCNetworkInterfaceTypeIPv4
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeIPv4 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkInterfaceIPv4
+ @discussion A network interface that can used for layering other
+ interfaces (e.g. 6to4, PPP, PPTP, L2TP) over an existing
+ IPv4 network.
+ */
+extern const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+/*!
+ @group Protocol configuration
+ */
+
+/*!
+ @typedef SCNetworkProtocolRef
+ @discussion This is the type of a reference to an object that represents
+ a network protocol.
+ */
+typedef const struct __SCNetworkProtocol * SCNetworkProtocolRef;
+
+/* network "protocol" types */
+
+/*!
+ @const kSCNetworkProtocolTypeAppleTalk
+ */
+extern const CFStringRef kSCNetworkProtocolTypeAppleTalk AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkProtocolTypeDNS
+ */
+extern const CFStringRef kSCNetworkProtocolTypeDNS AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkProtocolTypeIPv4
+ */
+extern const CFStringRef kSCNetworkProtocolTypeIPv4 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkProtocolTypeIPv6
+ */
+extern const CFStringRef kSCNetworkProtocolTypeIPv6 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @const kSCNetworkProtocolTypeProxies
+ */
+extern const CFStringRef kSCNetworkProtocolTypeProxies AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+/*!
+ @group Service configuration
+ */
+
+/*!
+ @typedef SCNetworkServiceRef
+ @discussion This is the type of a reference to an object that represents
+ a network service.
+ */
+typedef const struct __SCNetworkService * SCNetworkServiceRef;
+
+
+/*!
+ @group Set configuration
+ */
+
+/*!
+ @typedef SCNetworkSetRef
+ @discussion This is the type of a reference to an object that represents
+ a network set.
+ */
+typedef const struct __SCNetworkSet * SCNetworkSetRef;
+
+
+__BEGIN_DECLS
+
+
+/* --------------------------------------------------------------------------------
+ * INTERFACES
+ * -------------------------------------------------------------------------------- */
+
+/*!
+ @group Interface configuration
+ */
+
+/*!
+ @function SCNetworkInterfaceGetTypeID
+ @discussion Returns the type identifier of all SCNetworkInterface instances.
+ */
+CFTypeID
+SCNetworkInterfaceGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceCopyAll
+ @discussion Returns all network capable devices on the system.
+ @result The list of SCNetworkInterface devices on the system.
+ You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkInterfaceRef's */
+SCNetworkInterfaceCopyAll (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetSupportedInterfaceTypes
+ @discussion Identify all of the network interface types (e.g. PPP) that
+ can be layered on top of this interface.
+ @param interface The network interface.
+ @result The list of SCNetworkInterface types supported by the interface;
+ NULL if no interface types are supported.
+ */
+CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedInterfaceTypes (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetSupportedProtocolTypes
+ @discussion Identify all of the network protocol types (e.g. IPv4, IPv6) that
+ can be layered on top of this interface.
+ @param interface The network interface.
+ @result The list of SCNetworkProtocol types supported by the interface;
+ NULL if no protocol types are supported.
+ */
+CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedProtocolTypes (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceCreateWithInterface
+ @discussion Create a new network interface layered on top of another. For
+ example, this function would be used to create a "PPP" interface
+ on top of a "modem".
+ @param interface The network interface.
+ @param interfaceType The type of SCNetworkInterface to be layered on
+ top of the provided interface.
+ @result A reference to the new SCNetworkInterface.
+ You must release the returned value.
+ */
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithInterface (SCNetworkInterfaceRef interface,
+ CFStringRef interfaceType) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetBSDName
+ @discussion Returns the BSD interface (en0) or device name (modem)
+ for the interface.
+ @param interface The network interface.
+ @result The BSD name associated with the interface (e.g. "en0");
+ NULL if no BSD name is available.
+ */
+CFStringRef
+SCNetworkInterfaceGetBSDName (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetConfiguration
+ @discussion Returns the configuration settings associated with a interface.
+ @param interface The network interface.
+ @result The configuration settings associated with the interface;
+ NULL if no changes to the default configuration have been saved.
+ */
+CFDictionaryRef
+SCNetworkInterfaceGetConfiguration (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetHardwareAddressString
+ @discussion Returns a displayable link layer address for the interface.
+ @param interface The network interface.
+ @result A string representing the hardware (MAC) address for the interface.
+ */
+CFStringRef
+SCNetworkInterfaceGetHardwareAddressString (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetInterface
+ @discussion For layered network interfaces, return the underlying interface.
+ @param interface The network interface.
+ @result The underlying network interface;
+ NULL if this is a leaf interface.
+ */
+SCNetworkInterfaceRef
+SCNetworkInterfaceGetInterface (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetInterfaceType
+ @discussion Returns the associated network interface type.
+ @param interface The network interface.
+ @result The interface type.
+ */
+CFStringRef
+SCNetworkInterfaceGetInterfaceType (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceGetLocalizedDisplayName
+ @discussion Returns the localized name (e.g. "Built-in Ethernet") for
+ the interface.
+ @param interface The network interface.
+ @result A localized, display name for the interface;
+ NULL if no name is available.
+ */
+CFStringRef
+SCNetworkInterfaceGetLocalizedDisplayName (SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkInterfaceSetConfiguration
+ @discussion Stores the configuration settings for the interface.
+ @param interface The network interface.
+ @param config The configuration settings to associate with this interface.
+ @result TRUE if the configuration was stored; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkInterfaceSetConfiguration (SCNetworkInterfaceRef interface,
+ CFDictionaryRef config) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* --------------------------------------------------------------------------------
+ * PROTOCOLS
+ * -------------------------------------------------------------------------------- */
+
+/*!
+ @group Protocol configuration
+ */
+
+/*!
+ @function SCNetworkProtocolGetTypeID
+ @discussion Returns the type identifier of all SCNetworkProtocol instances.
+ */
+CFTypeID
+SCNetworkProtocolGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkProtocolGetConfiguration
+ @discussion Returns the configuration settings associated with the protocol.
+ @param protocol The network protocol.
+ @result The configuration settings associated with the protocol;
+ NULL if no changes to the default configuration have been saved.
+ */
+CFDictionaryRef
+SCNetworkProtocolGetConfiguration (SCNetworkProtocolRef protocol) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkProtocolGetEnabled
+ @discussion Returns whether this protocol has been enabled.
+ @param protocol The network protocol.
+ @result TRUE if the protocol is enabled.
+ */
+Boolean
+SCNetworkProtocolGetEnabled (SCNetworkProtocolRef protocol) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkProtocolGetProtocolType
+ @discussion Returns the associated network protocol type.
+ @param protocol The network protocol.
+ @result The protocol type.
+ */
+CFStringRef
+SCNetworkProtocolGetProtocolType (SCNetworkProtocolRef protocol) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkProtocolSetConfiguration
+ @discussion Stores the configuration settings for the protocol.
+ @param protocol The network protocol.
+ @param config The configuration settings to associate with this protocol.
+ @result TRUE if the configuration was stored; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkProtocolSetConfiguration (SCNetworkProtocolRef protocol,
+ CFDictionaryRef config) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkProtocolSetEnabled
+ @discussion Enables or disables the protocol.
+ @param protocol The network protocol.
+ @param enabled TRUE if the protocol should be enabled.
+ @result TRUE if the enabled status was saved; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkProtocolSetEnabled (SCNetworkProtocolRef protocol,
+ Boolean enabled) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* --------------------------------------------------------------------------------
+ * SERVICES
+ * -------------------------------------------------------------------------------- */
+
+/*!
+ @group Service configuration
+ */
+
+/*!
+ @function SCNetworkServiceGetTypeID
+ @discussion Returns the type identifier of all SCNetworkService instances.
+ */
+CFTypeID
+SCNetworkServiceGetTypeID (void);
+
+/*!
+ @function SCNetworkServiceAddProtocolType
+ @discussion Adds a network protocol of the specified type to the
+ service. The protocal configuration is set to default values
+ that are appropriate for the interface associated with the
+ service.
+ @param service The network service.
+ @param protocolType The type of SCNetworkProtocol to be added to the service.
+ @result TRUE if the protocol was added to the service; FALSE if the
+ protocol was already present or an error was encountered.
+ */
+Boolean
+SCNetworkServiceAddProtocolType (SCNetworkServiceRef service,
+ CFStringRef protocolType) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceCopyAll
+ @discussion Returns all available network services for the specified preferences.
+ @param prefs The "preferences" session.
+ @result The list of SCNetworkService services associated with the preferences.
+ You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkServiceCopyAll (SCPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceCopyProtocols
+ @discussion Returns all network protocols associated with the service.
+ @param service The network service.
+ @result The list of SCNetworkProtocol protocols associated with the service.
+ You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkProtocolRef's */
+SCNetworkServiceCopyProtocols (SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceCreate
+ @discussion Create a new network service for the specified interface in the
+ configuration.
+ @param prefs The "preferences" session.
+ @result A reference to the new SCNetworkService.
+ You must release the returned value.
+ */
+SCNetworkServiceRef
+SCNetworkServiceCreate (SCPreferencesRef prefs,
+ SCNetworkInterfaceRef interface) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceCopy
+ @discussion Returns the network service with the specified identifier.
+ @param prefs The "preferences" session.
+ @param serviceID The unique identifier for the service.
+ @result A reference to the SCNetworkService from the associated preferences;
+ NULL if the serviceID does not exist in the preferences or if an
+ error was encountered.
+ You must release the returned value.
+ */
+SCNetworkServiceRef
+SCNetworkServiceCopy (SCPreferencesRef prefs,
+ CFStringRef serviceID) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceGetEnabled
+ @discussion Returns whether this service has been enabled.
+ @param service The network service.
+ @result TRUE if the service is enabled.
+ */
+Boolean
+SCNetworkServiceGetEnabled (SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceGetInterface
+ @discussion Returns the network interface associated with the service.
+ @param service The network service.
+ @result A reference to the SCNetworkInterface associated with the service;
+ NULL if an error was encountered.
+ */
+SCNetworkInterfaceRef
+SCNetworkServiceGetInterface (SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceGetName
+ @discussion Returns the [user specified] name associated with the service.
+ @param service The network service.
+ @result The [user specified] name.
+ */
+CFStringRef
+SCNetworkServiceGetName (SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceCopyProtocol
+ @discussion Returns the network protocol of the specified type for
+ the service.
+ @param service The network service.
+ @result A reference to the SCNetworkProtocol associated with the service;
+ NULL if this protocol has not been added or if an error was encountered.
+ You must release the returned value.
+ */
+SCNetworkProtocolRef
+SCNetworkServiceCopyProtocol (SCNetworkServiceRef service,
+ CFStringRef protocolType) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceGetServiceID
+ @discussion Returns the identifier for the service.
+ @param service The network service.
+ @result The service identifier.
+ */
+CFStringRef
+SCNetworkServiceGetServiceID (SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceRemove
+ @discussion Removes the network service from the configuration.
+ @param service The network service.
+ @result TRUE if the service was removed; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkServiceRemove (SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceRemoveProtocolType
+ @discussion Removes the network protocol of the specified type from the service.
+ @param service The network service.
+ @param protocolType The type of SCNetworkProtocol to be removed from the service.
+ @result TRUE if the protocol was removed to the service; FALSE if the
+ protocol was not configured or an error was encountered.
+ */
+Boolean
+SCNetworkServiceRemoveProtocolType (SCNetworkServiceRef service,
+ CFStringRef protocolType) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceSetEnabled
+ @discussion Enables or disables the service.
+ @param service The network service.
+ @param enabled TRUE if the service should be enabled.
+ @result TRUE if the enabled status was saved; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkServiceSetEnabled (SCNetworkServiceRef service,
+ Boolean enabled) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkServiceSetName
+ @discussion Stores the [user specified] name for the service.
+ @param service The network service.
+ @param name The [user defined] name to associate with the service.
+ @result TRUE if the name was saved; FALSE if an error was encountered.
+
+ Note: although not technically required, the [user specified] names
+ for all services within any given set should be unique. As such, an
+ error will be returned if you attemp to name two services with the
+ same string.
+ */
+Boolean
+SCNetworkServiceSetName (SCNetworkServiceRef service,
+ CFStringRef name) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* --------------------------------------------------------------------------------
+ * SETS
+ * -------------------------------------------------------------------------------- */
+
+/*!
+ @group Set configuration
+ */
+
+/*!
+ @function SCNetworkSetGetTypeID
+ @discussion Returns the type identifier of all SCNetworkSet instances.
+ */
+CFTypeID
+SCNetworkSetGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetAddService
+ @discussion Adds the network service to the set.
+ @param set The network set.
+ @param service The service to be added.
+ @result TRUE if the service was added to the set; FALSE if the
+ service was already present or an error was encountered.
+
+ Note: at the present time, the Network Prefs UI does not
+ support having a single service be a member of more than
+ one set. As such, an error will be returned if you attempt
+ to add a service to more than one set.
+ */
+Boolean
+SCNetworkSetAddService (SCNetworkSetRef set,
+ SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetCopyAll
+ @discussion Returns all available sets for the specified preferences.
+ @param prefs The "preferences" session.
+ @result The list of SCNetworkSet sets associated with the preferences.
+ You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkSetRef's */
+SCNetworkSetCopyAll (SCPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetCopyCurrent
+ @discussion Returns the "current" set.
+ @param prefs The "preferences" session.
+ @result The current set; NULL if no current set has been defined.
+ */
+SCNetworkSetRef
+SCNetworkSetCopyCurrent (SCPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetCopyServices
+ @discussion Returns all network services associated with the set.
+ @param set The network set.
+ @result The list of SCNetworkService services associated with the set.
+ You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkSetCopyServices (SCNetworkSetRef set) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetCreate
+ @discussion Create a new set in the configuration.
+ @param prefs The "preferences" session.
+ @result A reference to the new SCNetworkSet.
+ You must release the returned value.
+ */
+SCNetworkSetRef
+SCNetworkSetCreate (SCPreferencesRef prefs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetCopy
+ @discussion Returns the set with the specified identifier.
+ @param prefs The "preferences" session.
+ @param setID The unique identifier for the set.
+ @result A reference to the SCNetworkSet from the associated preferences;
+ NULL if the setID does not exist in the preferences or if an
+ error was encountered.
+ You must release the returned value.
+ */
+SCNetworkSetRef
+SCNetworkSetCopy (SCPreferencesRef prefs,
+ CFStringRef setID) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetGetName
+ @discussion Returns the [user specified] name associated with the set.
+ @param set The network set.
+ @result The [user specified] name.
+ */
+CFStringRef
+SCNetworkSetGetName (SCNetworkSetRef set) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetGetSetID
+ @discussion Returns the identifier for the set.
+ @param set The network set.
+ @result The set identifier.
+ */
+CFStringRef
+SCNetworkSetGetSetID (SCNetworkSetRef set) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetGetServiceOrder
+ @discussion Returns the [user specified] ordering of network services
+ within the set.
+ @param set The network set.
+ @result The ordered list of CFStringRef service identifiers associated
+ with the set;
+ NULL if no service order has been specified or if an error
+ was encountered.
+ */
+CFArrayRef /* of serviceID CFStringRef's */
+SCNetworkSetGetServiceOrder (SCNetworkSetRef set) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetRemove
+ @discussion Removes the set from the configuration.
+ @param set The network set.
+ @result TRUE if the set was removed; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkSetRemove (SCNetworkSetRef set) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetRemoveService
+ @discussion Removes the network service from the set.
+ @param set The network set.
+ @param service The service to be removed.
+ @result TRUE if the service was removed from the set; FALSE if the
+ service was not already present or an error was encountered.
+ */
+Boolean
+SCNetworkSetRemoveService (SCNetworkSetRef set,
+ SCNetworkServiceRef service) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetSetCurrent
+ @discussion Specifies the set that should be the "current" set.
+ @param set The network set.
+ @result TRUE if the current set was updated;
+ FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkSetSetCurrent (SCNetworkSetRef set) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetSetName
+ @discussion Stores the [user specified] name for the set.
+ @param set The network set.
+ @param name The [user defined] name to associate with the set.
+ @result TRUE if the name was saved; FALSE if an error was encountered.
+
+ Note: although not technically required, the [user specified] names
+ for all set should be unique. As such, an error will be returned if
+ you attemp to name two sets with the same string.
+ */
+Boolean
+SCNetworkSetSetName (SCNetworkSetRef set,
+ CFStringRef name) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCNetworkSetGetServiceOrder
+ @discussion Stores the [user specified] ordering of network services for the set.
+ @param set The network set.
+ @param newOrder The ordered list of CFStringRef service identifiers for the set.
+ @result TRUE if the new service order was saved; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkSetSetServiceOrder (SCNetworkSetRef set,
+ CFArrayRef newOrder) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; /* serviceID CFStringRef's */
+
+
+__END_DECLS
+
+#endif /* _SCNETWORKCONFIGURATION_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 27, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+
+__private_extern__ CFDictionaryRef
+__getPrefsConfiguration(SCPreferencesRef prefs, CFStringRef path)
+{
+ CFDictionaryRef config;
+ CFIndex n;
+
+ config = SCPreferencesPathGetValue(prefs, path);
+
+ n = isA_CFDictionary(config) ? CFDictionaryGetCount(config) : 0;
+ switch (n) {
+ case 0 :
+ // ignore empty configuration entities
+ config = NULL;
+ break;
+ case 1 :
+ if (CFDictionaryContainsKey(config, kSCResvInactive)) {
+ // ignore [effectively] empty configuration entities
+ config = NULL;
+ }
+ break;
+ default :
+ break;
+ }
+
+ return config;
+}
+
+
+__private_extern__ Boolean
+__setPrefsConfiguration(SCPreferencesRef prefs,
+ CFStringRef path,
+ CFDictionaryRef config,
+ Boolean keepInactive)
+{
+ CFMutableDictionaryRef newConfig = NULL;
+ Boolean ok = FALSE;
+
+ if (config != NULL) {
+ if (!isA_CFDictionary(config)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+ newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
+ } else {
+ newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ }
+
+ if (keepInactive) {
+ CFDictionaryRef curConfig;
+
+ /*
+ * preserve enabled/disabled state
+ */
+
+ curConfig = SCPreferencesPathGetValue(prefs, path);
+ if (isA_CFDictionary(curConfig) && CFDictionaryContainsKey(curConfig, kSCResvInactive)) {
+ // if currently disabled
+ CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
+ } else {
+ // if currently enabled
+ CFDictionaryRemoveValue(newConfig, kSCResvInactive);
+ }
+ }
+
+ /*
+ * set new configuration
+ */
+
+ if (CFDictionaryGetCount(newConfig) == 0) {
+ CFRelease(newConfig);
+ newConfig = NULL;
+ }
+
+ if (newConfig == NULL) {
+ ok = SCPreferencesPathRemoveValue(prefs, path);
+ } else {
+ ok = SCPreferencesPathSetValue(prefs, path, newConfig);
+ }
+
+ if (newConfig != NULL) CFRelease(newConfig);
+ return ok;
+}
+
+
+__private_extern__ Boolean
+__getPrefsEnabled(SCPreferencesRef prefs, CFStringRef path)
+{
+ CFDictionaryRef config;
+
+ config = SCPreferencesPathGetValue(prefs, path);
+ if (isA_CFDictionary(config) && CFDictionaryContainsKey(config, kSCResvInactive)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+__private_extern__ Boolean
+__setPrefsEnabled(SCPreferencesRef prefs,
+ CFStringRef path,
+ Boolean enabled)
+{
+ CFDictionaryRef curConfig = NULL;
+ CFMutableDictionaryRef newConfig = NULL;
+ Boolean ok = FALSE;
+
+ /*
+ * preserve current configuration
+ */
+
+ curConfig = SCPreferencesPathGetValue(prefs, path);
+ if (curConfig != NULL) {
+ if (!isA_CFDictionary(curConfig)) {
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+ newConfig = CFDictionaryCreateMutableCopy(NULL, 0, curConfig);
+ } else {
+ newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ }
+
+ if (enabled) {
+ // enable
+ CFDictionaryRemoveValue(newConfig, kSCResvInactive);
+ } else {
+ // disable
+ CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
+ }
+
+ /*
+ * update configuration
+ */
+
+ if (CFDictionaryGetCount(newConfig) == 0) {
+ CFRelease(newConfig);
+ newConfig = NULL;
+ }
+
+ if (newConfig == NULL) {
+ ok = SCPreferencesPathRemoveValue(prefs, path);
+ } else {
+ ok = SCPreferencesPathSetValue(prefs, path, newConfig);
+ }
+
+ if (newConfig != NULL) CFRelease(newConfig);
+ return ok;
+}
+
+
+#define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
+#define SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration.framework"
+
+
+static CFDictionaryRef
+__copyTemplates()
+{
+ CFBundleRef bundle;
+ Boolean ok;
+ CFDictionaryRef templates;
+ CFURLRef url;
+ CFStringRef xmlError = NULL;
+ CFDataRef xmlTemplates = NULL;
+
+ bundle = CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID);
+ if (bundle == NULL) {
+ return NULL;
+ }
+
+ url = CFBundleCopyResourceURL(bundle, CFSTR("NetworkConfiguration"), CFSTR("plist"), NULL);
+ if (url == NULL) {
+ return NULL;
+ }
+
+ ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlTemplates, NULL, NULL, NULL);
+ CFRelease(url);
+ if (!ok || (xmlTemplates == NULL)) {
+ return NULL;
+ }
+
+ /* convert the XML data into a property list */
+ templates = CFPropertyListCreateFromXMLData(NULL, xmlTemplates, kCFPropertyListImmutable, &xmlError);
+ CFRelease(xmlTemplates);
+ if (templates == NULL) {
+ if (xmlError != NULL) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("could not load SCNetworkConfiguration templates: %@"), xmlError);
+ CFRelease(xmlError);
+ }
+ return NULL;
+ }
+
+ if (!isA_CFDictionary(templates)) {
+ CFRelease(templates);
+ return NULL;
+ }
+
+ return templates;
+}
+
+
+__private_extern__ CFDictionaryRef
+__copyInterfaceTemplate(CFStringRef interfaceType,
+ CFStringRef childInterfaceType)
+{
+ CFDictionaryRef interface = NULL;
+ CFDictionaryRef interfaces;
+ CFDictionaryRef templates;
+
+ templates = __copyTemplates();
+ if (templates == NULL) {
+ return NULL;
+ }
+
+ interfaces = CFDictionaryGetValue(templates, CFSTR("Interface"));
+ if (!isA_CFDictionary(interfaces)) {
+ CFRelease(templates);
+ return NULL;
+ }
+
+ if (childInterfaceType == NULL) {
+ interface = CFDictionaryGetValue(interfaces, interfaceType);
+ } else {
+ CFStringRef expandedType;
+
+ expandedType = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("%@-%@"),
+ interfaceType,
+ childInterfaceType);
+ interface = CFDictionaryGetValue(interfaces, expandedType);
+ CFRelease(expandedType);
+ }
+
+ if (isA_CFDictionary(interface) && (CFDictionaryGetCount(interface) > 0)) {
+ CFRetain(interface);
+ } else {
+ interface = NULL;
+ }
+
+ CFRelease(templates);
+
+ return interface;
+}
+
+
+__private_extern__ CFDictionaryRef
+__copyProtocolTemplate(CFStringRef interfaceType,
+ CFStringRef childInterfaceType,
+ CFStringRef protocolType)
+{
+ CFDictionaryRef interface = NULL;
+ CFDictionaryRef protocol = NULL;
+ CFDictionaryRef protocols;
+ CFDictionaryRef templates;
+
+ templates = __copyTemplates();
+ if (templates == NULL) {
+ return NULL;
+ }
+
+ protocols = CFDictionaryGetValue(templates, CFSTR("Protocol"));
+ if (!isA_CFDictionary(protocols)) {
+ CFRelease(templates);
+ return NULL;
+ }
+
+ if (childInterfaceType == NULL) {
+ interface = CFDictionaryGetValue(protocols, interfaceType);
+ } else {
+ CFStringRef expandedType;
+
+ expandedType = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("%@-%@"),
+ interfaceType,
+ childInterfaceType);
+ interface = CFDictionaryGetValue(protocols, expandedType);
+ CFRelease(expandedType);
+ }
+
+ if (isA_CFDictionary(interface)) {
+ protocol = CFDictionaryGetValue(interface, protocolType);
+ if (isA_CFDictionary(protocol) && (CFDictionaryGetCount(protocol) > 0)) {
+ CFRetain(protocol);
+ } else {
+ protocol = NULL;
+ }
+ }
+
+ CFRelease(templates);
+
+ return protocol;
+}
+
+
+__private_extern__ Boolean
+__createInterface(int s, CFStringRef interface)
+{
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof(ifr));
+ (void) _SC_cfstring_to_cstring(interface,
+ ifr.ifr_name,
+ sizeof(ifr.ifr_name),
+ kCFStringEncodingASCII);
+
+ if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("could not create interface \"%@\": %s"),
+ interface,
+ strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+__private_extern__ Boolean
+__destroyInterface(int s, CFStringRef interface)
+{
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof(ifr));
+ (void) _SC_cfstring_to_cstring(interface,
+ ifr.ifr_name,
+ sizeof(ifr.ifr_name),
+ kCFStringEncodingASCII);
+
+ if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("could not destroy interface \"%@\": %s"),
+ interface,
+ strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+__private_extern__ Boolean
+__markInterfaceUp(int s, CFStringRef interface)
+{
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof(ifr));
+ (void) _SC_cfstring_to_cstring(interface,
+ ifr.ifr_name,
+ sizeof(ifr.ifr_name),
+ kCFStringEncodingASCII);
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("could not get flags for interface \"%@\": %s"),
+ interface,
+ strerror(errno));
+ return FALSE;
+ }
+
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) == -1) {
+ SCLog(TRUE,
+ LOG_ERR,
+ CFSTR("could not set flags for interface \"%@\": %s"),
+ interface,
+ strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef _SCNETWORKCONFIGURATIONINTERNAL_H
+#define _SCNETWORKCONFIGURATIONINTERNAL_H
+
+
+#include <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPreferencesPathKey.h>
+#include <IOKit/IOKitLib.h>
+
+#include "SCNetworkConfiguration.h"
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* set id */
+ CFStringRef setID;
+
+ /* prefs */
+ SCPreferencesRef prefs;
+
+} SCNetworkSetPrivate, *SCNetworkSetPrivateRef;
+
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* service id */
+ CFStringRef serviceID;
+
+ /* interface */
+ SCNetworkInterfaceRef interface;
+
+ /* prefs */
+ SCPreferencesRef prefs;
+
+} SCNetworkServicePrivate, *SCNetworkServicePrivateRef;
+
+
+typedef struct {
+
+ /* base CFType information */
+ CFRuntimeBase cfBase;
+
+ /* entity id */
+ CFStringRef entityID;
+
+ /* service */
+ SCNetworkServiceRef service;
+
+} SCNetworkProtocolPrivate, *SCNetworkProtocolPrivateRef;
+
+
+typedef struct {
+
+ // base CFType information
+ CFRuntimeBase cfBase;
+
+ // interface information
+ CFStringRef interface_type; // interface type
+
+ // localized name
+ CFStringRef localized_name; // localized [display] name
+ CFStringRef localized_key;
+ CFStringRef localized_arg1;
+ CFStringRef localized_arg2;
+
+ /* [layered] interface*/
+ SCNetworkInterfaceRef interface;
+
+ /* service (NULL if not associated with a service) */
+ SCNetworkServiceRef service;
+
+ /* unsaved configuration (when prefs not [yet] available) */
+ CFDictionaryRef unsaved;
+
+ // [SCPreferences] interface entity information
+ CFStringRef entity_device; // interface device
+ CFStringRef entity_hardware; // interface hardware
+ CFStringRef entity_type; // interface type
+ CFStringRef entity_subtype; // interface subtype
+
+ // configuration information
+ CFMutableArrayRef supported_interface_types;
+ CFMutableArrayRef supported_protocol_types;
+
+ // IORegistry (service plane) information
+ CFStringRef address;
+ Boolean builtin;
+ CFStringRef location;
+ CFStringRef path;
+ Boolean supportsDeviceOnHold;
+ Boolean supportsBond;
+ Boolean supportsVLAN;
+
+ // misc
+ int sort_order; // sort order for this interface
+
+} SCNetworkInterfacePrivate, *SCNetworkInterfacePrivateRef;
+
+
+__BEGIN_DECLS
+
+
+SCNetworkServicePrivateRef
+__SCNetworkServiceCreatePrivate (CFAllocatorRef allocator,
+ CFStringRef serviceID,
+ SCNetworkInterfaceRef interface,
+ SCPreferencesRef prefs);
+
+
+SCNetworkProtocolPrivateRef
+__SCNetworkProtocolCreatePrivate (CFAllocatorRef allocator,
+ CFStringRef entityID,
+ SCNetworkServiceRef service);
+
+Boolean
+__SCNetworkProtocolIsValidType (CFStringRef protocolType);
+
+SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreateCopy (CFAllocatorRef allocator,
+ SCNetworkInterfaceRef interface,
+ SCNetworkServiceRef service);
+
+SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreatePrivate (CFAllocatorRef allocator,
+ SCNetworkInterfaceRef interface,
+ SCNetworkServiceRef service,
+ io_string_t path);
+
+SCNetworkInterfaceRef
+__SCNetworkInterfaceCreateWithEntity (CFAllocatorRef allocator,
+ CFDictionaryRef interface_entity,
+ SCNetworkServiceRef service);
+
+CFArrayRef
+__SCNetworkInterfaceCopyDeepConfiguration (SCNetworkInterfaceRef interface);
+
+Boolean
+__SCNetworkInterfaceSetConfiguration (SCNetworkInterfaceRef interface,
+ CFDictionaryRef config,
+ Boolean okToHold);
+
+void
+__SCNetworkInterfaceSetDeepConfiguration (SCNetworkInterfaceRef interface,
+ CFArrayRef configs);
+
+CFDictionaryRef
+__copyInterfaceTemplate (CFStringRef interfaceType,
+ CFStringRef childInterfaceType);
+
+CFDictionaryRef
+__copyProtocolTemplate (CFStringRef interfaceType,
+ CFStringRef childInterfaceType,
+ CFStringRef protocolType);
+
+CFDictionaryRef
+__getPrefsConfiguration (SCPreferencesRef prefs,
+ CFStringRef path);
+
+Boolean
+__setPrefsConfiguration (SCPreferencesRef prefs,
+ CFStringRef path,
+ CFDictionaryRef config,
+ Boolean keepInactive);
+
+Boolean
+__getPrefsEnabled (SCPreferencesRef prefs,
+ CFStringRef path);
+
+Boolean
+__setPrefsEnabled (SCPreferencesRef prefs,
+ CFStringRef path,
+ Boolean enabled);
+
+Boolean
+__createInterface (int s,
+ CFStringRef interface);
+
+Boolean
+__destroyInterface (int s,
+ CFStringRef interface);
+
+Boolean
+__markInterfaceUp (int s,
+ CFStringRef interface);
+
+__END_DECLS
+
+#endif /* _SCNETWORKCONFIGURATIONINTERNAL_H */
/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * April 14, 2004 Christophe Allie <callie@apple.com>
+ * - use mach messages
+
* December 20, 2002 Christophe Allie <callie@apple.com>
* - initial revision
*/
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
+#include <servers/bootstrap.h>
+
#include <pthread.h>
+#include <notify.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <arpa/nameser.h>
#include <netdb.h>
-#include <resolv.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
-#include "ppp.h"
-
+#include <ppp/ppp_msg.h>
+#include <ppp/PPPControllerPriv.h>
+#include "pppcontroller.h"
+#include <ppp/pppcontroller_types.h>
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
typedef struct {
/* base CFType information */
- CFRuntimeBase cfBase;
+ CFRuntimeBase cfBase;
/* service ID */
- CFStringRef serviceID; /* serviceID */
+ CFStringRef serviceID;
+
+ /* ref to PPP controller for control messages */
+ mach_port_t session_port;
- int eventRef; /* ref to PPP controller for event messages */
- CFSocketRef eventRefCF; /* ref to PPP controller for event messages */
- int controlRef; /* ref to PPP controller for control messages */
- //u_int32_t status; /* current status of the connection */
- //char ifname[IFNAMSIZ]; /* ppp interface used for this connection */
+ /* ref to PPP controller for notification messages */
+ CFMachPortRef notify_port;
/* run loop source, callout, context, rl scheduling info */
CFRunLoopSourceRef rls;
SCNetworkConnectionContext rlsContext;
CFMutableArrayRef rlList;
+ /* misc info */
+ int debug;
+
} SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef;
/* -------------------------------------------------------------------------------------------
static CFStringRef
__SCNetworkConnectionCopyDescription(CFTypeRef cf)
{
- CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)cf;
CFMutableStringRef result;
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)cf;
result = CFStringCreateMutable(allocator, 0);
CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkConnection, %p [%p]> {\n"), cf, allocator);
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
+
static void
__SCNetworkConnectionDeallocate(CFTypeRef cf)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)cf;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionDeallocate:"));
+ if (connectionPrivate->debug) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionDeallocate (0x%x)"), connectionPrivate);
+ }
/* release resources */
- if (connectionPrivate->eventRef != -1) {
- while (CFArrayGetCount(connectionPrivate->rlList)) {
- CFRunLoopRef runLoop;
- CFStringRef runLoopMode;
-
- runLoop = (CFRunLoopRef)CFArrayGetValueAtIndex(connectionPrivate->rlList, 1);
- runLoopMode = CFArrayGetValueAtIndex(connectionPrivate->rlList, 2);
- CFRunLoopRemoveSource(runLoop, connectionPrivate->rls, runLoopMode);
-
- CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 2);
- CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 1);
- CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 0);
- }
+ if (connectionPrivate->rlList != NULL) {
+ CFRunLoopSourceInvalidate(connectionPrivate->rls);
CFRelease(connectionPrivate->rls);
CFRelease(connectionPrivate->rlList);
- //PPPDispose(connectionPrivate->eventRef);
- CFSocketInvalidate(connectionPrivate->eventRefCF);
- CFRelease(connectionPrivate->eventRefCF);
- }
- if (connectionPrivate->controlRef != -1)
- PPPDispose(connectionPrivate->controlRef);
- if (connectionPrivate->rlsContext.release)
- connectionPrivate->rlsContext.release(connectionPrivate->rlsContext.info);
+ }
+
+ if (connectionPrivate->notify_port != NULL) {
+ CFMachPortInvalidate(connectionPrivate->notify_port);
+ CFRelease(connectionPrivate->notify_port);
+ }
+
+ if (connectionPrivate->session_port != MACH_PORT_NULL)
+ mach_port_destroy(mach_task_self(), connectionPrivate->session_port);
+
+ if (connectionPrivate->rlsContext.release != NULL)
+ (*connectionPrivate->rlsContext.release)(connectionPrivate->rlsContext.info);
+
if (connectionPrivate->serviceID)
CFRelease(connectionPrivate->serviceID);
return;
}
+/* -------------------------------------------------------------------------------------------
+------------------------------------------------------------------------------------------- */
+
+static SCNetworkConnectionStatus
+__SCNetworkConnectionConvertStatus (int state)
+{
+ SCNetworkConnectionStatus status = kSCNetworkConnectionDisconnected;
+
+ switch (state) {
+ case PPP_INITIALIZE:
+ case PPP_CONNECTLINK:
+ case PPP_ESTABLISH:
+ case PPP_AUTHENTICATE:
+ case PPP_CALLBACK:
+ case PPP_NETWORK:
+ case PPP_WAITONBUSY:
+ status = kSCNetworkConnectionConnecting;
+ break;
+ case PPP_TERMINATE:
+ case PPP_DISCONNECTLINK:
+ status = kSCNetworkConnectionDisconnecting;
+ break;
+ case PPP_RUNNING:
+ case PPP_ONHOLD:
+ status = kSCNetworkConnectionConnected;
+ break;
+ case PPP_IDLE:
+ case PPP_DORMANT:
+ case PPP_HOLDOFF:
+ default:
+ status = kSCNetworkConnectionDisconnected;
+ }
+ return status;
+}
+
+/* -------------------------------------------------------------------------------------------
+------------------------------------------------------------------------------------------- */
+
+static void
+__SCNetworkConnectionCallBack(CFMachPortRef port, void * msg, CFIndex size, void * info)
+{
+ mach_msg_empty_rcv_t * buf = msg;
+ SCNetworkConnectionRef connection = (SCNetworkConnectionRef)info;
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ void *context_info;
+ void (*context_release)(const void *);
+ int error = kSCStatusFailed;
+ mach_msg_id_t msgid = buf->header.msgh_id;
+ int phase = PPP_IDLE;
+ SCNetworkConnectionCallBack rlsFunction;
+ kern_return_t status;
+ SCNetworkConnectionStatus scstatus;
+
+ if (msgid == MACH_NOTIFY_NO_SENDERS) {
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionCallBack: PPPController server died"));
+ } else {
+ status = pppcontroller_getstatus(connectionPrivate->session_port, &phase, &error);
+ }
+
+ if (connectionPrivate->rls == NULL) {
+ return;
+ }
+
+ rlsFunction = connectionPrivate->rlsFunction;
+ if (rlsFunction == NULL) {
+ return;
+ }
+
+ if ((connectionPrivate->rlsContext.retain != NULL) && (connectionPrivate->rlsContext.info != NULL)) {
+ context_info = (void *)(*connectionPrivate->rlsContext.retain)(connectionPrivate->rlsContext.info);
+ context_release = connectionPrivate->rlsContext.release;
+ } else {
+ context_info = connectionPrivate->rlsContext.info;
+ context_release = NULL;
+ }
+
+ scstatus = __SCNetworkConnectionConvertStatus(phase);
+
+ (*rlsFunction)(connection, scstatus, context_info);
+ if ((context_release != NULL) && (context_info != NULL)) {
+ (*context_release)(context_info);
+ }
+
+ return;
+}
+
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
static SCNetworkConnectionPrivateRef
-__SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef serviceID)
+__SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator,
+ CFStringRef serviceID,
+ SCNetworkConnectionCallBack callout,
+ SCNetworkConnectionContext *context)
{
- SCNetworkConnectionPrivateRef connectionPrivate = 0;
+ boolean_t active;
+ SCNetworkConnectionPrivateRef connectionPrivate = NULL;
+ void *data;
+ CFIndex dataLen;
+ CFDataRef dataRef = NULL;
+ char *envdebug;
+ int error = kSCStatusFailed;
+ CFMachPortContext mach_context = {0, NULL, NULL, NULL, NULL};
+ mach_port_t notify_port = MACH_PORT_NULL;
+ mach_port_t port_old;
+ mach_port_t server;
uint32_t size;
- struct ppp_status *stats = 0;
- int error = kSCStatusFailed;
+ kern_return_t status;
+ mach_port_t unpriv_bootstrap_port;
/* initialize runtime */
pthread_once(&initialized, __SCNetworkConnectionInitialize);
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionCreatePrivate:"));
+ if ((bootstrap_status (bootstrap_port, PPPCONTROLLER_SERVER, &active) != BOOTSTRAP_SUCCESS) ||
+ (bootstrap_look_up(bootstrap_port, PPPCONTROLLER_SERVER, &server) != BOOTSTRAP_SUCCESS)) {
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("PPP Controller server not found"));
+ goto fail;
+ }
/* allocate NetworkConnection */
size = sizeof(SCNetworkConnectionPrivate) - sizeof(CFRuntimeBase);
- connectionPrivate = (SCNetworkConnectionPrivateRef)_CFRuntimeCreateInstance(allocator, __kSCNetworkConnectionTypeID,size, NULL);
- if (connectionPrivate == 0)
+ connectionPrivate = (SCNetworkConnectionPrivateRef)_CFRuntimeCreateInstance(allocator, __kSCNetworkConnectionTypeID, size, NULL);
+ if (connectionPrivate == NULL) {
goto fail;
+ }
/* zero the data structure */
bzero(((u_char*)connectionPrivate)+sizeof(CFRuntimeBase), size);
/* save the serviceID */
connectionPrivate->serviceID = CFStringCreateCopy(NULL, serviceID);
- connectionPrivate->controlRef = -1;
- connectionPrivate->eventRef = -1;
+ /* get the debug environment variable */
+ envdebug = getenv("PPPDebug");
+ if (envdebug) {
+ if (sscanf(envdebug, "%d", &connectionPrivate->debug) != 1)
+ connectionPrivate->debug = 1; /* PPPDebug value is invalid, set debug to 1 */
+ }
+
+ if (callout != NULL) {
+ connectionPrivate->rlsFunction = callout;
+
+ mach_context.info = (void*)connectionPrivate;
+ connectionPrivate->notify_port = CFMachPortCreate(NULL, __SCNetworkConnectionCallBack, &mach_context, NULL);
+ if (connectionPrivate->notify_port == NULL) {
+ goto fail;
+ }
- if (PPPInit(&connectionPrivate->controlRef))
+ notify_port = CFMachPortGetPort(connectionPrivate->notify_port);
+ status = mach_port_request_notification(mach_task_self(),
+ notify_port, MACH_NOTIFY_NO_SENDERS, 1,
+ notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &port_old);
+ if (status != KERN_SUCCESS) {
+ goto fail;
+ }
+ }
+
+ if (context) {
+ bcopy(context, &connectionPrivate->rlsContext, sizeof(SCNetworkConnectionContext));
+ if (context->retain != NULL) {
+ connectionPrivate->rlsContext.info = (void *)(*context->retain)(context->info);
+ }
+ }
+
+ if (!_SCSerializeString(serviceID, &dataRef, &data, &dataLen)) {
goto fail;
+ }
- if (PPPStatus(connectionPrivate->controlRef, serviceID, 0, &stats)) {
- error = kSCStatusInvalidArgument; // XXX can't get status, invalid service id
+ status = bootstrap_unprivileged(bootstrap_port, &unpriv_bootstrap_port);
+ if (status != BOOTSTRAP_SUCCESS) {
goto fail;
}
- CFAllocatorDeallocate(NULL, stats);
- stats = 0;
+ status = pppcontroller_attach(server, data, dataLen, unpriv_bootstrap_port, notify_port,
+ &connectionPrivate->session_port, &error);
+
+ mach_port_deallocate(mach_task_self(), unpriv_bootstrap_port);
+ CFRelease(dataRef);
+ dataRef = NULL;
+
+ if (status != KERN_SUCCESS) {
+ goto fail;
+ }
+
+ if (error != kSCStatusOK) {
+ goto fail;
+ }
+
+ if (connectionPrivate->debug) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCreate (0x%x) succeeded for service ID: %@"), connectionPrivate, serviceID);
+ }
/* success, return the connection reference */
return connectionPrivate;
fail:
+
/* failure, clean up and leave */
- if (connectionPrivate)
+ if (connectionPrivate != NULL) {
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCreate (0x%x) failed for service ID: %@"), connectionPrivate, serviceID);
CFRelease(connectionPrivate);
- if (stats)
- CFAllocatorDeallocate(NULL, stats);
+ }
+
+ if (dataRef) CFRelease(dataRef);
_SCErrorSet(error);
return NULL;
}
------------------------------------------------------------------------------------------- */
CFTypeID
-SCNetworkConnectionGetTypeID (void) {
+SCNetworkConnectionGetTypeID(void) {
pthread_once(&initialized, __SCNetworkConnectionInitialize); /* initialize runtime */
return __kSCNetworkConnectionTypeID;
}
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-static SCNetworkConnectionStatus
-__SCNetworkConnectionConvertStatus (int state)
-{
- SCNetworkConnectionStatus status = kSCNetworkConnectionDisconnected;
-
- switch (state) {
- case PPP_INITIALIZE:
- case PPP_CONNECTLINK:
- case PPP_ESTABLISH:
- case PPP_AUTHENTICATE:
- case PPP_CALLBACK:
- case PPP_NETWORK:
- case PPP_WAITONBUSY:
- status = kSCNetworkConnectionConnecting;
- break;
- case PPP_TERMINATE:
- case PPP_DISCONNECTLINK:
- case PPP_HOLDOFF:
- status = kSCNetworkConnectionDisconnecting;
- break;
- case PPP_RUNNING:
- case PPP_ONHOLD:
- status = kSCNetworkConnectionConnected;
- break;
- case PPP_IDLE:
- case PPP_STATERESERVED:
- default:
- status = kSCNetworkConnectionDisconnected;
- }
- return status;
-}
-
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
SCNetworkConnectionRef
-SCNetworkConnectionCreateWithServiceID (CFAllocatorRef allocator,
- CFStringRef serviceID,
- SCNetworkConnectionCallBack callout,
- SCNetworkConnectionContext *context)
+SCNetworkConnectionCreateWithServiceID(CFAllocatorRef allocator,
+ CFStringRef serviceID,
+ SCNetworkConnectionCallBack callout,
+ SCNetworkConnectionContext *context)
{
SCNetworkConnectionPrivateRef connectionPrivate;
return NULL;
}
- connectionPrivate = __SCNetworkConnectionCreatePrivate(allocator, serviceID);
-
- if (connectionPrivate) {
- connectionPrivate->rlsFunction = callout;
- if (context) {
- bcopy(context, &connectionPrivate->rlsContext, sizeof(SCNetworkConnectionContext));
- if (context->retain) {
- connectionPrivate->rlsContext.info = (void *)context->retain(context->info);
- }
- }
- }
+ connectionPrivate = __SCNetworkConnectionCreatePrivate(allocator, serviceID, callout, context);
return (SCNetworkConnectionRef)connectionPrivate;
}
------------------------------------------------------------------------------------------- */
CFStringRef
-SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyServiceID(SCNetworkConnectionRef connection)
{
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
------------------------------------------------------------------------------------------- */
CFDictionaryRef
-SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyStatistics(SCNetworkConnectionRef connection)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ void *data = NULL;
+ int datalen;
int error = kSCStatusFailed;
- struct ppp_status *stats = 0;
- CFMutableDictionaryRef dict = 0;
- CFMutableDictionaryRef statsdict = 0;
-
-#define ADDNUMBER(d, k, n) \
-{ \
- CFNumberRef num; \
- num = CFNumberCreate(NULL, kCFNumberSInt32Type, n); \
- if (num) { \
- CFDictionaryAddValue(d, k, num); \
- CFRelease(num); \
- } \
-}
+ CFPropertyListRef statistics = NULL;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
- /* get status and check connected state */
- if (PPPStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &stats))
- goto fail;
-
- if (__SCNetworkConnectionConvertStatus(stats->status) != kSCNetworkConnectionConnected)
+ status = pppcontroller_copystatistics(connectionPrivate->session_port, (xmlDataOut_t *)&data, &datalen, &error);
+ if (status != KERN_SUCCESS) {
goto fail;
+ }
- /* create dictionaries */
- if ((statsdict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0)
+ if (error != kSCStatusOK) {
goto fail;
+ }
- if ((dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0)
+ if ((data == NULL) ||
+ !_SCUnserialize(&statistics, NULL, data, datalen) ||
+ !isA_CFDictionary(statistics)) {
goto fail;
+ }
- /* add statistics */
- ADDNUMBER(dict, kSCNetworkConnectionBytesIn, &stats->s.run.inBytes);
- ADDNUMBER(dict, kSCNetworkConnectionBytesOut, &stats->s.run.outBytes);
- ADDNUMBER(dict, kSCNetworkConnectionPacketsIn, &stats->s.run.inPackets);
- ADDNUMBER(dict, kSCNetworkConnectionPacketsOut, &stats->s.run.outPackets);
- ADDNUMBER(dict, kSCNetworkConnectionErrorsIn, &stats->s.run.inErrors);
- ADDNUMBER(dict, kSCNetworkConnectionErrorsOut, &stats->s.run.outErrors);
-
- /* add the PPP dictionary to the statistics dictionary */
- CFDictionaryAddValue(statsdict, kSCEntNetPPP, dict);
- CFRelease(dict);
-
- /* done */
- CFAllocatorDeallocate(NULL, stats);
- return statsdict;
+ return statistics;
fail:
- if (stats)
- CFAllocatorDeallocate(NULL, stats);
- if (dict)
- CFRelease(dict);
- if (statsdict)
- CFRelease(statsdict);
+ if (statistics) CFRelease(statistics);
_SCErrorSet(error);
return NULL;
}
------------------------------------------------------------------------------------------- */
SCNetworkConnectionStatus
-SCNetworkConnectionGetStatus (SCNetworkConnectionRef connection)
+SCNetworkConnectionGetStatus(SCNetworkConnectionRef connection)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
- struct ppp_status *stats = 0;
- SCNetworkConnectionStatus status;
+ int error = kSCStatusFailed;
+ int phase;
+ SCNetworkConnectionStatus scstatus;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
- return NULL;
+ return kSCNetworkConnectionInvalid;
}
- if (PPPStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &stats))
- return kSCNetworkConnectionDisconnected; // XXX
-
- status = __SCNetworkConnectionConvertStatus(stats->status);
+ status = pppcontroller_getstatus(connectionPrivate->session_port, &phase, &error);
+ if ((status != KERN_SUCCESS) || (error != kSCStatusOK)) {
+ return kSCNetworkConnectionDisconnected;
+ }
- CFAllocatorDeallocate(NULL, stats);
- return status;
+ scstatus = __SCNetworkConnectionConvertStatus(phase);
+ return scstatus;
}
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
+
CFDictionaryRef
-SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyExtendedStatus(SCNetworkConnectionRef connection)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
- CFPropertyListRef status = 0;
- void *data = 0;
- u_int32_t datalen;
+ void *data = NULL;
+ int datalen;
+ int error = kSCStatusFailed;
+ CFPropertyListRef extstatus = NULL;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
- if (PPPExtendedStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &data, &datalen))
+ status = pppcontroller_copyextendedstatus(connectionPrivate->session_port, (xmlDataOut_t *)&data, &datalen, &error);
+ if (status != KERN_SUCCESS) {
goto fail;
+ }
- if (!data
- || !(status = PPPUnserialize(data, datalen))
- || !isA_CFDictionary(status))
+ if (error != kSCStatusOK) {
goto fail;
+ }
- CFAllocatorDeallocate(NULL, data);
- return status;
+ if ((data == NULL) ||
+ !_SCUnserialize(&extstatus, NULL, data, datalen) ||
+ !isA_CFDictionary(extstatus)) {
+ goto fail;
+ }
+
+ return extstatus;
fail:
- _SCErrorSet(kSCStatusFailed);
- if (status)
- CFRelease(status);
- if (data)
- CFAllocatorDeallocate(NULL, data);
+ if (extstatus) CFRelease(extstatus);
+ _SCErrorSet(error);
return NULL;
}
------------------------------------------------------------------------------------------- */
Boolean
-SCNetworkConnectionStart (SCNetworkConnectionRef connection,
- CFDictionaryRef userOptions,
- Boolean linger)
+SCNetworkConnectionStart(SCNetworkConnectionRef connection,
+ CFDictionaryRef userOptions,
+ Boolean linger)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
- CFDataRef dataref = 0;
- void *data = 0;
- u_int32_t datalen = 0;
+ CFDataRef dataref = NULL;
+ void *data = NULL;
+ CFIndex datalen = 0;
+ int error = kSCStatusFailed;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
- return NULL;
+ return FALSE;
}
- if (userOptions && !(dataref = PPPSerialize(userOptions, &data, &datalen)))
+ if (connectionPrivate->debug) {
+ CFMutableDictionaryRef mdict = NULL, mdict1;
+ CFDictionaryRef dict;
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStart (0x%x)"), connectionPrivate);
+
+ if (userOptions) {
+ /* special code to remove secret information */
+ mdict = CFDictionaryCreateMutableCopy(0, 0, userOptions);
+ if (mdict) {
+ dict = CFDictionaryGetValue(mdict, kSCEntNetPPP);
+ if (isA_CFDictionary(dict)) {
+ mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict);
+ if (mdict1) {
+ CFDictionaryReplaceValue(mdict1, kSCPropNetPPPAuthPassword, CFSTR("******"));
+ CFDictionarySetValue(mdict, kSCEntNetPPP, mdict1);
+ CFRelease(mdict1);
+ }
+ }
+
+ dict = CFDictionaryGetValue(mdict, kSCEntNetL2TP);
+ if (isA_CFDictionary(dict)) {
+ mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict);
+ if (mdict1) {
+ CFDictionaryReplaceValue(mdict1, kSCPropNetL2TPIPSecSharedSecret, CFSTR("******"));
+ CFDictionarySetValue(mdict, kSCEntNetL2TP, mdict1);
+ CFRelease(mdict1);
+ }
+ }
+
+ dict = CFDictionaryGetValue(mdict, kSCEntNetIPSec);
+ if (isA_CFDictionary(dict)) {
+ mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict);
+ if (mdict1) {
+ CFDictionaryReplaceValue(mdict1, kSCPropNetIPSecSharedSecret, CFSTR("******"));
+ CFDictionarySetValue(mdict, kSCEntNetIPSec, mdict1);
+ CFRelease(mdict1);
+ }
+ }
+ }
+ }
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("User options: %@"), mdict);
+ if (mdict)
+ CFRelease(mdict);
+ }
+
+ if (userOptions && !_SCSerialize(userOptions, &dataref, &data, &datalen)) {
goto fail;
+ }
- if (PPPConnect(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, data, datalen, linger))
+ status = pppcontroller_start(connectionPrivate->session_port, data, datalen, linger, &error);
+ if (status != KERN_SUCCESS) {
goto fail;
+ }
- if (dataref)
+ if (dataref) {
CFRelease(dataref);
+ dataref = NULL;
+ }
+
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStart (0x%x), return: %d"), connectionPrivate, error);
+
+ if (error != kSCStatusOK) {
+ goto fail;
+ }
/* connection is now started */
return TRUE;
fail:
- if (dataref)
- CFRelease(dataref);
- _SCErrorSet(kSCStatusFailed); // XXX
+ if (dataref) CFRelease(dataref);
+ _SCErrorSet(error);
return FALSE;
}
------------------------------------------------------------------------------------------- */
Boolean
-SCNetworkConnectionStop (SCNetworkConnectionRef connection,
- Boolean forceDisconnect)
+SCNetworkConnectionStop(SCNetworkConnectionRef connection,
+ Boolean forceDisconnect)
{
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ int error = kSCStatusFailed;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
- if (PPPDisconnect(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, forceDisconnect)) {
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStop (0x%x)"), connectionPrivate);
+
+ status = pppcontroller_stop(connectionPrivate->session_port, forceDisconnect, &error);
+ if (status != KERN_SUCCESS) {
+ goto fail;
+ }
+
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStop (0x%x), return: %d"), connectionPrivate, error);
+
+ if (error != kSCStatusOK) {
+ goto fail;
}
/* connection is now disconnecting */
return TRUE;
+
+ fail:
+
+ _SCErrorSet(error);
+ return FALSE;
}
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
Boolean
-SCNetworkConnectionSuspend (SCNetworkConnectionRef connection)
+SCNetworkConnectionSuspend(SCNetworkConnectionRef connection)
{
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ int error = kSCStatusFailed;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
- return NULL;
+ return FALSE;
}
- if (PPPSuspend(connectionPrivate->controlRef, connectionPrivate->serviceID, 0)) {
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionSuspend (0x%x)"), connectionPrivate);
+
+ status = pppcontroller_suspend(connectionPrivate->session_port, &error);
+ if (status != KERN_SUCCESS) {
+ goto fail;
+ }
+
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionSuspend (0x%x), return: %d"), connectionPrivate, error);
+
+ if (error != kSCStatusOK) {
+ goto fail;
}
/* connection is now suspended */
return TRUE;
+
+ fail:
+
+ _SCErrorSet(error);
+ return FALSE;
}
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
Boolean
-SCNetworkConnectionResume (SCNetworkConnectionRef connection)
+SCNetworkConnectionResume(SCNetworkConnectionRef connection)
{
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ int error = kSCStatusFailed;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
- return NULL;
+ return FALSE;
}
- if (PPPResume(connectionPrivate->controlRef, connectionPrivate->serviceID, 0)) {
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionResume (0x%x)"), connectionPrivate);
+
+ status = pppcontroller_resume(connectionPrivate->session_port, &error);
+ if (status != KERN_SUCCESS) {
+ goto fail;
+ }
+
+ if (connectionPrivate->debug)
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionResume (0x%x), return: %d"), connectionPrivate, error);
+
+ if (error != kSCStatusOK) {
+ goto fail;
}
/* connection is now resume */
return TRUE;
+
+ fail:
+
+ _SCErrorSet(error);
+ return FALSE;
}
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
CFDictionaryRef
-SCNetworkConnectionCopyUserOptions (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyUserOptions(SCNetworkConnectionRef connection)
{
SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
- void *data = 0;
- u_int32_t datalen;
- CFPropertyListRef userOptions = 0;
+ void *data = NULL;
+ int datalen;
+ int error = kSCStatusFailed;
+ kern_return_t status;
+ CFPropertyListRef userOptions = NULL;
if (!isA_SCNetworkConnection(connection)) {
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
- if (PPPGetConnectData(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &data, &datalen))
+ status = pppcontroller_copyuseroptions(connectionPrivate->session_port, (xmlDataOut_t *)&data, &datalen, &error);
+ if (status != KERN_SUCCESS) {
goto fail;
+ }
+
+ if (error != kSCStatusOK) {
+ goto fail;
+ }
// no data were used, return an empty dictionary
- if (data == 0) {
+ if (data == NULL) {
CFDictionaryRef dict;
dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- if (dict == 0)
+ if (dict == NULL) {
_SCErrorSet(kSCStatusFailed); // XXX
+ }
return dict;
}
- userOptions = PPPUnserialize(data, datalen);
- if (!isA_CFDictionary(userOptions))
+ if (!_SCUnserialize(&userOptions, NULL, data, datalen) ||
+ !isA_CFDictionary(userOptions)) {
goto fail;
+ }
- CFAllocatorDeallocate(NULL, data);
return userOptions;
fail:
- _SCErrorSet(kSCStatusFailed);
- if (userOptions)
- CFRelease(userOptions);
- if (data)
- CFAllocatorDeallocate(NULL, data);
+ if (userOptions) CFRelease(userOptions);
+ _SCErrorSet(error);
return NULL;
}
/* -------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------- */
-static Boolean
-__isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
- CFIndex i;
- CFIndex n = CFArrayGetCount(rlList);
-
- for (i = 0; i < n; i += 3) {
- if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- continue;
- }
- if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
- continue;
- }
- if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
- continue;
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-static void
-__schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
- CFArrayAppendValue(rlList, obj);
- CFArrayAppendValue(rlList, runLoop);
- CFArrayAppendValue(rlList, runLoopMode);
-
- return;
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-static Boolean
-__unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
-{
- CFIndex i = 0;
- Boolean found = FALSE;
- CFIndex n = CFArrayGetCount(rlList);
-
- while (i < n) {
- if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- i += 3;
- continue;
- }
- if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
- i += 3;
- continue;
- }
- if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
- i += 3;
- continue;
- }
-
- found = TRUE;
-
- CFArrayRemoveValueAtIndex(rlList, i + 2);
- CFArrayRemoveValueAtIndex(rlList, i + 1);
- CFArrayRemoveValueAtIndex(rlList, i);
-
- if (!all) {
- return found;
- }
-
- n -= 3;
- }
-
- return found;
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-
-static void
-__SCNetworkConnectionCallBack(CFSocketRef inref,
- CFSocketCallBackType type,
- CFDataRef address,
- const void *data,
- void *info)
-{
- void *context_info;
- void (*context_release)(const void *);
- SCNetworkConnectionRef connection = (SCNetworkConnectionRef)info;
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
- SCNetworkConnectionCallBack rlsFunction;
- SCNetworkConnectionStatus status;
- int pppstatus;
- int err;
-
- err = PPPReadEvent(connectionPrivate->eventRef, &pppstatus);
- if (err)
- return;
-
- rlsFunction = connectionPrivate->rlsFunction;
- if (connectionPrivate->rlsContext.retain && connectionPrivate->rlsContext.info) {
- context_info = (void *)connectionPrivate->rlsContext.retain(connectionPrivate->rlsContext.info);
- context_release = connectionPrivate->rlsContext.release;
- }
- else {
- context_info = connectionPrivate->rlsContext.info;
- context_release = NULL;
- }
-
- status = __SCNetworkConnectionConvertStatus(pppstatus);
-
- (*rlsFunction)(connection, status, context_info);
- if (context_release && context_info) {
- context_release(context_info);
- }
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-
Boolean
SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef connection,
CFRunLoopRef runLoop,
CFStringRef runLoopMode)
{
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
- //CFSocketRef ref;
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ int error = kSCStatusFailed;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
- if (connectionPrivate->rlsFunction == 0) {
+ if (connectionPrivate->rlsFunction == NULL) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
- if (connectionPrivate->rlList
- && __isScheduled(NULL, runLoop, runLoopMode, connectionPrivate->rlList)) {
+ if ((connectionPrivate->rlList != NULL) &&
+ _SC_isScheduled(NULL, runLoop, runLoopMode, connectionPrivate->rlList)) {
/* already scheduled */
_SCErrorSet(kSCStatusFailed);
return FALSE;
}
- if (connectionPrivate->eventRef == -1) {
- CFSocketContext context = { 0, (void*)connection, CFRetain, CFRelease, CFCopyDescription };
-
- if (PPPInit(&connectionPrivate->eventRef)) {
- _SCErrorSet(kSCStatusFailed);
+ if (connectionPrivate->rlList == NULL) {
+ status = pppcontroller_notification(connectionPrivate->session_port, 1, &error);
+ if ((status != KERN_SUCCESS) || (error != kSCStatusOK)) {
+ _SCErrorSet(error);
return FALSE;
}
- PPPEnableEvents(connectionPrivate->eventRef, connectionPrivate->serviceID, 0, 1);
-
- connectionPrivate->eventRefCF = CFSocketCreateWithNative(NULL, connectionPrivate->eventRef,
- kCFSocketReadCallBack, __SCNetworkConnectionCallBack, &context);
- connectionPrivate->rls = CFSocketCreateRunLoopSource(NULL, connectionPrivate->eventRefCF, 0);
+ connectionPrivate->rls = CFMachPortCreateRunLoopSource(NULL, connectionPrivate->notify_port, 0);
connectionPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
- //CFRelease(ref);
}
CFRunLoopAddSource(runLoop, connectionPrivate->rls, runLoopMode);
- __schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList);
+ _SC_schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList);
return TRUE;
}
CFRunLoopRef runLoop,
CFStringRef runLoopMode)
{
- SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ SCNetworkConnectionPrivateRef connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+ int error = kSCStatusFailed;
+ kern_return_t status;
if (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) {
_SCErrorSet(kSCStatusInvalidArgument);
return FALSE;
}
- if (connectionPrivate->rlList == NULL
- || !__unschedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList, FALSE)) {
+ if ((connectionPrivate->rlList == NULL) ||
+ !_SC_unschedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList, FALSE)) {
/* if not currently scheduled */
_SCErrorSet(kSCStatusFailed);
return FALSE;
connectionPrivate->rls = NULL;
CFRelease(connectionPrivate->rlList);
connectionPrivate->rlList = NULL;
- //PPPDispose(connectionPrivate->eventRef);
- CFSocketInvalidate(connectionPrivate->eventRefCF);
- CFRelease(connectionPrivate->eventRefCF);
- connectionPrivate->eventRefCF = 0;
- connectionPrivate->eventRef = -1;
+
+ status = pppcontroller_notification(connectionPrivate->session_port, 0, &error);
+ if ((status != KERN_SUCCESS) || (error != kSCStatusOK)) {
+ _SCErrorSet(error);
+ return FALSE;
+ }
}
return TRUE;
//************************* USER LEVEL DIAL API **********************************
+#define k_NetworkConnect_Notification "com.apple.networkConnect"
#define k_NetworkConnect_Pref_File CFSTR("com.apple.networkConnect")
#define k_InterentConnect_Pref_File CFSTR("com.apple.internetconnect")
static Boolean SCNetworkConnectionPrivateCopyDefaultServiceIDForDial (SCDynamicStoreRef session, CFStringRef *serviceID);
static Boolean SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore (SCDynamicStoreRef session, CFStringRef *serviceID);
static Boolean SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptionsArray, CFDictionaryRef *userOptions);
-static Boolean SCNetworkConnectionPrivateIsPPPService (SCDynamicStoreRef session, CFStringRef serviceID);
-static void addPasswordFromKeychain(CFDictionaryRef *userOptions);
-static CFArrayRef copyKeychainEnumerator(CFStringRef uniqueIdentifier);
+static Boolean SCNetworkConnectionPrivateIsPPPService (SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2);
+static void addPasswordFromKeychain (SCDynamicStoreRef session, CFStringRef serviceID, CFDictionaryRef *userOptions);
+static CFStringRef copyPasswordFromKeychain (CFStringRef uniqueID);
+static CFArrayRef copyKeychainEnumerator (CFStringRef uniqueIdentifier);
+
+static uint32_t notify_userprefs_token = -1;
+
+/*
+ * return TRUE if domain1 ends with domain2, and will check for trailing "."
+ */
+static Boolean
+domainEndsWithDomain(CFStringRef domain1, CFStringRef domain2)
+{
+ CFRange range;
+ Boolean ret = FALSE;
+ CFStringRef s1 = NULL;
+ Boolean s1_created = FALSE;
+ CFStringRef s2 = NULL;
+ Boolean s2_created = FALSE;
+
+ if (CFStringHasSuffix(domain1, CFSTR("."))) {
+ range.location = 0;
+ range.length = CFStringGetLength(domain1) - 1;
+ s1 = CFStringCreateWithSubstring(NULL, domain1, range);
+ if (s1 == NULL) {
+ goto done;
+ }
+ s1_created = TRUE;
+ } else {
+ s1 = domain1;
+ }
+
+ if (CFStringHasSuffix(domain2, CFSTR("."))) {
+ range.location = 0;
+ range.length = CFStringGetLength(domain2) - 1;
+ s2 = CFStringCreateWithSubstring(NULL, domain2, range);
+ if (s2 == NULL) {
+ goto done;
+ }
+ s2_created = TRUE;
+ } else {
+ s2 = domain2;
+ }
+
+ ret = CFStringHasSuffix(s1, s2);
+
+ done :
+
+ if (s1_created) CFRelease(s1);
+ if (s2_created) CFRelease(s2);
+ return ret;
+}
+
Boolean
-SCNetworkConnectionCopyUserPreferences (CFDictionaryRef selectionOptions,
- CFStringRef *serviceID,
- CFDictionaryRef *userOptions)
+SCNetworkConnectionCopyUserPreferences(CFDictionaryRef selectionOptions,
+ CFStringRef *serviceID,
+ CFDictionaryRef *userOptions)
{
- SCDynamicStoreRef session = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkConnection"), NULL, NULL);
- Boolean success = FALSE;
+ int debug = 0;
+ char *envdebug;
+ int prefsChanged;
+ SCDynamicStoreRef session;
+ Boolean success = FALSE;
+ int status;
+
+ envdebug = getenv("PPPDebug");
+ if (envdebug) {
+ if (sscanf(envdebug, "%d", &debug) != 1)
+ debug = 1; /* PPPDebug value is invalid, set debug to 1 */
+ }
+
+ if (notify_userprefs_token == -1) {
+ status = notify_register_check(k_NetworkConnect_Notification, ¬ify_userprefs_token);
+ if (status != NOTIFY_STATUS_OK)
+ notify_userprefs_token = -1;
+ else
+ // clear the flag
+ notify_check(notify_userprefs_token, &prefsChanged);
+ }
+
+ prefsChanged = 1;
+ if (notify_userprefs_token != -1)
+ notify_check(notify_userprefs_token, &prefsChanged);
+
// NOTE: we are currently ignoring selectionOptions
- if (session != NULL) {
- // (1) Figure out which service ID we care about, allocate it into passed "serviceID"
- success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(session, serviceID);
-
- if (success && (*serviceID != NULL)) {
- // (2) Get the list of user data for this service ID
- CFPropertyListRef userServices = CFPreferencesCopyValue(*serviceID,
- k_NetworkConnect_Pref_File,
- kCFPreferencesCurrentUser,
- kCFPreferencesCurrentHost);
-
- // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't
- if (userServices != NULL) {
- if (isA_CFArray(userServices)) {
- // (4) Get the default set of user options for this service
- success = SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(
- (CFArrayRef)userServices,
- userOptions);
- if(success && userOptions != NULL)
- {
- addPasswordFromKeychain(userOptions);
+ *serviceID = NULL;
+ *userOptions = NULL;
+
+ session = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkConnection"), NULL, NULL);
+ if (session == NULL) {
+ fprintf(stderr, "Error, SCNetworkConnectionCopyUserPreferences, SCDynamicStoreCreate() returned NULL!\n");
+ return FALSE;
+ }
+
+ if (selectionOptions) {
+ Boolean catchAllFound = FALSE;
+ CFIndex catchAllService = 0;
+ CFIndex catchAllConfig = 0;
+ CFStringRef hostName = NULL;
+ CFStringRef priority = NULL;
+ CFArrayRef serviceNames = NULL;
+ CFDictionaryRef services = NULL;
+ CFIndex serviceIndex;
+ CFIndex servicesCount;
+
+ hostName = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandHostName);
+ if (!isA_CFString(hostName))
+ hostName = NULL;
+
+ // can't select anything
+ if (hostName == NULL)
+ goto done_selection;
+
+ priority = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandPriority);
+ if (!isA_CFString(priority))
+ priority = kSCValNetPPPOnDemandPriorityDefault;
+
+
+ if (!isA_CFArray(serviceNames))
+ goto done_selection;
+
+
+ if (!isA_CFDictionary(services))
+ goto done_selection;
+
+ servicesCount = CFArrayGetCount(serviceNames);
+ for (serviceIndex = 0; serviceIndex < servicesCount; serviceIndex++) {
+ CFIndex configIndex;
+ CFIndex configsCount;
+ CFArrayRef serviceConfigs;
+ CFStringRef serviceName;
+ int val;
+
+ serviceName = CFArrayGetValueAtIndex(serviceNames, serviceIndex);
+ if (!isA_CFString(serviceName))
+ continue;
+
+ serviceConfigs = CFDictionaryGetValue(services, serviceName);
+ if (!isA_CFArray(serviceConfigs))
+ continue;
+
+ configsCount = CFArrayGetCount(serviceConfigs);
+ for (configIndex = 0; configIndex < configsCount; configIndex++) {
+ CFNumberRef autodial;
+ CFDictionaryRef config;
+ CFDictionaryRef pppConfig;
+
+ config = CFArrayGetValueAtIndex(serviceConfigs, configIndex);
+ if (!isA_CFDictionary(config))
+ continue;
+
+ pppConfig = CFDictionaryGetValue(config, kSCEntNetPPP);
+ if (!isA_CFDictionary(pppConfig))
+ continue;
+
+ autodial = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandEnabled);
+ if (!isA_CFNumber(autodial))
+ continue;
+
+ CFNumberGetValue(autodial, kCFNumberIntType, &val);
+ if (val) {
+ CFArrayRef autoDomains;
+ CFIndex domainIndex;
+ CFIndex domainsCount;
+
+ /* we found an conditional connection enabled configuration */
+
+ /* check domain */
+ autoDomains = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandDomains);
+ if (!isA_CFArray(autoDomains))
+ continue;
+
+ domainsCount = CFArrayGetCount(autoDomains);
+ for (domainIndex = 0; domainIndex < domainsCount; domainIndex++) {
+ CFStringRef domain;
+
+ domain = CFArrayGetValueAtIndex(autoDomains, domainIndex);
+ if (!isA_CFString(domain))
+ continue;
+
+ if (!catchAllFound &&
+ (CFStringCompare(domain, CFSTR(""), 0) == kCFCompareEqualTo
+ || CFStringCompare(domain, CFSTR("."), 0) == kCFCompareEqualTo)) {
+ // found a catch all
+ catchAllFound = TRUE;
+ catchAllService = serviceIndex;
+ catchAllConfig = configIndex;
+ }
+
+ if (domainEndsWithDomain(hostName, domain)) {
+ // found matching configuration
+ *serviceID = serviceName;
+ CFRetain(*serviceID);
+ *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
+ CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandHostName, hostName);
+ CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
+ addPasswordFromKeychain(session, *serviceID, userOptions);
+ success = TRUE;
+ goto done_selection;
+ }
}
- } else {
- fprintf(stderr, "Error, userServices are not of type CFArray!\n");
}
-
- CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL
}
}
+ // config not found, do we have a catchall ?
+ if (catchAllFound) {
+ CFDictionaryRef config;
+ CFArrayRef serviceConfigs;
+ CFStringRef serviceName;
+
+ serviceName = CFArrayGetValueAtIndex(serviceNames, catchAllService);
+ serviceConfigs = CFDictionaryGetValue(services, serviceName);
+ config = CFArrayGetValueAtIndex(serviceConfigs, catchAllConfig);
+
+ *serviceID = serviceName;
+ CFRetain(*serviceID);
+ *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
+ CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandHostName, hostName);
+ CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
+ addPasswordFromKeychain(session, *serviceID, userOptions);
+ success = TRUE;
+ goto done_selection;
+ }
+
+ done_selection:
+
+ if (serviceNames)
+ CFRelease(serviceNames);
+ if (services)
+ CFRelease(services);
CFRelease(session);
- } else {
- fprintf(stderr, "Error, SCNetworkConnectionCopyUserPreferences, SCDynamicStoreCreate() returned NULL!\n");
+
+ if (debug > 1) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@"), success ? CFSTR("succeeded") : CFSTR("failed"));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("Selection options: %@"), selectionOptions);
+ }
+
+ return success;
}
+ /* we don't have selection options */
+
+ // (1) Figure out which service ID we care about, allocate it into passed "serviceID"
+ success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(session, serviceID);
+
+ if (success && (*serviceID != NULL)) {
+ // (2) Get the list of user data for this service ID
+ CFPropertyListRef userServices = NULL;
+
+
+ // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't
+ if (userServices != NULL) {
+ if (isA_CFArray(userServices)) {
+ // (4) Get the default set of user options for this service
+ success = SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray((CFArrayRef)userServices,
+ userOptions);
+ if(success && (userOptions != NULL)) {
+ addPasswordFromKeychain(session, *serviceID, userOptions);
+ }
+ } else {
+ fprintf(stderr, "Error, userServices are not of type CFArray!\n");
+ }
+
+ CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL
+ }
+ }
+
+ if (debug > 1) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@, no selection options"), success ? CFSTR("succeeded") : CFSTR("failed"));
+ }
+
+ CFRelease(session);
return success;
}
+
//*******************************************************************************************
// SCNetworkConnectionPrivateCopyDefaultServiceIDForDial
// ----------------------------------------------------
Boolean foundService = FALSE;
CFPropertyListRef lastServiceSelectedInIC = NULL;
- // NULL out the pointer
- *serviceID = NULL;
-
- // read out the last service from the Internet Connect preference file
- lastServiceSelectedInIC = CFPreferencesCopyValue(k_Last_Service_Id_Key,
- k_InterentConnect_Pref_File,
- kCFPreferencesCurrentUser,
- kCFPreferencesAnyHost);
// we found the service the user last had open in IC
if (lastServiceSelectedInIC != NULL) {
// make sure its a PPP service
- if (SCNetworkConnectionPrivateIsPPPService(session, lastServiceSelectedInIC)) {
+ if (SCNetworkConnectionPrivateIsPPPService(session, lastServiceSelectedInIC, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
// make sure the service that we found is valid
CFDictionaryRef dict;
CFStringRef key;
kSCEntNetInterface);
dict = SCDynamicStoreCopyValue(session, key);
CFRelease(key);
- if (dict) {
+ if (dict != NULL) {
+ CFRelease(dict);
*serviceID = CFRetain(lastServiceSelectedInIC);
foundService = TRUE;
- CFRelease(dict);
}
}
CFRelease(lastServiceSelectedInIC);
static Boolean
SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef session, CFStringRef *serviceID)
{
- Boolean success = FALSE;
- CFStringRef key = NULL;
CFDictionaryRef dict = NULL;
+ CFStringRef key = NULL;
CFArrayRef serviceIDs = NULL;
+ Boolean success = FALSE;
*serviceID = NULL;
}
dict = SCDynamicStoreCopyValue(session, key);
- if (dict == NULL) {
- fprintf(stderr, "Error, Dictionary for setup key == NULL!\n");
+ if (!isA_CFDictionary(dict)) {
+ fprintf(stderr, "no global IPv4 entity\n");
break;
}
serviceIDs = CFDictionaryGetValue(dict, kSCPropNetServiceOrder); // array of service id's
- if (isA_CFArray(serviceIDs) == NULL) {
- if (serviceIDs == NULL)
- fprintf(stderr, "Error, Array of service IDs == NULL!\n");
- else
- fprintf(stderr, "Error, serviceIds are not of type CFArray!\n");
+ if (!isA_CFArray(serviceIDs)) {
+ fprintf(stderr, "service order not specified\n");
break;
}
for (i = 0; i < count; i++) {
CFStringRef service = CFArrayGetValueAtIndex(serviceIDs, i);
- if (SCNetworkConnectionPrivateIsPPPService(session, service)) {
+ if (SCNetworkConnectionPrivateIsPPPService(session, service, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
*serviceID = CFRetain(service);
success = TRUE;
break;
}
} while (FALSE);
- if (key != NULL)
- CFRelease(key);
-
- if (dict != NULL)
- CFRelease(dict);
+ if (key != NULL) CFRelease(key);
+ if (dict != NULL) CFRelease(dict);
return success;
}
CFIndex count = CFArrayGetCount(userOptionsArray);
int i;
- *userOptions = NULL;
-
for (i = 0; i < count; i++) {
// (1) Find the dictionary
CFPropertyListRef propertyList = CFArrayGetValueAtIndex(userOptionsArray, i);
if (isA_CFDictionary(propertyList) != NULL) {
// See if there's a value for dial on demand
- CFPropertyListRef value = CFDictionaryGetValue((CFDictionaryRef)propertyList,
- k_Dial_Default_Key);
+ CFPropertyListRef value;
+
+ value = CFDictionaryGetValue((CFDictionaryRef)propertyList, k_Dial_Default_Key);
if (isA_CFBoolean(value) != NULL) {
if (CFBooleanGetValue(value)) {
// we found the default user options
}
//********************************************************************************
-// SCNetworkConnectionPrivateIsPPPService
+// SCNetworkConnectionPrivateIsServiceType
// --------------------------------------
-// Check and see if the service is a PPP service
+// Check and see if the service is a PPP service of the given types
//********************************************************************************
static Boolean
-SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID)
+SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2)
{
CFStringRef entityKey;
- Boolean isPPPService = FALSE;
- Boolean isModemOrPPPoE = FALSE;
+ Boolean isPPPService = FALSE;
+ Boolean isMatchingSubType = FALSE;
+ CFDictionaryRef serviceDict;
entityKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
kSCDynamicStoreDomainSetup,
serviceID,
kSCEntNetInterface);
- if (entityKey != NULL) {
- CFDictionaryRef serviceDict;
-
- serviceDict = SCDynamicStoreCopyValue(session, entityKey);
- if (serviceDict != NULL) {
- if (isA_CFDictionary(serviceDict)) {
- CFStringRef type;
- CFStringRef subtype;
-
- type = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceType);
- if (isA_CFString(type)) {
- isPPPService = CFEqual(type, kSCValNetInterfaceTypePPP);
- }
+ if (entityKey == NULL) {
+ return FALSE;
+ }
- subtype = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceSubType);
- if (isA_CFString(subtype)) {
- isModemOrPPPoE = (CFEqual(subtype, kSCValNetInterfaceSubTypePPPSerial) ||
- CFEqual(subtype, kSCValNetInterfaceSubTypePPPoE));
- }
+ serviceDict = SCDynamicStoreCopyValue(session, entityKey);
+ if (serviceDict != NULL) {
+ if (isA_CFDictionary(serviceDict)) {
+ CFStringRef type;
+ CFStringRef subtype;
+
+ type = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceType);
+ if (isA_CFString(type)) {
+ isPPPService = CFEqual(type, kSCValNetInterfaceTypePPP);
+ }
+
+ subtype = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceSubType);
+ if (isA_CFString(subtype)) {
+ isMatchingSubType = CFEqual(subtype, subType1);
+ if (!isMatchingSubType && subType2)
+ isMatchingSubType = CFEqual(subtype, subType2);
}
- CFRelease(serviceDict);
}
- CFRelease(entityKey);
+ CFRelease(serviceDict);
}
+ CFRelease(entityKey);
- return (isPPPService && isModemOrPPPoE);
+ return (isPPPService && isMatchingSubType);
}
//********************************************************************************
// addPasswordFromKeychain
// --------------------------------------
-// Get the password out of the keychain and add it to the PPP dictionary
+// Get the password and shared secret out of the keychain and add
+// them to the PPP and IPSec dictionaries
//********************************************************************************
static void
-addPasswordFromKeychain(CFDictionaryRef *userOptions)
+addPasswordFromKeychain(SCDynamicStoreRef session, CFStringRef serviceID, CFDictionaryRef *userOptions)
{
- CFArrayRef enumerator;
- CFIndex n;
- CFDictionaryRef oldDict;
- CFPropertyListRef uniqueID = NULL;
+ CFPropertyListRef uniqueID;
+ CFStringRef password;
+ CFStringRef sharedsecret = NULL;
+
+ /* user options must exist */
+ if (*userOptions == NULL)
+ return;
- oldDict = *userOptions;
- if(oldDict == NULL) {
- return; // if no userOptions
+ /* first, get the unique identifier used to store passwords in the keychain */
+ uniqueID = CFDictionaryGetValue(*userOptions, k_Unique_Id_Key);
+ if (!isA_CFString(uniqueID))
+ return;
+
+ /* first, get the PPP password */
+ password = copyPasswordFromKeychain(uniqueID);
+
+ /* then, if necessary, get the IPSec Shared Secret */
+ if (SCNetworkConnectionPrivateIsPPPService(session, serviceID, kSCValNetInterfaceSubTypeL2TP, 0)) {
+ CFMutableStringRef uniqueIDSS;
+
+ uniqueIDSS = CFStringCreateMutableCopy(NULL, 0, uniqueID);
+ CFStringAppend(uniqueIDSS, CFSTR(".SS"));
+ sharedsecret = copyPasswordFromKeychain(uniqueIDSS);
+ CFRelease(uniqueIDSS);
}
- uniqueID = CFDictionaryGetValue(oldDict, k_Unique_Id_Key);
- if(!isA_CFString(uniqueID)) {
- return; // if no unique ID
+ /* did we find our information in the key chain ? */
+ if ((password != NULL) || (sharedsecret != NULL)) {
+ CFMutableDictionaryRef newOptions;
+
+ newOptions = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
+
+ /* PPP password */
+ if (password != NULL) {
+ CFDictionaryRef entity;
+ CFMutableDictionaryRef newEntity;
+
+ entity = CFDictionaryGetValue(*userOptions, kSCEntNetPPP);
+ if (isA_CFDictionary(entity))
+ newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+ else
+ newEntity = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+
+ /* set the PPP password */
+ CFDictionarySetValue(newEntity, kSCPropNetPPPAuthPassword, password);
+ CFRelease(password);
+
+ /* update the PPP entity */
+ CFDictionarySetValue(newOptions, kSCEntNetPPP, newEntity);
+ CFRelease(newEntity);
+ }
+
+ /* IPSec Shared Secret */
+ if (sharedsecret != NULL) {
+ CFDictionaryRef entity;
+ CFMutableDictionaryRef newEntity;
+
+ entity = CFDictionaryGetValue(*userOptions, kSCEntNetIPSec);
+ if (isA_CFDictionary(entity))
+ newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+ else
+ newEntity = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ /* set the IPSec Shared Secret */
+ CFDictionarySetValue(newEntity, kSCPropNetIPSecSharedSecret, sharedsecret);
+ CFRelease(sharedsecret);
+
+ /* update the IPSec entity */
+ CFDictionarySetValue(newOptions, kSCEntNetIPSec, newEntity);
+ CFRelease(newEntity);
+ }
+
+ /* update the userOptions dictionary */
+ CFRelease(*userOptions);
+ *userOptions = CFDictionaryCreateCopy(NULL, newOptions);
+ CFRelease(newOptions);
}
+}
+
+//********************************************************************************
+// copyPasswordFromKeychain
+// --------------------------------------
+// Given a uniqueID, retrieve the password from the keychain
+//********************************************************************************
+static CFStringRef
+copyPasswordFromKeychain(CFStringRef uniqueID)
+{
+ CFArrayRef enumerator;
+ CFIndex n;
+ CFStringRef password = NULL;
+
enumerator = copyKeychainEnumerator(uniqueID);
- if(enumerator == NULL) {
- return; // if no keychain enumerator
+ if (enumerator == NULL) {
+ return NULL; // if no keychain enumerator
}
-
n = CFArrayGetCount(enumerator);
if (n > 0) {
void *data = NULL;
NULL, // attrList
&dataLen, // length
(void *)&data); // outData
- if(result == noErr && data != NULL && dataLen > 0) {
- CFStringRef pass;
-
- pass = CFStringCreateWithBytes(NULL, data, dataLen, kCFStringEncodingUTF8, TRUE);
- if (pass) {
- CFMutableDictionaryRef newDict;
- CFMutableDictionaryRef newPPP;
- CFDictionaryRef pppDict;
-
- newDict = CFDictionaryCreateMutableCopy(NULL, 0, oldDict);
- pppDict = CFDictionaryGetValue(newDict, kSCEntNetPPP);
- if (isA_CFDictionary(pppDict)) {
- newPPP = CFDictionaryCreateMutableCopy(NULL, 0, pppDict);
- } else {
- newPPP = CFDictionaryCreateMutable(NULL,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- }
-
- // set the PPP password
- CFDictionarySetValue(newPPP, kSCPropNetPPPAuthPassword, pass);
- CFRelease(pass);
-
- // update the PPP entity
- CFDictionarySetValue(newDict, kSCEntNetPPP, newPPP);
- CFRelease(newPPP);
-
- // update the userOptions dictionary
- CFRelease(oldDict);
- *userOptions = CFDictionaryCreateCopy(NULL, newDict);
- CFRelease(newDict);
- }
+ if ((result == noErr) && (data != NULL) && (dataLen > 0)) {
+ password = CFStringCreateWithBytes(NULL, data, dataLen, kCFStringEncodingUTF8, TRUE);
}
}
CFRelease(enumerator);
- return;
+
+ return password;
}
//********************************************************************************
static CFArrayRef
copyKeychainEnumerator(CFStringRef uniqueIdentifier)
{
- char *buf = NULL;
+ char *buf;
CFMutableArrayRef itemArray = NULL;
OSStatus result;
SecKeychainSearchRef search = NULL;
/*!
@header SCNetworkConnection
- The SCNetworkConnectionXXX() APIs allow an application to
- control connection oriented services defined in the system.
+ @discussion The SCNetworkConnection API contains functions that allow
+ an application to control connection-oriented services defined
+ in the system and get connection-status information.
- This is a set of control APIs only. Using these APIs, an
- application will be able to control existing services.
- To create, change, or remove services, SCPreferences APIs
- must be used.
+ The functions in the SCNetworkConnection API allow you to
+ control and get information about existing services only.
+ If you need to create, change, or remove services, you
+ should use the SCNetworkConfiguration API instead.
- Note: Currently only PPP services can be controlled.
+ Note: Currently, only PPP services can be controlled.
*/
/*!
@typedef SCNetworkConnectionRef
- @discussion This is the handle to manage a connection oriented service.
+ @discussion This is the handle to manage a connection-oriented service.
*/
-typedef const struct __SCNetworkConnection * SCNetworkConnectionRef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef const struct __SCNetworkConnection * SCNetworkConnectionRef;
/*!
@typedef SCNetworkConnectionContext
+ @discussion Structure containing user-specified data and callbacks
+ for a SCNetworkConnection.
+ @field version The version number of the structure type being passed
+ in as a parameter to the SCNetworkConnectionCreateWithServiceID
+ function. This structure is version 0.
+ @field info A C pointer to a user-specified block of data.
+ @field retain The callback used to add a retain for the info field.
+ If this parameter is not a pointer to a function of the correct
+ prototype, the behavior is undefined. The value may be NULL.
+ @field release The calllback used to remove a retain previously added
+ for the info field. If this parameter is not a pointer to a
+ function of the correct prototype, the behavior is undefined.
+ The value may be NULL.
+ @field copyDescription The callback used to provide a description of
+ the info field.
*/
typedef struct {
CFIndex version;
const void *(*retain)(const void *info);
void (*release)(const void *info);
CFStringRef (*copyDescription)(const void *info);
-} SCNetworkConnectionContext AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+} SCNetworkConnectionContext;
An extended status, specific to the type of network
connection is also available for applications that
need additonal information.
-
@constant kSCNetworkConnectionInvalid
The network connection refers to an invalid service.
-
@constant kSCNetworkConnectionDisconnected
The network connection is disconnected.
-
@constant kSCNetworkConnectionConnecting
The network connection is connecting.
-
@constant kSCNetworkConnectionConnected
The network connection is connected.
-
@constant kSCNetworkConnectionDisconnecting
The network connection is disconnecting.
*/
kSCNetworkConnectionConnected = 2,
kSCNetworkConnectionDisconnecting = 3
};
-typedef int32_t SCNetworkConnectionStatus AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef int32_t SCNetworkConnectionStatus;
/*!
@enum SCNetworkConnectionPPPStatus
- @discussion PPP specific status of the network connection.
- This status is PPP specific and returned as part of the extended information
+ @discussion PPP-specific status of the network connection.
+ This status is returned as part of the extended information
for a PPP service.
- Note: additional status might be returned in the future, and the application should
- be prepared to receive an unknown value.
-
+ Note: additional status might be returned in the future.
+ Your application should be prepared to receive an unknown value.
@constant kSCNetworkConnectionPPPDisconnected
PPP is disconnected.
-
@constant kSCNetworkConnectionPPPInitializing
PPP is initializing.
-
@constant kSCNetworkConnectionPPPConnectingLink
- PPP is connecting the lower connection layer (for example, the modem is dialing out).
-
+ PPP is connecting the lower connection layer (for example,
+ the modem is dialing out).
@constant kSCNetworkConnectionPPPDialOnTraffic
- PPP is waiting for networking traffic to automatically establish the connection.
-
+ PPP is waiting for networking traffic to automatically
+ establish the connection.
@constant kSCNetworkConnectionPPPNegotiatingLink
- PPP lower layer is connected and PPP is negotiating the link layer (LCP protocol).
-
+ The PPP lower layer is connected and PPP is negotiating the
+ link layer (LCP protocol).
@constant kSCNetworkConnectionPPPAuthenticating
- PPP is authenticating to the server (PAP, CHAP, MS-CHAP or EAP protocols).
-
+ PPP is authenticating to the server (PAP, CHAP, MS-CHAP or
+ EAP protocols).
@constant kSCNetworkConnectionPPPWaitingForCallBack
- PPP is waiting for server to call back.
-
+ PPP is waiting for the server to call back.
@constant kSCNetworkConnectionPPPNegotiatingNetwork
- PPP is now authenticated and negotiating the networking layer (IPCP or IPv6CP protocols)
-
+ PPP is now authenticated and negotiating the networking
+ layer (IPCP or IPv6CP protocols)
@constant kSCNetworkConnectionPPPConnected
- PPP is now fully connected for at least one of the networking layer.
+ PPP is now fully connected for at least one networking layer.
Additional networking protocol might still be negotiating.
-
@constant kSCNetworkConnectionPPPTerminating
PPP networking and link protocols are terminating.
-
@constant kSCNetworkConnectionPPPDisconnectingLink
- PPP is disconnecting the lower level (for example, the modem is hanging up).
-
+ PPP is disconnecting the lower level (for example, the modem
+ is hanging up).
@constant kSCNetworkConnectionPPPHoldingLinkOff
PPP is disconnected and maintaining the link temporarily off.
-
@constant kSCNetworkConnectionPPPSuspended
- PPP is suspended as a result of the suspend command (for example, when a V92 Modem is On Hold).
-
+ PPP is suspended as a result of the suspend command (for
+ example, when a V.92 Modem is On Hold).
@constant kSCNetworkConnectionPPPWaitingForRedial
PPP has found a busy server and is waiting for redial.
*/
kSCNetworkConnectionPPPSuspended = 12,
kSCNetworkConnectionPPPWaitingForRedial = 13
};
-typedef int32_t SCNetworkConnectionPPPStatus AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef int32_t SCNetworkConnectionPPPStatus;
/*!
status event is delivered.
@param status The connection status.
@param connection The connection reference.
- @param info ....
+ @param info Application-specific information.
*/
typedef void (*SCNetworkConnectionCallBack) (
SCNetworkConnectionRef connection,
SCNetworkConnectionStatus status,
void *info
- ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+ );
__BEGIN_DECLS
/*!
- @function SCDynamicStoreGetTypeID
- Returns the type identifier of all SCNetworkConnection instances.
+ @function SCNetworkConnectionGetTypeID
+ @discussion Returns the type identifier of all SCNetworkConnection
+ instances.
*/
CF_EXPORT
CFTypeID SCNetworkConnectionGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
/*!
- @function SCNetworkConnectionCopyUserPreferences
- @discussion Provides the default serviceID and a userOptions dictionary for the connection.
- Applications can use the serviceID and userOptions returned to open a connection on the fly.
- @param selectionOptions Currently unimplemented. Pass NULL for this version.
- @param serviceID Reference to the default serviceID for starting connections,
- this value will be returned by the function.
- @param userOptions Reference to default userOptions for starting connections,
- this will be returned by the function.
- @result TRUE if there is a valid service to dial.
- FALSE if function was unable to retrieve a service to dial.
+ @function SCNetworkConnectionCopyUserPreferences
+ @discussion Provides the default service ID and a dictionary of user
+ options for the connection. Applications can use the
+ returned serviceID and userOptions values to open a
+ connection on the fly.
+ @param selectionOptions Currently unimplemented. Pass NULL for this
+ version.
+ @param serviceID Reference to the default serviceID for starting
+ connections, this value will be returned by the function.
+ @param userOptions Reference to default userOptions for starting
+ connections, this will be returned by the function.
+ @result Returns TRUE if there is a valid service to dial;
+ FALSE if the function was unable to retrieve a service to dial.
*/
Boolean SCNetworkConnectionCopyUserPreferences (
CFDictionaryRef selectionOptions,
/*!
@function SCNetworkConnectionCreateWithServiceID
- @discussion Creates a new connection reference to use for getting the status,
- for connecting or for disconnecting the associated service.
- @param allocator The CFAllocator which should be used to allocate
- memory for the connection structure.
- This parameter may be NULL in which case the current
- default CFAllocator is used. If this reference is not
- a valid CFAllocator, the behavior is undefined.
+ @discussion Creates a new connection reference to use for getting
+ the status or for connecting or disconnecting the associated
+ service.
+ @param allocator The CFAllocator that should be used to allocate
+ memory for the connection structure. This parameter may be
+ NULL in which case the current default CFAllocator is used.
+ If this reference is not a valid CFAllocator, the behavior
+ is undefined.
@param serviceID A string that defines the service identifier
- of the connection. Service identifiers uniquely identify
+ of the connection. Service identifiers uniquely identify
services in the system configuration database.
@param callout The function to be called when the status
- of the connection changes.
- If this parameter is NULL, the application will not receive
- change of status notifications and will need to poll for updates.
- @param context The SCNetworkConnectionContext associated with the callout.
- @result A reference to the new SCNetworkConnection.
+ of the connection changes. If this parameter is NULL, the
+ application will not receive notifications of status change
+ and will need to poll for updates.
+ @param context The SCNetworkConnectionContext associated with the
+ callout.
+ @result Returns a reference to the new SCNetworkConnection.
*/
SCNetworkConnectionRef
SCNetworkConnectionCreateWithServiceID (
/*!
@function SCNetworkConnectionCopyService
@discussion Returns the service ID associated with the SCNetworkConnection.
- @param connection The SCNetworkConnection to obtained status from.
- Returns the service ID associated with the SCNetworkConnection.
+ @param connection The SCNetworkConnection to obtain status from.
+ @result Returns the service ID associated with the SCNetworkConnection.
*/
CFStringRef
SCNetworkConnectionCopyServiceID (
/*!
@function SCNetworkConnectionGetStatus
@discussion Returns the status of the SCNetworkConnection.
- A status is one of the following values :
- kSCNetworkConnectionInvalid
- kSCNetworkConnectionDisconnected
- kSCNetworkConnectionConnecting
- kSCNetworkConnectionDisconnecting
- kSCNetworkConnectionConnected
-
+ A status is one of the following values:
+<pre>
+@textblock
+ 
+ kSCNetworkConnectionInvalid
+ kSCNetworkConnectionDisconnected
+ kSCNetworkConnectionConnecting
+ kSCNetworkConnectionDisconnecting
+ kSCNetworkConnectionConnected
+@/textblock
+</pre>
@param connection The SCNetworkConnection to obtain status from.
- @result The status value.
+ @result Returns the status value.
*/
SCNetworkConnectionStatus
SCNetworkConnectionGetStatus (
An extended status dictionary contains specific dictionaries
describing the status for each subcomponent of the service.
- For example, a status dictionary will contain the following dictionaries:
-
- IPv4:
- IPaddress: IP address used.
-
- PPP:
- Status: PPP specific status of type SCNetworkConnectionPPPStatus.
- LastCause: Available when status is Disconnected.
- Contains the last error of disconnection.
- ConnectTime: time when the connection happened
- MaxTime: maximum time for this connection
-
- Modem:
- ConnectionSpeed: Speed of the modem connection in bits/s
-
- Other dictionaries could be present for PPPoE, PPTP and L2TP.
-
- The status dictionary can be extended as needed in the future
- to contain additional information.
-
+ For example, a status dictionary will contain the following
+ sub-dictionaries, keys, and values:
+<pre>
+@textblock
+ 
+ IPv4 : Addresses : the assigned IP address.
+ 
+ PPP : Status : the PPP-specific status of type
+ SCNetworkConnectionPPPStatus.
+ 
+ LastCause : Available when the status is "Disconnected"
+ and contains the last error associated with
+ connecting or disconnecting.
+ 
+ ConnectTime : the time when the connection was
+ established.
+ 
+ Modem : ConnectSpeed : the speed of the modem connection
+ in bits/second.
+@/textblock
+</pre>
+ Other dictionaries could be present for PPPoE, PPTP, and L2TP.
+
+ The status dictionary may be extended in the future to contain
+ additional information.
@param connection The SCNetworkConnection to obtain status from.
- @result The status dictionary.
- If NULL is returned, the error can be retrieved with SCError().
+ @result Returns the status dictionary.
+ If NULL is returned, the error can be retrieved using the SCError function.
*/
CFDictionaryRef
SCNetworkConnectionCopyExtendedStatus (
@function SCNetworkConnectionCopyStatistics
@discussion Returns the statistics of the SCNetworkConnection.
A statistic dictionary contains specific dictionaries
- with statistics for each subcomponents of the service.
-
- For example, a statistic dictionary will contain the following dictionaries:
-
- PPP: {Bytes,Packets,Errors}{In,Out}:
- Statistics at the Network level.
- Contains the number of bytes, packets, and errors on the PPP interface.
- For example, BytesIn contains the number of bytes going up
- into the network stack, for any networking protocol,
- without the PPP headers and trailers.
-
- The statistic dictionary can be extended as needed in the future
- to contain additional information.
-
+ with statistics for each subcomponent of the service.
+
+ For example, a statistics dictionary will contain the following
+ sub-dictionaries, keys, and values:
+<pre>
+@textblock
+ 
+ PPP : BytesIn :
+ PPP : BytesOut : Contains the number of bytes going up into
+ (or coming out of) the network stack for
+ any networking protocol without the PPP
+ headers and trailers.
+ 
+ PPP : PacketsIn :
+ PPP : PacketsOut : Contains the number of packets going up into
+ (or coming out of) the network stack for
+ any networking protocol without the PPP
+ headers and trailers.
+ 
+ PPP : ErrorsIn :
+ PPP : ErrorsOut : Contains the number of errors going up into
+ (or coming out of) the network stack for
+ any networking protocol without the PPP
+ headers and trailers.
+@/textblock
+</pre>
+ The statistics dictionary may be extended in the future to
+ contain additional information.
@param connection The SCNetworkConnection to obtained statistics from.
- @result The statistics dictionary.
- If NULL is returned, the error can be retrieved with SCError().
+ @result Returns the statistics dictionary.
+ If NULL is returned, the error can be retrieved using the SCError function.
*/
CFDictionaryRef
SCNetworkConnectionCopyStatistics (
/*!
@function SCNetworkConnectionStart
- @discussion Start the connection for the SCNetworkConnection.
+ @discussion Starts the connection for the SCNetworkConnection.
The connection process is asynchronous and the function will
- return immediately. The connection status can be obtain by polling or
- by callback.
- The connection is done with the default settings from the administrator.
- Some of the settings can be overridden for the duration of
- the connection. They are given in an option dictionary.
- The options dictionary is in the format of a Network Service
- as described in SystemConfiguration.
-
- Note: Starting and stopping of connections is implicitely arbitrated.
- Calling Start on a connection already started will indicate
- that the application has interest in the connection and it shouldn't
- be stopped by anyone else.
-
+ return immediately. The connection status can be obtained
+ by polling or by callback. The connection is made with the
+ default settings from the administrator. Some of the settings
+ can be overridden for the duration of the connection. These
+ are specified in an options dictionary. The options dictionary
+ uses the same format as a network service defined in the system
+ configuration preferences schema.
+
+ Note: Starting and stopping of connections is implicitly
+ arbitrated. Calling SCNetworkConnectionStart on a connection
+ already started will indicate that the application has
+ interest in the connection and it shouldn't be stopped by
+ anyone else.
@param connection The SCNetworkConnection to start.
@param userOptions The options dictionary to start the connection with.
If userOptions is NULL, the default settings will be used.
- If userOptions are specified, they must be in the SystemConfiguration format.
- The options will override the default settings defined for the service.
-
- For security reasons, not all the options can be overridden, the appropriate merging
- of all the settings will be done before the connection is established,
- and inappropriate options will be ignored.
-
- @param linger This parameter indicates whether or not the connection can stay around
- when the application no longer has interest in it.
- Typical application should pass FALSE, and the Stop function will
- automatically be called when the reference is released or if the application quits.
- If the application passes TRUE, the application can release the reference
- or exit and the Stop function will not be called.
-
- @result TRUE if the connection was correctly started. The actual connection is not established yet,
- and the connection status needs to be periodically checked.
- FALSE if the connection request didn't start. Error must be taken
- from SCError().
+ If userOptions are specified, they must be in the same format
+ as network services stored in the system configuration
+ preferences schema. The options will override the default
+ settings defined for the service.
+
+ For security reasons, not all options can be overridden; the
+ appropriate merging of all settings will be done before the
+ connection is established, and inappropriate options will be
+ ignored.
+ @param linger This parameter indicates whether or not the connection
+ can stay around when the application no longer has interest
+ in it. A typical application should pass FALSE, and the
+ connection will be automatically stopped when the reference
+ is released or if the application quits. If the application
+ passes TRUE, the application can release the reference or
+ exit and the connection will be maintained until a timeout
+ event, until a specific stop request occurs, or until an
+ error is encountered.
+ @result Returns TRUE if the connection was correctly started (the
+ actual connection is not established yet, and the connection
+ status needs to be periodically checked); FALSE if the
+ connection request was not started. The error must be
+ retrieved from the SCError function.
*/
Boolean
SCNetworkConnectionStart (
/*!
@function SCNetworkConnectionStop
- @discussion Stop the connection for the SCNetworkConnection.
- The disconnection process is asynchronous and the function will
- return immediately. The connection status can be obtain by polling or
- by callback.
- This function performs an arbitrated stop of the connection.
- If several applications have marked their interest in the connection,
- by calling SCNetworkConnectionStart, the call will succeed but the the actual
- connection will be maintained until the last interested application calls stop.
-
- In certain cases, you might want to stop the connection anyway, and
- SCNetworkConnectionStop with forceDisconnect argument can be used.
-
+ @discussion Stops the connection for the SCNetworkConnection.
+ The disconnection process is asynchronous and the function
+ will return immediately. The connection status can be
+ obtained by polling or by callback. This function performs
+ an arbitrated stop of the connection. If several applications
+ have marked their interest in the connection, by calling
+ SCNetworkConnectionStart, the call will succeed but the
+ actual connection will be maintained until the last interested
+ application calls SCNetworkConnectionStop.
+
+ In certain cases, you might want to stop the connection anyway.
+ In these cases, you set the forceDisconnect argument to TRUE.
@param connection The SCNetworkConnection to stop.
- @result TRUE if the disconnection request succeeded.
- FALSE if the disconnection request failed. Error must be taken from SCError().
+ @result Returns TRUE if the disconnection request succeeded;
+ FALSE if the disconnection request failed.
+ The error must be retrieved from the SCError function.
*/
Boolean
SCNetworkConnectionStop (
/*!
@function SCNetworkConnectionCopyCurrentOptions
- @discussion Copy the user options used to start the connection.
- This is a mechanism for a client to retrieve the user options
+ @discussion Copies the user options used to start the connection.
+ This is a mechanism a client can use to retrieve the user options
previously passed to the SCNetworkConnectionStart function.
@param connection The SCNetworkConnection to obtain options from.
- @result The service dictionary containing the connection options.
+ @result Returns the service dictionary containing the connection options.
The dictionary can be empty if no user options were used.
- If NULL is returned, the error can be retrieved with SCError().
+ If NULL is returned, the error can be retrieved using the SCError function.
*/
CFDictionaryRef
SCNetworkConnectionCopyUserOptions (
/*!
@function SCNetworkConnectionScheduleWithRunLoop
- @discussion Schedule a connection with the Run Loop.
+ @discussion Schedules a connection with the run loop.
@param connection The SCNetworkConnection to schedule.
- @param runLoop The runloop to schedule with.
- @param runLoopMode The runloop mode.
- @result TRUE if success.
- FALSE if failed. The error can be retrieved with SCError().
+ @param runLoop The run loop to schedule with.
+ @param runLoopMode The run loop mode.
+ @result Returns TRUE if the connection is scheduled successfully;
+ FALSE if the scheduling failed.
+ The error can be retrieved using the SCError function.
*/
Boolean
SCNetworkConnectionScheduleWithRunLoop (
/*!
@function SCNetworkConnectionUnscheduleFromRunLoop
- @discussion Unschedule a connection from the Run Loop.
+ @discussion Unschedules a connection from the run loop.
@param connection The SCNetworkConnection to unschedule.
- @param runLoop The runloop to unschedule from.
- @param runLoopMode The runloop mode.
- @result TRUE if success.
- FALSE if failed. The error can be retrieved with SCError().
+ @param runLoop The run loop to unschedule from.
+ @param runLoopMode The run loop mode.
+ @result Returns TRUE if the connection is unscheduled successfully;
+ FALSE if the unscheduling failed.
+ The error can be retrieved using the SCError function.
*/
Boolean
SCNetworkConnectionUnscheduleFromRunLoop (
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 13, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ * which includes code originally authored by
+ * Robert Ulrich <rulrich@apple.com>
+ * Elizaabeth Douglas <elizabeth@apple.com>
+ * Quinn <eskimo1@apple.com>
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/BondConfiguration.h>
+#include <SystemConfiguration/VLANConfiguration.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFBundle.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/network/IONetworkController.h>
+#include <IOKit/network/IONetworkInterface.h>
+#include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
+#include <IOKit/serial/IOSerialKeys.h>
+#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
+#include "dy_framework.h"
+
+#ifndef kIODeviceSupportsHoldKey
+#define kIODeviceSupportsHoldKey "V92Modem"
+#endif
+
+#include "SCNetworkConfiguration.h"
+#include "SCNetworkConfigurationInternal.h"
+
+#include <mach/mach.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <pthread.h>
+
+
+static CFStringRef __SCNetworkInterfaceCopyDescription (CFTypeRef cf);
+static void __SCNetworkInterfaceDeallocate (CFTypeRef cf);
+static Boolean __SCNetworkInterfaceEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+
+enum {
+ kSortInternalModem,
+ kSortUSBModem,
+ kSortModem,
+ kSortBluetooth,
+ kSortIrDA,
+ kSortSerialPort,
+ kSortEthernet,
+ kSortFireWire,
+ kSortAirPort,
+ kSortOtherWireless,
+ kSortBond,
+ kSortVLAN,
+ kSortUnknown
+};
+
+
+const CFStringRef kSCNetworkInterfaceType6to4 = CFSTR("6to4");
+const CFStringRef kSCNetworkInterfaceTypeBluetooth = CFSTR("Bluetooth");
+const CFStringRef kSCNetworkInterfaceTypeBond = CFSTR("Bond");
+const CFStringRef kSCNetworkInterfaceTypeEthernet = CFSTR("Ethernet");
+const CFStringRef kSCNetworkInterfaceTypeFireWire = CFSTR("FireWire");
+const CFStringRef kSCNetworkInterfaceTypeIEEE80211 = CFSTR("IEEE80211"); // IEEE 802.11, AirPort
+const CFStringRef kSCNetworkInterfaceTypeIrDA = CFSTR("IrDA");
+const CFStringRef kSCNetworkInterfaceTypeL2TP = CFSTR("L2TP");
+const CFStringRef kSCNetworkInterfaceTypeModem = CFSTR("Modem");
+const CFStringRef kSCNetworkInterfaceTypePPP = CFSTR("PPP");
+const CFStringRef kSCNetworkInterfaceTypePPTP = CFSTR("PPTP");
+const CFStringRef kSCNetworkInterfaceTypeSerial = CFSTR("Serial");
+const CFStringRef kSCNetworkInterfaceTypeVLAN = CFSTR("VLAN");
+
+const CFStringRef kSCNetworkInterfaceTypeIPv4 = CFSTR("IPv4");
+
+static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4 = {
+ INIT_CFRUNTIME_BASE(NULL, 0, 0x0080), // cfBase
+ NULL, // interface type
+ NULL, // localized name
+ NULL, // localization key
+ NULL, // localization arg1
+ NULL, // localization arg2
+ NULL, // [layered] interface
+ NULL, // service
+ NULL, // unsaved
+ NULL, // entity_device
+ NULL, // entity_hardware
+ NULL, // entity_type
+ NULL, // entity_subtype
+ NULL, // supported_interface_types
+ NULL, // supported_protocol_types
+ NULL, // address
+ FALSE, // builtin
+ NULL, // location
+ NULL, // path
+ FALSE, // supportsDeviceOnHold
+ FALSE, // supportsBond
+ FALSE, // supportsVLAN
+ kSortUnknown // sort_order
+};
+
+const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4 = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceIPv4;
+
+#define doNone 0
+
+#define do6to4 1<<0
+#define doL2TP 1<<1
+#define doPPP 1<<2
+#define doPPTP 1<<3
+
+#define doAppleTalk 1<<0
+#define doDNS 1<<1
+#define doIPv4 1<<2
+#define doIPv6 1<<3
+#define doProxies 1<<4
+
+static const struct {
+ const CFStringRef *interface_type;
+ Boolean per_interface_config;
+ uint32_t supported_interfaces;
+ const CFStringRef *ppp_subtype;
+ uint32_t supported_protocols;
+} configurations[] = {
+ // interface type if config? interface types PPP sub-type interface protocols
+ // ===================================== ========== ======================= ======================================= =========================================
+ { &kSCNetworkInterfaceType6to4 , FALSE, doNone, NULL, doIPv6 },
+ { &kSCNetworkInterfaceTypeBluetooth , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
+ { &kSCNetworkInterfaceTypeBond , TRUE, doNone, NULL, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies },
+ { &kSCNetworkInterfaceTypeEthernet , TRUE, doPPP, &kSCValNetInterfaceSubTypePPPoE, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies },
+ { &kSCNetworkInterfaceTypeFireWire , TRUE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies },
+ { &kSCNetworkInterfaceTypeIEEE80211 , TRUE, doPPP, &kSCValNetInterfaceSubTypePPPoE, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies },
+ { &kSCNetworkInterfaceTypeIrDA , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
+ { &kSCNetworkInterfaceTypeL2TP , FALSE, doPPP, &kSCValNetInterfaceSubTypeL2TP, doNone },
+ { &kSCNetworkInterfaceTypeModem , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
+ { &kSCNetworkInterfaceTypePPP , FALSE, doNone, NULL, doDNS|doIPv4|doIPv6|doProxies },
+ { &kSCNetworkInterfaceTypePPTP , FALSE, doPPP, &kSCValNetInterfaceSubTypePPTP, doNone },
+ { &kSCNetworkInterfaceTypeSerial , FALSE, doPPP, &kSCValNetInterfaceSubTypePPPSerial, doNone },
+ { &kSCNetworkInterfaceTypeVLAN , TRUE, doNone, NULL, doAppleTalk|doDNS|doIPv4|doIPv6|doProxies },
+ // ===================================== ========== ======================= ======================================= =========================================
+ { &kSCNetworkInterfaceTypeIPv4 , FALSE, do6to4|doPPTP|doL2TP, NULL, doNone }
+};
+
+
+#define SYSTEMCONFIGURATION_BUNDLE_ID CFSTR("com.apple.SystemConfiguration")
+#define NETWORKINTERFACE_LOCALIZATIONS CFSTR("NetworkInterface")
+static CFBundleRef bundle = NULL;
+
+
+static CFTypeID __kSCNetworkInterfaceTypeID = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkInterfaceClass = {
+ 0, // version
+ "SCNetworkInterface", // className
+ NULL, // init
+ NULL, // copy
+ __SCNetworkInterfaceDeallocate, // dealloc
+ __SCNetworkInterfaceEqual, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __SCNetworkInterfaceCopyDescription // copyDebugDesc
+};
+
+
+static pthread_once_t initialized = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkInterface(CFTypeRef obj)
+{
+ return (isA_CFType(obj, SCNetworkInterfaceGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkInterfaceCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkInterface %p [%p]> { "), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR("type = %@"), interfacePrivate->interface_type);
+ CFStringAppendFormat(result, NULL, CFSTR(", entity = %@ / %@ / %@"),
+ interfacePrivate->entity_device,
+ interfacePrivate->entity_hardware,
+ interfacePrivate->entity_type);
+ if (interfacePrivate->entity_subtype != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(" / %@"), interfacePrivate->entity_subtype);
+ }
+ if (interfacePrivate->localized_name != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), interfacePrivate->localized_name);
+ } else {
+ if (interfacePrivate->localized_key != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", name = \"%@\""), interfacePrivate->localized_key);
+ if (interfacePrivate->localized_arg1 != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg1);
+ }
+ if (interfacePrivate->localized_arg2 != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg2);
+ }
+ }
+ }
+ if (interfacePrivate->address != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", address = %@"), interfacePrivate->address);
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(", builtin = %s"), interfacePrivate->builtin ? "TRUE" : "FALSE");
+ if (interfacePrivate->location != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location);
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path);
+ CFStringAppendFormat(result, NULL, CFSTR(", order = %d"), interfacePrivate->sort_order);
+
+ if (interfacePrivate->service != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", service=%@"), interfacePrivate->service);
+ }
+
+ if (interfacePrivate->interface != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", interface=%@"), interfacePrivate->interface);
+ }
+
+ if (interfacePrivate->unsaved != NULL) {
+ CFStringAppendFormat(result, NULL, CFSTR(", unsaved=%@"), interfacePrivate->unsaved);
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__SCNetworkInterfaceDeallocate(CFTypeRef cf)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)cf;
+
+ /* release resources */
+
+ if (interfacePrivate->interface != NULL)
+ CFRelease(interfacePrivate->interface);
+
+ if (interfacePrivate->localized_name != NULL)
+ CFRelease(interfacePrivate->localized_name);
+
+ if (interfacePrivate->localized_arg1 != NULL)
+ CFRelease(interfacePrivate->localized_arg1);
+
+ if (interfacePrivate->localized_arg2 != NULL)
+ CFRelease(interfacePrivate->localized_arg2);
+
+ if (interfacePrivate->unsaved != NULL)
+ CFRelease(interfacePrivate->unsaved);
+
+ if (interfacePrivate->entity_device != NULL)
+ CFRelease(interfacePrivate->entity_device);
+
+ if (interfacePrivate->supported_interface_types != NULL)
+ CFRelease(interfacePrivate->supported_interface_types);
+
+ if (interfacePrivate->supported_protocol_types != NULL)
+ CFRelease(interfacePrivate->supported_protocol_types);
+
+ if (interfacePrivate->address != NULL)
+ CFRelease(interfacePrivate->address);
+
+ if (interfacePrivate->location != NULL)
+ CFRelease(interfacePrivate->location);
+
+ if (interfacePrivate->path != NULL)
+ CFRelease(interfacePrivate->path);
+
+ return;
+}
+
+
+static Boolean
+__SCNetworkInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+ SCNetworkInterfacePrivateRef if1 = (SCNetworkInterfacePrivateRef)cf1;
+ SCNetworkInterfacePrivateRef if2 = (SCNetworkInterfacePrivateRef)cf2;
+
+ if (if1 == if2)
+ return TRUE;
+
+ if (!CFEqual(if1->interface_type, if2->interface_type)) {
+ return FALSE; // if not the same interface type
+ }
+
+ if (if1->entity_device != if2->entity_device) {
+ if ((if1->entity_device != NULL) && (if2->entity_device != NULL)) {
+ if (!CFEqual(if1->entity_device, if2->entity_device)) {
+ return FALSE; // if not the same device
+ }
+ } else {
+ return FALSE; // if only one interface has a device
+ }
+ }
+
+ return TRUE;
+}
+
+
+static void
+__SCNetworkInterfaceInitialize(void)
+{
+ // register w/CF
+ __kSCNetworkInterfaceTypeID = _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass);
+
+ // initialize __kSCNetworkInterfaceIPv4
+ _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4, __kSCNetworkInterfaceTypeID);
+ __kSCNetworkInterfaceIPv4.interface_type = kSCNetworkInterfaceTypeIPv4;
+ __kSCNetworkInterfaceIPv4.localized_key = CFSTR("ipv4");
+
+ // get CFBundleRef for SystemConfiguration.framework
+ bundle = CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID);
+ if (bundle == NULL) {
+ // try a bit harder
+ CFURLRef url;
+
+ url = CFURLCreateWithFileSystemPath(NULL,
+ CFSTR("/System/Library/Frameworks/SystemConfiguration.framework"),
+ kCFURLPOSIXPathStyle,
+ TRUE);
+ bundle = CFBundleCreate(NULL, url);
+ CFRelease(url);
+ }
+
+ return;
+}
+
+
+__private_extern__ SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreatePrivate(CFAllocatorRef allocator,
+ SCNetworkInterfaceRef interface,
+ SCNetworkServiceRef service,
+ io_string_t path)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ /* allocate target */
+ size = sizeof(SCNetworkInterfacePrivate) - sizeof(CFRuntimeBase);
+ interfacePrivate = (SCNetworkInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kSCNetworkInterfaceTypeID,
+ size,
+ NULL);
+ if (interfacePrivate == NULL) {
+ return NULL;
+ }
+
+ interfacePrivate->interface_type = NULL;
+ interfacePrivate->localized_name = NULL;
+ interfacePrivate->localized_key = NULL;
+ interfacePrivate->localized_arg1 = NULL;
+ interfacePrivate->localized_arg2 = NULL;
+ interfacePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
+ interfacePrivate->service = service;
+ interfacePrivate->unsaved = NULL;
+ interfacePrivate->entity_device = NULL;
+ interfacePrivate->entity_hardware = NULL;
+ interfacePrivate->entity_type = NULL;
+ interfacePrivate->entity_subtype = NULL;
+ interfacePrivate->supported_interface_types = NULL;
+ interfacePrivate->supported_protocol_types = NULL;
+ interfacePrivate->address = NULL;
+ interfacePrivate->builtin = FALSE;
+ interfacePrivate->path = (path != NULL) ? CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8)
+ : NULL;
+ interfacePrivate->location = NULL;
+ interfacePrivate->supportsDeviceOnHold = FALSE;
+ interfacePrivate->supportsBond = FALSE;
+ interfacePrivate->supportsVLAN = FALSE;
+ interfacePrivate->sort_order = kSortUnknown;
+
+ return interfacePrivate;
+}
+
+
+/* ---------- ordering ---------- */
+
+
+static CFArrayRef
+split_path(CFStringRef path)
+{
+ CFArrayRef components;
+ CFMutableStringRef nPath;
+
+ // turn '@'s into '/'s
+ nPath = CFStringCreateMutableCopy(NULL, 0, path);
+ (void) CFStringFindAndReplace(nPath,
+ CFSTR("@"),
+ CFSTR("/"),
+ CFRangeMake(0, CFStringGetLength(nPath)),
+ 0);
+
+ // split path into components to be compared
+ components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
+ CFRelease(nPath);
+
+ return components;
+}
+
+
+static CFComparisonResult
+compare_interfaces(const void *val1, const void *val2, void *context)
+{
+ SCNetworkInterfacePrivateRef dev1 = (SCNetworkInterfacePrivateRef)val1;
+ SCNetworkInterfacePrivateRef dev2 = (SCNetworkInterfacePrivateRef)val2;
+ CFComparisonResult res = kCFCompareEqualTo;
+
+ /* sort by interface type */
+ if (dev1->sort_order != dev2->sort_order) {
+ if (dev1->sort_order < dev2->sort_order) {
+ res = kCFCompareLessThan;
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+ return (res);
+ }
+
+ /* built-in interfaces sort first */
+ if (dev1->builtin != dev2->builtin) {
+ if (dev1->builtin) {
+ res = kCFCompareLessThan;
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+ return (res);
+ }
+
+ /* ... and then, sort built-in interfaces by "location" */
+ if (dev1->builtin) {
+ if (dev1->location != dev2->location) {
+ if (isA_CFString(dev1->location)) {
+ if (isA_CFString(dev2->location)) {
+ res = CFStringCompare(dev1->location, dev2->location, 0);
+ } else {
+ res = kCFCompareLessThan;
+ }
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+
+ if (res != kCFCompareEqualTo) {
+ return (res);
+ }
+ }
+ }
+
+ /* ... and, then sort by IOPathMatch */
+ if ((dev1->path != NULL) && (dev2->path != NULL)) {
+ CFArrayRef elements1;
+ CFArrayRef elements2;
+ CFIndex i;
+ CFIndex n;
+ CFIndex n1;
+ CFIndex n2;
+
+ elements1 = split_path(dev1->path);
+ n1 = CFArrayGetCount(elements1);
+
+ elements2 = split_path(dev2->path);
+ n2 = CFArrayGetCount(elements2);
+
+ n = (n1 <= n2) ? n1 : n2;
+ for (i = 0; i < n; i++) {
+ CFStringRef e1;
+ CFStringRef e2;
+ char *end;
+ quad_t q1;
+ quad_t q2;
+ char *str;
+ Boolean isNum;
+
+ e1 = CFArrayGetValueAtIndex(elements1, i);
+ e2 = CFArrayGetValueAtIndex(elements2, i);
+
+ str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingUTF8);
+ errno = 0;
+ q1 = strtoq(str, &end, 16);
+ isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+ CFAllocatorDeallocate(NULL, str);
+
+ if (isNum) {
+ // if e1 is a valid numeric string
+ str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingUTF8);
+ errno = 0;
+ q2 = strtoq(str, &end, 16);
+ isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+ CFAllocatorDeallocate(NULL, str);
+
+ if (isNum) {
+ // if e2 is also a valid numeric string
+
+ if (q1 == q2) {
+ res = kCFCompareEqualTo;
+ continue;
+ } else if (q1 < q2) {
+ res = kCFCompareLessThan;
+ } else {
+ res = kCFCompareGreaterThan;
+ }
+ break;
+ }
+ }
+
+ res = CFStringCompare(e1, e2, 0);
+ if (res != kCFCompareEqualTo) {
+ break;
+ }
+ }
+
+ if (res == kCFCompareEqualTo) {
+ if (n1 < n2) {
+ res = kCFCompareLessThan;
+ } else if (n1 < n2) {
+ res = kCFCompareGreaterThan;
+ }
+ }
+
+ CFRelease(elements1);
+ CFRelease(elements2);
+
+ if (res != kCFCompareEqualTo) {
+ return (res);
+ }
+ }
+
+ /* ... and lastly, sort by BSD interface name */
+ if ((dev1->entity_device != NULL) && (dev2->entity_device != NULL)) {
+ res = CFStringCompare(dev1->entity_device, dev2->entity_device, 0);
+ }
+
+ return res;
+}
+
+
+static void
+sort_interfaces(CFMutableArrayRef all_interfaces)
+{
+ int n = CFArrayGetCount(all_interfaces);
+
+ if (n < 2) {
+ return;
+ }
+
+ CFArraySortValues(all_interfaces, CFRangeMake(0, n), compare_interfaces, NULL);
+ return;
+}
+
+
+/* ---------- interface details ---------- */
+
+
+static CFStringRef
+IOCopyCFStringValue(CFTypeRef ioVal)
+{
+ if (isA_CFString(ioVal)) {
+ return CFStringCreateCopy(NULL, ioVal);
+ }
+
+ if (isA_CFData(ioVal)) {
+ return CFStringCreateWithCString(NULL, CFDataGetBytePtr(ioVal), kCFStringEncodingUTF8);
+ }
+
+ return NULL;
+}
+
+
+static CFStringRef
+IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key)
+{
+ CFTypeRef ioVal;
+
+ ioVal = CFDictionaryGetValue(io_dict, io_key);
+ return IOCopyCFStringValue(ioVal);
+}
+
+
+static Boolean
+IOStringValueHasPrefix(CFTypeRef ioVal, CFStringRef prefix)
+{
+ Boolean match = FALSE;
+ CFIndex prefixLen = CFStringGetLength(prefix);
+ CFStringRef str = ioVal;
+
+ if (!isA_CFString(ioVal)) {
+ if (isA_CFData(ioVal)) {
+ str = CFStringCreateWithCStringNoCopy(NULL,
+ (const char *)CFDataGetBytePtr(ioVal),
+ kCFStringEncodingUTF8,
+ kCFAllocatorNull);
+ } else {
+ return FALSE;
+ }
+ }
+
+ if ((str != NULL) &&
+ (CFStringGetLength(str) >= prefixLen) &&
+ (CFStringCompareWithOptions(str,
+ prefix,
+ CFRangeMake(0, prefixLen),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
+ match = TRUE;
+ }
+
+ if (str != ioVal) CFRelease(str);
+ return match;
+}
+
+
+static CFStringRef
+copyMACAddress(CFDictionaryRef controller_dict)
+{
+ CFStringRef address = NULL;
+ uint8_t *bp;
+ char *cp;
+ CFDataRef data;
+ CFIndex n;
+ char mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+ char *mac_p = mac;
+
+ data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
+ if (data == NULL) {
+ return NULL;
+ }
+
+ bp = (uint8_t *)CFDataGetBytePtr(data);
+ n = CFDataGetLength(data) * 3;
+
+ if (n > sizeof(mac)) {
+ mac_p = CFAllocatorAllocate(NULL, 0, n);
+ }
+
+ for (cp = mac_p; n > 0; n -= 3) {
+ cp += snprintf(cp, n, "%2.2x:", *bp++);
+ }
+
+ address = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8);
+ if (mac_p != mac) CFAllocatorDeallocate(NULL, mac_p);
+ return address;
+}
+
+
+static const struct {
+ const CFStringRef name;
+ const CFStringRef slot;
+} slot_mappings[] = {
+ // Beige G3
+ { CFSTR("A1") , CFSTR("1") },
+ { CFSTR("B1") , CFSTR("2") },
+ { CFSTR("C1") , CFSTR("3") },
+
+ // Blue&White G3, Yikes G4
+ { CFSTR("J12"), CFSTR("1") },
+ { CFSTR("J11"), CFSTR("2") },
+ { CFSTR("J10"), CFSTR("3") },
+ { CFSTR("J9"), CFSTR("4") },
+
+ // AGP G4
+ { CFSTR("A") , CFSTR("1") },
+ { CFSTR("B") , CFSTR("2") },
+ { CFSTR("C") , CFSTR("3") },
+ { CFSTR("D") , CFSTR("4") },
+
+ // Digital Audio G4 (and later models)
+ { CFSTR("1") , CFSTR("1") },
+ { CFSTR("2") , CFSTR("2") },
+ { CFSTR("3") , CFSTR("3") },
+ { CFSTR("4") , CFSTR("4") },
+ { CFSTR("5") , CFSTR("5") }
+};
+
+
+static CFStringRef
+pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name)
+{
+ kern_return_t kr;
+ io_registry_entry_t slot = interface;
+
+ if (pci_slot_name != NULL) *pci_slot_name = NULL;
+
+ while (slot != MACH_PORT_NULL) {
+ io_registry_entry_t parent;
+ CFTypeRef slot_name;
+
+ slot_name = IORegistryEntryCreateCFProperty(slot, CFSTR("AAPL,slot-name"), NULL, 0);
+ if (slot_name != NULL) {
+ Boolean found;
+
+ found = IOStringValueHasPrefix(slot_name, CFSTR("slot"));
+ if (found) {
+ CFIndex i;
+ CFMutableStringRef name;
+
+ // if we found a slot #
+ name = CFStringCreateMutable(NULL, 0);
+ if (isA_CFString(slot_name)) {
+ if (pci_slot_name != NULL) *pci_slot_name = CFStringCreateCopy(NULL, slot_name);
+ CFStringAppend(name, slot_name);
+ } else if (isA_CFData(slot_name)) {
+ if (pci_slot_name != NULL) *pci_slot_name = CFDataCreateCopy(NULL, slot_name);
+ CFStringAppendCString(name, CFDataGetBytePtr(slot_name), kCFStringEncodingUTF8);
+ }
+
+ (void) CFStringFindAndReplace(name,
+ CFSTR("slot-"),
+ CFSTR(""),
+ CFRangeMake(0, 5),
+ kCFCompareCaseInsensitive|kCFCompareAnchored);
+ for (i = 0; i < sizeof(slot_mappings)/sizeof(slot_mappings[0]); i++) {
+ if (CFStringCompareWithOptions(name,
+ slot_mappings[i].name,
+ CFRangeMake(0, CFStringGetLength(slot_mappings[i].name)),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ CFRelease(name);
+ name = (CFMutableStringRef)CFRetain(slot_mappings[i].slot);
+ break;
+ }
+ }
+
+ CFRelease(slot_name);
+ if (slot != interface) IOObjectRelease(slot);
+ return name;
+ }
+
+ CFRelease(slot_name);
+ }
+
+ kr = IORegistryEntryGetParentEntry(slot, kIOServicePlane, &parent);
+ if (slot != interface) IOObjectRelease(slot);
+ switch (kr) {
+ case kIOReturnSuccess :
+ slot = parent;
+ break;
+ case kIOReturnNoDevice :
+ // if we have hit the root node without finding a slot #
+ goto done;
+ default :
+ SCLog(TRUE, LOG_INFO, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+ goto done;
+ }
+ }
+
+ done :
+
+ return NULL;
+}
+
+
+static CFComparisonResult
+compare_bsdNames(const void *val1, const void *val2, void *context)
+{
+ CFStringRef bsd1 = (CFStringRef)val1;
+ CFStringRef bsd2 = (CFStringRef)val2;
+
+ return CFStringCompare(bsd1, bsd2, 0);
+}
+
+
+static CFStringRef
+pci_port(mach_port_t masterPort, CFTypeRef slot_name, CFStringRef bsdName)
+{
+ CFIndex n;
+ CFStringRef port_name = NULL;
+ CFMutableArrayRef port_names;
+
+ kern_return_t kr;
+ CFStringRef match_keys[2];
+ CFTypeRef match_vals[2];
+ CFDictionaryRef match_dict;
+ CFDictionaryRef matching;
+ io_registry_entry_t slot;
+ io_iterator_t slot_iterator = MACH_PORT_NULL;
+
+ match_keys[0] = CFSTR("AAPL,slot-name");
+ match_vals[0] = slot_name;
+
+ match_dict = CFDictionaryCreate(NULL,
+ (const void **)match_keys,
+ (const void **)match_vals,
+ 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ match_keys[0] = CFSTR(kIOProviderClassKey);
+ match_vals[0] = CFSTR("IOPCIDevice");
+
+ match_keys[1] = CFSTR(kIOPropertyMatchKey);
+ match_vals[1] = match_dict;
+
+ // note: the "matching" dictionary will be consumed by the following
+ matching = CFDictionaryCreate(NULL,
+ (const void **)match_keys,
+ (const void **)match_vals,
+ sizeof(match_keys)/sizeof(match_keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFRelease(match_dict);
+
+ kr = IOServiceGetMatchingServices(masterPort, matching, &slot_iterator);
+ if (kr != kIOReturnSuccess) {
+ SCPrint(TRUE, stderr, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr);
+ return MACH_PORT_NULL;
+ }
+
+ port_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ while ((slot = IOIteratorNext(slot_iterator)) != MACH_PORT_NULL) {
+ io_registry_entry_t child;
+ io_iterator_t child_iterator = MACH_PORT_NULL;
+
+ kr = IORegistryEntryCreateIterator(slot,
+ kIOServicePlane,
+ kIORegistryIterateRecursively,
+ &child_iterator);
+ if (kr != kIOReturnSuccess) {
+ SCPrint(TRUE, stderr, CFSTR("IORegistryEntryCreateIterator() failed, kr = 0x%x\n"), kr);
+ return MACH_PORT_NULL;
+ }
+
+ while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) {
+ if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) {
+ CFStringRef if_bsdName;
+
+ if_bsdName = IORegistryEntryCreateCFProperty(child,
+ CFSTR(kIOBSDNameKey),
+ NULL,
+ 0);
+ if (if_bsdName != NULL) {
+ CFArrayAppendValue(port_names, if_bsdName);
+ CFRelease(if_bsdName);
+ }
+ }
+ IOObjectRelease(child);
+ }
+ IOObjectRelease(child_iterator);
+ IOObjectRelease(slot);
+ }
+ IOObjectRelease(slot_iterator);
+
+ n = CFArrayGetCount(port_names);
+ if (n > 1) {
+ CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL);
+ n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName);
+ if (n != kCFNotFound) {
+ port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), n + 1);
+ }
+ }
+
+ CFRelease(port_names);
+ return port_name;
+}
+
+
+static Boolean
+pci_slot_info(mach_port_t masterPort, io_registry_entry_t interface, CFStringRef *slot_name, CFStringRef *port_name)
+{
+ CFStringRef bsd_name;
+ Boolean ok = FALSE;
+ CFTypeRef pci_slot_name;
+
+ *slot_name = NULL;
+ *port_name = NULL;
+
+ bsd_name = IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, 0);
+ if (bsd_name == NULL) {
+ return FALSE;
+ }
+
+ *slot_name = pci_slot(interface, &pci_slot_name);
+ if (*slot_name != NULL) {
+ if (pci_slot_name != NULL) {
+ *port_name = pci_port(masterPort, pci_slot_name, bsd_name);
+ CFRelease(pci_slot_name);
+ }
+ ok = TRUE;
+ }
+
+ CFRelease(bsd_name);
+ return ok;
+}
+
+
+static Boolean
+isBuiltIn(io_registry_entry_t interface)
+{
+ kern_return_t kr;
+ io_registry_entry_t slot = interface;
+
+ while (slot != MACH_PORT_NULL) {
+ io_registry_entry_t parent;
+ CFTypeRef slot_name;
+
+ slot_name = IORegistryEntryCreateCFProperty(slot, CFSTR("AAPL,slot-name"), NULL, 0);
+ if (slot_name != NULL) {
+ Boolean found;
+
+ found = IOStringValueHasPrefix(slot_name, CFSTR("slot"));
+ CFRelease(slot_name);
+
+ if (found) {
+ // if we found a slot # then this is not a built-in interface
+ if (slot != interface) IOObjectRelease(slot);
+ return FALSE;
+ }
+ }
+
+ kr = IORegistryEntryGetParentEntry(slot, kIOServicePlane, &parent);
+ if (slot != interface) IOObjectRelease(slot);
+ switch (kr) {
+ case kIOReturnSuccess :
+ slot = parent;
+ break;
+ case kIOReturnNoDevice :
+ // if we have hit the root node without finding a slot #
+ return TRUE;
+ default :
+ SCLog(TRUE, LOG_INFO, CFSTR("isBuiltIn IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/* ---------- interface enumeration ---------- */
+
+
+typedef Boolean (*processInterface)(mach_port_t masterPort,
+ SCNetworkInterfacePrivateRef interfacePrivate,
+ io_registry_entry_t interface,
+ CFDictionaryRef interface_dict,
+ io_registry_entry_t controller,
+ CFDictionaryRef controller_dict,
+ io_registry_entry_t bus,
+ CFDictionaryRef bus_dict);
+
+
+static Boolean
+processNetworkInterface(mach_port_t masterPort,
+ SCNetworkInterfacePrivateRef interfacePrivate,
+ io_registry_entry_t interface,
+ CFDictionaryRef interface_dict,
+ io_registry_entry_t controller,
+ CFDictionaryRef controller_dict,
+ io_registry_entry_t bus,
+ CFDictionaryRef bus_dict)
+{
+ CFBooleanRef bVal;
+ io_name_t c_IOClass;
+ io_name_t c_IOName;
+ io_name_t i_IOClass;
+ int ift = -1;
+ int iVal;
+ CFNumberRef num;
+ CFStringRef str;
+
+ // get the interface type
+
+ num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &ift)) {
+ SCPrint(TRUE, stderr, CFSTR("Could not get interface type\n"));
+ return FALSE;
+ }
+
+ switch (ift) {
+ case IFT_ETHER :
+ // Type, Hardware
+
+ if (IOObjectGetClass(interface, i_IOClass) != KERN_SUCCESS) {
+ i_IOClass[0] = '\0';
+ }
+ if (IOObjectGetClass(controller, c_IOClass) != KERN_SUCCESS) {
+ c_IOClass[0] = '\0';
+ }
+ if (IORegistryEntryGetName(controller, c_IOName) != KERN_SUCCESS) {
+ c_IOName[0] = '\0';
+ }
+
+ if ((strcmp(i_IOClass, "IO80211Interface" ) == 0) ||
+ (strcmp(c_IOClass, "AirPortPCI" ) == 0) ||
+ (strcmp(c_IOClass, "AirPortDriver" ) == 0) ||
+ (strcmp(c_IOName , "AppleWireless80211") == 0)) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
+ interfacePrivate->entity_type = kSCEntNetEthernet;
+ interfacePrivate->entity_hardware = kSCEntNetAirPort;
+ interfacePrivate->sort_order = kSortAirPort;
+ } else {
+ str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name"));
+ if ((str != NULL) && CFEqual(str, CFSTR("radio"))) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet; // ??
+ interfacePrivate->entity_type = kSCEntNetEthernet;
+ interfacePrivate->entity_hardware = kSCEntNetEthernet; // ??
+ interfacePrivate->sort_order = kSortOtherWireless;
+ } else {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
+ interfacePrivate->entity_type = kSCEntNetEthernet;
+ interfacePrivate->entity_hardware = kSCEntNetEthernet;
+ interfacePrivate->sort_order = kSortEthernet;
+
+ // BOND support only enabled for ethernet devices
+ interfacePrivate->supportsBond = TRUE;
+ }
+
+ if (str != NULL) CFRelease(str);
+ }
+
+ // built-in
+ bVal = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin)));
+ if ((bVal == NULL) || !CFBooleanGetValue(bVal)) {
+ bVal = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOPrimaryInterface)));
+ }
+ if (bVal != NULL) {
+ interfacePrivate->builtin = CFBooleanGetValue(bVal);
+ } else {
+ interfacePrivate->builtin = isBuiltIn(interface);
+ }
+
+ // location
+ interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation));
+
+ // VLAN support
+ num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures));
+ if (isA_CFNumber(num) &&
+ CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
+ if (iVal & (kIONetworkFeatureHardwareVlan | kIONetworkFeatureSoftwareVlan)) {
+ interfacePrivate->supportsVLAN = TRUE;
+ }
+ }
+
+ // localized name
+ if (interfacePrivate->builtin) {
+ if ((interfacePrivate->location == NULL) ||
+ (CFStringGetLength(interfacePrivate->location) == 0)) {
+ interfacePrivate->localized_key = CFSTR("ether");
+ } else {
+ interfacePrivate->localized_key = CFSTR("multiether");
+ interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
+ }
+ } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
+ interfacePrivate->localized_key = CFSTR("airport");
+ } else if (interfacePrivate->sort_order == kSortOtherWireless) {
+ interfacePrivate->localized_key = CFSTR("wireless");
+ interfacePrivate->localized_arg1 = CFRetain(CFSTR("")); // ??
+ } else {
+ CFStringRef provider;
+
+ // check provider class
+ provider = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR(kIOProviderClassKey),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ if (provider != NULL) {
+ if (CFEqual(provider, CFSTR("IOPCIDevice"))) {
+ CFStringRef port_name;
+ CFStringRef slot_name;
+
+ if (pci_slot_info(masterPort, interface, &slot_name, &port_name)) {
+ if (port_name == NULL) {
+ interfacePrivate->localized_key = CFSTR("pci-ether");
+ interfacePrivate->localized_arg1 = slot_name;
+ } else {
+ interfacePrivate->localized_key = CFSTR("pci-multiether");
+ interfacePrivate->localized_arg1 = slot_name;
+ interfacePrivate->localized_arg2 = port_name;
+ }
+ }
+ }
+ CFRelease(provider);
+ }
+
+ if (interfacePrivate->localized_key == NULL) {
+ // if no provider, not a PCI device, or no slot information
+ interfacePrivate->localized_key = CFSTR("generic-ether");
+ interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+ }
+ }
+
+ break;
+ case IFT_IEEE1394 :
+ // Type
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
+
+ // Entity
+ interfacePrivate->entity_type = kSCEntNetFireWire;
+ interfacePrivate->entity_hardware = kSCEntNetFireWire;
+
+ // built-in
+ interfacePrivate->builtin = isBuiltIn(interface);
+
+ // sort order
+ interfacePrivate->sort_order = kSortFireWire;
+
+ // localized name
+ if (interfacePrivate->builtin) {
+ interfacePrivate->localized_key = CFSTR("firewire");
+ } else {
+ CFStringRef slot_name;
+
+ slot_name = pci_slot(interface, NULL);
+ if (slot_name != NULL) {
+ interfacePrivate->localized_key = CFSTR("pci-firewire");
+ interfacePrivate->localized_arg1 = slot_name;
+ }
+ }
+
+ break;
+ default :
+ SCPrint(TRUE, stderr, CFSTR("Unknown interface type = %d\n"), ift);
+ return FALSE;
+ }
+
+ // Device
+ interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+
+ // Hardware (MAC) address
+ interfacePrivate->address = copyMACAddress(controller_dict);
+
+ return TRUE;
+}
+
+
+static Boolean
+processSerialInterface(mach_port_t masterPort,
+ SCNetworkInterfacePrivateRef interfacePrivate,
+ io_registry_entry_t interface,
+ CFDictionaryRef interface_dict,
+ io_registry_entry_t controller,
+ CFDictionaryRef controller_dict,
+ io_registry_entry_t bus,
+ CFDictionaryRef bus_dict)
+{
+ CFStringRef ift;
+ Boolean isModem = FALSE;
+ CFStringRef str;
+ CFTypeRef val;
+
+ // check if hidden
+ val = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR("HiddenPort"),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ if (val != NULL) {
+ CFRelease(val);
+ return FALSE; // if this interface should not be exposed
+ }
+
+ // Type
+ str = CFDictionaryGetValue(interface_dict, CFSTR(kIOTTYBaseNameKey));
+ if (str == NULL) {
+ return FALSE;
+ }
+
+ /*
+ * From MoreSCF:
+ *
+ * Exclude ports named "irda" because otherwise the IrDA ports on the
+ * original iMac (rev's A through D) show up as serial ports. Given
+ * that only the rev A actually had an IrDA port, and Mac OS X doesn't
+ * even support it, these ports definitely shouldn't be listed.
+ */
+ if (CFStringCompare(str,
+ CFSTR("irda"),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ return FALSE;
+ }
+
+ if (IOStringValueHasPrefix(str, CFSTR("irda-ircomm"))) {
+ // IrDA
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
+ interfacePrivate->sort_order = kSortIrDA;
+ } else if (IOStringValueHasPrefix(str, CFSTR("bluetooth"))) {
+ // Bluetooth
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
+ interfacePrivate->sort_order = kSortBluetooth;
+ } else {
+ // Modem
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
+
+ // DeviceOnHold support
+ val = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR(kIODeviceSupportsHoldKey),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ if (val != NULL) {
+ uint32_t supportsHold;
+
+ if (isA_CFNumber(val) &&
+ CFNumberGetValue(val, kCFNumberSInt32Type, &supportsHold)) {
+ interfacePrivate->supportsDeviceOnHold = (supportsHold == 1);
+ }
+ CFRelease(val);
+ }
+ }
+
+ // Entity (Type)
+ interfacePrivate->entity_type = kSCEntNetModem;
+
+ // Entity (Hardware)
+ ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey));
+ if (!isA_CFString(ift)) {
+ return FALSE;
+ }
+
+ if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) {
+ // if modem
+ isModem = TRUE;
+ interfacePrivate->entity_hardware = kSCEntNetModem;
+
+ if (CFEqual(str, CFSTR("modem"))) {
+ interfacePrivate->builtin = TRUE;
+ interfacePrivate->sort_order = kSortInternalModem;
+ } else if (CFEqual(str, CFSTR("usbmodem"))) {
+ interfacePrivate->sort_order = kSortUSBModem;
+ } else {
+ interfacePrivate->sort_order = kSortModem;
+ }
+ } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) {
+ // if serial port
+ interfacePrivate->entity_hardware = kSCEntNetModem;
+ interfacePrivate->sort_order = kSortSerialPort;
+ } else {
+ return FALSE;
+ }
+
+ // Entity (Device)
+ interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey));
+
+ // localized name
+ if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) {
+ interfacePrivate->localized_key = CFSTR("irda");
+ } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) {
+ interfacePrivate->localized_key = CFSTR("bluetooth");
+ } else {
+ CFStringRef localized;
+ CFMutableStringRef port;
+
+ port = CFStringCreateMutableCopy(NULL, 0, str);
+ CFStringLowercase(port, NULL);
+
+ if (!isModem) {
+ CFStringAppend(port, CFSTR("-port"));
+ }
+
+ localized = CFBundleCopyLocalizedString(bundle,
+ port,
+ port,
+ NETWORKINTERFACE_LOCALIZATIONS);
+ if (localized != NULL) {
+ if (!CFEqual(port, localized)) {
+ // if localization available
+ interfacePrivate->localized_name = localized;
+ } else {
+ // if no localization available, use TTY base name
+ CFRelease(localized);
+ interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
+ }
+ } else {
+ interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
+ }
+
+ if (!isModem || !CFEqual(str, CFSTR("modem"))) {
+ CFStringRef productName;
+
+ // check if a "Product Name" has been provided
+ val = IORegistryEntrySearchCFProperty(interface,
+ kIOServicePlane,
+ CFSTR(kIOPropertyProductNameKey),
+ NULL,
+ kIORegistryIterateRecursively | kIORegistryIterateParents);
+ if (val != NULL) {
+ productName = IOCopyCFStringValue(val);
+ CFRelease(val);
+
+ if (productName != NULL) {
+ if (CFStringGetLength(productName) > 0) {
+ // if we have a [somewhat reasonable?] product name
+ CFRelease(interfacePrivate->localized_name);
+ interfacePrivate->localized_name = CFRetain(productName);
+ }
+ CFRelease(productName);
+ }
+ }
+ }
+
+ CFRelease(port);
+ }
+
+ return TRUE;
+}
+
+
+static CFArrayRef
+findMatchingInterfaces(mach_port_t masterPort, CFDictionaryRef matching, processInterface func)
+{
+ CFMutableArrayRef interfaces;
+ io_registry_entry_t interface;
+ kern_return_t kr;
+ io_iterator_t iterator = MACH_PORT_NULL;
+
+ kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
+ if (kr != kIOReturnSuccess) {
+ SCPrint(TRUE, stderr, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr);
+ return NULL;
+ }
+
+ interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
+ io_registry_entry_t bus = MACH_PORT_NULL;
+ CFMutableDictionaryRef bus_dict = NULL;
+ io_registry_entry_t controller = MACH_PORT_NULL;
+ CFMutableDictionaryRef controller_dict = NULL;
+ SCNetworkInterfacePrivateRef interfacePrivate = NULL;
+ CFMutableDictionaryRef interface_dict = NULL;
+ io_string_t path;
+
+ kr = IORegistryEntryGetPath(interface, kIOServicePlane, path);
+ if (kr != kIOReturnSuccess) {
+ SCPrint(TRUE, stderr, CFSTR("IORegistryEntryGetPath() failed, kr = 0x%x"), kr);
+ goto done;
+ }
+
+ kr = IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
+ if (kr != kIOReturnSuccess) {
+ SCPrint(TRUE, stderr, CFSTR("IORegistryEntryCreateCFProperties() failed, kr = 0x%x\n"), kr);
+ goto done;
+ }
+
+ /* get the controller node */
+ kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+ goto done;
+ }
+
+ /* get the dictionary associated with the node */
+ kr = IORegistryEntryCreateCFProperties(controller, &controller_dict, NULL, kNilOptions);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
+ goto done;
+ }
+
+ /* get the bus node */
+ kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+ goto done;
+ }
+
+ /* get the dictionary associated with the node */
+ kr = IORegistryEntryCreateCFProperties(bus, &bus_dict, NULL, kNilOptions);
+ if (kr != KERN_SUCCESS) {
+ SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
+ goto done;
+ }
+
+ interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, path);
+
+ if ((*func)(masterPort, interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) {
+ CFArrayAppendValue(interfaces, (SCNetworkInterfaceRef)interfacePrivate);
+ }
+
+ CFRelease(interfacePrivate);
+
+ done:
+
+ if (interface != MACH_PORT_NULL) IOObjectRelease(interface);
+ if (interface_dict != NULL) CFRelease(interface_dict);
+
+ if (controller != MACH_PORT_NULL) IOObjectRelease(controller);
+ if (controller_dict != NULL) CFRelease(controller_dict);
+
+ if (bus != MACH_PORT_NULL) IOObjectRelease(bus);
+ if (bus_dict != NULL) CFRelease(bus_dict);
+ }
+
+ IOObjectRelease(iterator);
+
+ return interfaces;
+}
+
+
+/* ---------- Bond configuration ---------- */
+
+Boolean
+SCNetworkInterfaceSupportsBonding(SCNetworkInterfaceRef interface)
+{
+ return ((SCNetworkInterfacePrivateRef)interface)->supportsBond;
+}
+
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithBond(BondInterfaceRef bond)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate;
+ CFStringRef bond_if;
+
+ bond_if = BondInterfaceGetInterface(bond);
+ if (bond_if == NULL) {
+ return NULL;
+ }
+
+ interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+ if (interfacePrivate == NULL) {
+ return NULL;
+ }
+
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeBond;
+ interfacePrivate->entity_type = kSCEntNetEthernet;
+ interfacePrivate->entity_hardware = kSCEntNetEthernet;
+ interfacePrivate->entity_device = CFStringCreateCopy(NULL, bond_if);
+ interfacePrivate->builtin = TRUE;
+ interfacePrivate->sort_order = kSortBond;
+
+ interfacePrivate->localized_key = CFSTR("bond");
+ interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
+
+ return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+static CFArrayRef
+findBondInterfaces(CFStringRef match)
+{
+ CFMutableArrayRef interfaces = NULL;
+ CFIndex i;
+ CFIndex n;
+ BondPreferencesRef prefs;
+ CFArrayRef bonds = NULL;
+
+ prefs = BondPreferencesCreate(NULL);
+ if (prefs == NULL) {
+ // if no bonds
+ return NULL;
+ }
+
+ bonds = BondPreferencesCopyInterfaces(prefs);
+ if (bonds == NULL) {
+ // if no bonds
+ goto done;
+ }
+
+ n = CFArrayGetCount(bonds);
+ if (n == 0) {
+ // if no bonds
+ goto done;
+ }
+
+ interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ BondInterfaceRef bond = CFArrayGetValueAtIndex(bonds, i);
+ CFStringRef bond_if;
+
+ bond_if = BondInterfaceGetInterface(bond);
+ if (bond_if == NULL) {
+ continue;
+ }
+
+ if ((match != NULL) && !CFEqual(bond_if, match)) {
+ continue;
+ }
+
+ interface = SCNetworkInterfaceCreateWithBond(bond);
+ CFArrayAppendValue(interfaces, interface);
+ CFRelease(interface);
+ }
+
+ done :
+
+ if (bonds != NULL) CFRelease(bonds);
+ CFRelease(prefs);
+ return interfaces;
+}
+
+
+/* ---------- VLAN configuration ---------- */
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithVLAN(VLANInterfaceRef vlan)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate;
+ CFStringRef vlan_if;
+
+ vlan_if = VLANInterfaceGetInterface(vlan);
+ if (vlan_if == NULL) {
+ return NULL;
+ }
+
+ interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+ if (interfacePrivate == NULL) {
+ return NULL;
+ }
+
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeVLAN;
+ interfacePrivate->entity_type = kSCEntNetEthernet;
+ interfacePrivate->entity_hardware = kSCEntNetEthernet;
+ interfacePrivate->entity_device = CFStringCreateCopy(NULL, vlan_if);
+ interfacePrivate->builtin = TRUE;
+ interfacePrivate->sort_order = kSortVLAN;
+
+ interfacePrivate->localized_key = CFSTR("vlan");
+ interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->entity_device);
+
+ return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+static CFArrayRef
+findVLANInterfaces(CFStringRef match)
+{
+ CFMutableArrayRef interfaces = NULL;
+ CFIndex i;
+ CFIndex n;
+ VLANPreferencesRef prefs;
+ CFArrayRef vlans = NULL;
+
+ prefs = VLANPreferencesCreate(NULL);
+ if (prefs == NULL) {
+ // if no VLANs
+ return NULL;
+ }
+
+ vlans = VLANPreferencesCopyInterfaces(prefs);
+ if (vlans == NULL) {
+ // if no VLANs
+ goto done;
+ }
+
+ n = CFArrayGetCount(vlans);
+ if (n == 0) {
+ // if no VLANs
+ goto done;
+ }
+
+ interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ VLANInterfaceRef vlan = CFArrayGetValueAtIndex(vlans, i);
+ CFStringRef vlan_if;
+
+ vlan_if = VLANInterfaceGetInterface(vlan);
+ if (vlan_if == NULL) {
+ continue;
+ }
+
+ if ((match != NULL) && !CFEqual(vlan_if, match)) {
+ continue;
+ }
+
+ interface = SCNetworkInterfaceCreateWithVLAN(vlan);
+ CFArrayAppendValue(interfaces, interface);
+ CFRelease(interface);
+ }
+
+ done :
+
+ if (vlans != NULL) CFRelease(vlans);
+ CFRelease(prefs);
+ return interfaces;
+}
+
+
+/* ---------- interface from preferences ---------- */
+
+
+__private_extern__ SCNetworkInterfaceRef
+__SCNetworkInterfaceCreateWithEntity(CFAllocatorRef allocator,
+ CFDictionaryRef interface_entity,
+ SCNetworkServiceRef service)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = NULL;
+ CFStringRef ifDevice;
+ CFStringRef ifSubType;
+ CFStringRef ifType;
+ static mach_port_t masterPort = MACH_PORT_NULL;
+ CFArrayRef matching_interfaces = NULL;
+
+ if (masterPort == MACH_PORT_NULL) {
+ kern_return_t kr;
+
+ kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+ if (kr != KERN_SUCCESS) {
+ return NULL;
+ }
+ }
+
+ ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
+ if (!isA_CFString(ifType)) {
+ return NULL;
+ }
+
+ ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
+ if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+ if (!isA_CFString(ifSubType)) {
+ return NULL;
+ }
+ }
+
+ ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
+
+ if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||
+ CFEqual(ifType, kSCValNetInterfaceTypeFireWire) ||
+ (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) {
+ char bsdName[IFNAMSIZ + 1];
+ CFMutableDictionaryRef matching;
+
+ if (!isA_CFString(ifDevice)) {
+ return NULL;
+ }
+
+ if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) {
+ goto done;
+ }
+
+ matching = IOBSDNameMatching(masterPort, 0, bsdName);
+ if (matching == NULL) {
+ goto done;
+ }
+
+ // note: the "matching" dictionary will be consumed by the following
+ matching_interfaces = findMatchingInterfaces(masterPort, matching, processNetworkInterface);
+
+ } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+ if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
+ CFDictionaryRef matching;
+ CFStringRef match_keys[2];
+ CFStringRef match_vals[2];
+
+ if (!isA_CFString(ifDevice)) {
+ return NULL;
+ }
+
+ match_keys[0] = CFSTR(kIOProviderClassKey);
+ match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
+
+ match_keys[1] = CFSTR(kIOTTYDeviceKey);
+ match_vals[1] = ifDevice;
+
+ matching = CFDictionaryCreate(NULL,
+ (const void **)match_keys,
+ (const void **)match_vals,
+ sizeof(match_keys)/sizeof(match_keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ // note: the "matching" dictionary will be consumed by the following
+ matching_interfaces = findMatchingInterfaces(masterPort, matching, processSerialInterface);
+
+ } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) {
+ interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+ kSCNetworkInterfaceTypeL2TP);
+ } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) {
+ interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+ kSCNetworkInterfaceTypePPTP);
+ } else {
+ // XXX do we allow non-Apple variants of PPP??? XXX
+ interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+ ifSubType);
+ }
+ } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
+ if (!isA_CFString(ifDevice)) {
+ return NULL;
+ }
+
+ interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+ kSCNetworkInterfaceType6to4);
+ }
+
+ if (matching_interfaces != NULL) {
+ CFIndex n;
+
+ n = CFArrayGetCount(matching_interfaces);
+ switch (n) {
+ case 0 :
+ if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
+ CFArrayRef bonds;
+ CFArrayRef vlans;
+
+ bonds = findBondInterfaces(ifDevice);
+ if (bonds != NULL) {
+ if (CFArrayGetCount(bonds) == 1) {
+ interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(bonds, 0);
+ CFRetain(interfacePrivate);
+ }
+ CFRelease(bonds);
+ break;
+ }
+
+ vlans = findVLANInterfaces(ifDevice);
+ if (vlans != NULL) {
+ if (CFArrayGetCount(vlans) == 1) {
+ interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(vlans, 0);
+ CFRetain(interfacePrivate);
+ }
+ CFRelease(vlans);
+ break;
+ }
+ }
+ break;
+ case 1 :
+ interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
+ CFRetain(interfacePrivate);
+ break;
+ default :
+ SCPrint(TRUE, stderr, CFSTR("more than one interface matches %@\n"), ifDevice);
+ if (matching_interfaces != NULL) CFRelease(matching_interfaces);
+ _SCErrorSet(kSCStatusFailed);
+ return NULL;
+ }
+ CFRelease(matching_interfaces);
+ }
+
+ done :
+
+ if (interfacePrivate == NULL) {
+ /*
+ * if device not present on this system
+ */
+ interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+ interfacePrivate->entity_type = ifType;
+ interfacePrivate->entity_subtype = ifSubType;
+ interfacePrivate->entity_device = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL;
+ interfacePrivate->entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
+
+ if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
+ if ((interfacePrivate->entity_hardware != NULL) &&
+ CFEqual(interfacePrivate->entity_hardware, kSCEntNetAirPort)) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
+ } else {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
+ }
+ } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
+ } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+ if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
+ } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
+ if (CFStringHasPrefix(ifDevice, CFSTR("irda"))) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
+ } else if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
+ } else {
+ interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
+ }
+ } else {
+ // PPTP, L2TP, ...
+ CFRelease(interfacePrivate);
+ interfacePrivate = (SCNetworkInterfacePrivateRef)kSCNetworkInterfaceIPv4;
+ CFRetain(interfacePrivate);
+ }
+ } else {
+ // unknown interface type
+ CFRelease(interfacePrivate);
+ interfacePrivate = NULL;
+ }
+ }
+
+ if ((interfacePrivate != NULL) && (service != NULL)) {
+ interfacePrivate->service = service;
+ }
+
+ if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+ SCNetworkInterfaceRef parent;
+
+ parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
+ kSCNetworkInterfaceTypePPP);
+ CFRelease(interfacePrivate);
+ interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
+ }
+
+ return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+/* ---------- helper functions ---------- */
+
+
+static CFIndex
+findConfiguration(CFStringRef interface_type)
+{
+ CFIndex i;
+
+ for (i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
+ if (CFEqual(interface_type, *configurations[i].interface_type)) {
+ return i;
+ }
+ }
+
+ return kCFNotFound;
+}
+
+
+static CFArrayRef
+copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate)
+{
+ CFMutableArrayRef array = NULL;
+ CFIndex interfaceIndex;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ interfaceIndex = findConfiguration(interfacePrivate->interface_type);
+ if (interfaceIndex == kCFNotFound) {
+ // if unknown interface type
+ return NULL;
+ }
+
+ servicePrivate = (SCNetworkServicePrivateRef)interfacePrivate->service;
+ if (servicePrivate == NULL) {
+ // if not associated with a service (yet)
+ return NULL;
+ }
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if (configurations[interfaceIndex].per_interface_config) {
+ CFIndex i;
+ CFIndex n;
+ CFArrayRef sets;
+
+ /*
+ * per-interface configuration preferences
+ *
+ * 1. look for all sets which contain the associated service
+ * 2. add a per-set path for the interface configuration for
+ * each set.
+ */
+
+ sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+ n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
+
+ for (i = 0; i < n; i++) {
+ CFArrayRef services;
+ SCNetworkSetRef set;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ services = SCNetworkSetCopyServices(set);
+ if (CFArrayContainsValue(services,
+ CFRangeMake(0, CFArrayGetCount(services)),
+ interfacePrivate->service)) {
+ path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL, // allocator
+ SCNetworkSetGetSetID(set), // set
+ interfacePrivate->entity_device, // service
+ interfacePrivate->entity_type); // entity
+ CFArrayAppendValue(array, path);
+ CFRelease(path);
+ }
+ CFRelease(services);
+ }
+
+ if (CFArrayGetCount(array) == 0) {
+ CFRelease(array);
+ array = NULL;
+ }
+
+ CFRelease(sets);
+ } else {
+ // per-service configuration preferences
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ interfacePrivate->entity_type); // entity
+ CFArrayAppendValue(array, path);
+ CFRelease(path);
+ }
+
+ return array;
+}
+
+
+/* ---------- SCNetworkInterface APIs ---------- */
+
+
+CFArrayRef /* of SCNetworkInterfaceRef's */
+SCNetworkInterfaceCopyAll()
+{
+ CFMutableArrayRef all_interfaces;
+ static mach_port_t masterPort = MACH_PORT_NULL;
+ CFDictionaryRef matching;
+ CFStringRef match_keys[2];
+ CFStringRef match_vals[2];
+ CFArrayRef new_interfaces;
+
+ if (masterPort == MACH_PORT_NULL) {
+ kern_return_t kr;
+
+ kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+ if (kr != KERN_SUCCESS) {
+ return NULL;
+ }
+ }
+
+ all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ // get Ethernet, Firewire, and AirPort interfaces
+
+ matching = IOServiceMatching(kIONetworkInterfaceClass);
+ new_interfaces = findMatchingInterfaces(masterPort, matching, processNetworkInterface);
+ if (new_interfaces != NULL) {
+ CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+ CFRelease(new_interfaces);
+ }
+
+ // get Modem interfaces
+
+ match_keys[0] = CFSTR(kIOProviderClassKey);
+ match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
+
+ match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
+ match_vals[1] = CFSTR(kIOSerialBSDModemType);
+
+ matching = CFDictionaryCreate(NULL,
+ (const void **)match_keys,
+ (const void **)match_vals,
+ sizeof(match_keys)/sizeof(match_keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ new_interfaces = findMatchingInterfaces(masterPort, matching, processSerialInterface);
+ if (new_interfaces != NULL) {
+ CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+ CFRelease(new_interfaces);
+ }
+
+ // get serial (RS232) interfaces
+
+ match_keys[0] = CFSTR(kIOProviderClassKey);
+ match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
+
+ match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
+ match_vals[1] = CFSTR(kIOSerialBSDRS232Type);
+
+ matching = CFDictionaryCreate(NULL,
+ (const void **)match_keys,
+ (const void **)match_vals,
+ sizeof(match_keys)/sizeof(match_keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ new_interfaces = findMatchingInterfaces(masterPort, matching, processSerialInterface);
+ if (new_interfaces != NULL) {
+ CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+ CFRelease(new_interfaces);
+ }
+
+ new_interfaces = findBondInterfaces(NULL);
+ if (new_interfaces != NULL) {
+ CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+ CFRelease(new_interfaces);
+ }
+
+ new_interfaces = findVLANInterfaces(NULL);
+ if (new_interfaces != NULL) {
+ CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+ CFRelease(new_interfaces);
+ }
+
+ sort_interfaces(all_interfaces);
+
+ return all_interfaces;
+}
+
+
+CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface)
+{
+ CFIndex i;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ if (interfacePrivate->supported_interface_types != NULL) {
+ goto done;
+ }
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ i = findConfiguration(interfacePrivate->interface_type);
+ if (i != kCFNotFound) {
+ if (configurations[i].supported_interfaces != doNone) {
+ interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (configurations[i].supported_interfaces & do6to4) {
+ CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4);
+ }
+ if (configurations[i].supported_interfaces & doL2TP) {
+ CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP);
+ }
+ if (configurations[i].supported_interfaces & doPPP) {
+ CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP);
+ }
+ if (configurations[i].supported_interfaces & doPPTP) {
+ CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPTP);
+ }
+ }
+ }
+
+ done :
+
+ return interfacePrivate->supported_interface_types;
+}
+
+
+CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface)
+{
+ CFIndex i;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ if (interfacePrivate->supported_protocol_types != NULL) {
+ goto done;
+ }
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ i = findConfiguration(interfacePrivate->interface_type);
+ if (i != kCFNotFound) {
+ if (configurations[i].supported_protocols != doNone) {
+ interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (configurations[i].supported_protocols & doAppleTalk) {
+ CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeAppleTalk);
+ }
+ if (configurations[i].supported_protocols & doDNS) {
+ CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS);
+ }
+ if (configurations[i].supported_protocols & doIPv4) {
+ CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4);
+ }
+ if (configurations[i].supported_protocols & doIPv6) {
+ CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6);
+ }
+ if (configurations[i].supported_protocols & doProxies) {
+ CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies);
+ }
+ }
+ }
+
+ done :
+
+ return interfacePrivate->supported_protocol_types;
+}
+
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType)
+{
+ SCNetworkInterfacePrivateRef childPrivate = (SCNetworkInterfacePrivateRef)child;
+ CFIndex childIndex;
+ SCNetworkInterfacePrivateRef parentPrivate;
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ childIndex = findConfiguration(childPrivate->interface_type);
+
+ parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL, child, childPrivate->service, NULL);
+ if (parentPrivate == NULL) {
+ _SCErrorSet(kSCStatusFailed);
+ return NULL;
+ }
+
+ if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
+ parentPrivate->interface_type = kSCNetworkInterfaceTypePPP;
+ parentPrivate->entity_type = kSCEntNetPPP;
+
+ // entity subtype
+ if (childIndex != kCFNotFound) {
+ if (configurations[childIndex].ppp_subtype != NULL) {
+ parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype;
+ } else {
+ // sorry, the child interface does not support PPP
+ goto fail;
+ }
+ } else {
+ // if the child's interface type not known, use the child entities "Type"
+ parentPrivate->entity_subtype = childPrivate->entity_type;
+ }
+
+ if (childPrivate->entity_device != NULL) {
+ parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
+ }
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
+ if ((childIndex == kCFNotFound) ||
+ ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) {
+ // if the child interface does not support L2TP
+ goto fail;
+ }
+ parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP;
+ parentPrivate->entity_type = kSCValNetInterfaceSubTypeL2TP; // interface config goes into "L2TP"
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) {
+ if ((childIndex == kCFNotFound) ||
+ ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) {
+ // if the child interface does not support PPTP
+ goto fail;
+ }
+ parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP;
+ parentPrivate->entity_type = kSCValNetInterfaceSubTypePPTP; // interface config goes into "PPTP"
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) {
+ if ((childIndex == kCFNotFound) ||
+ ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) {
+ // if the child interface does not support 6to4
+ goto fail;
+ }
+
+ parentPrivate->interface_type = kSCNetworkInterfaceType6to4;
+ parentPrivate->entity_type = kSCEntNet6to4;
+ parentPrivate->entity_device = CFRetain(CFSTR("stf0"));
+ CFRetain(parentPrivate->entity_device);
+ } else {
+ // unknown interface type
+ goto fail;
+ }
+
+ parentPrivate->entity_hardware = childPrivate->entity_hardware;
+ parentPrivate->sort_order = childPrivate->sort_order;
+
+ return (SCNetworkInterfaceRef)parentPrivate;
+
+ fail :
+
+ CFRelease(parentPrivate);
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return NULL;
+}
+
+
+static CFDictionaryRef
+__SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface, Boolean okToHold)
+{
+ CFDictionaryRef config = NULL;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+ CFArrayRef paths;
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ paths = copyConfigurationPaths(interfacePrivate);
+ if (paths != NULL) {
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)interfacePrivate->service;
+
+ path = CFArrayGetValueAtIndex(paths, 0);
+ config = __getPrefsConfiguration(servicePrivate->prefs, path);
+
+ CFRelease(paths);
+ } else if (okToHold) {
+ config = interfacePrivate->unsaved;
+ }
+
+ return config;
+}
+
+
+CFDictionaryRef
+SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface)
+{
+ return __SCNetworkInterfaceGetConfiguration(interface, FALSE);
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ if (interfacePrivate->interface != NULL) {
+ return NULL;
+ }
+
+ return interfacePrivate->entity_device;
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ return interfacePrivate->address;
+}
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ return interfacePrivate->interface;
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ return interfacePrivate->interface_type;
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+
+ if (interfacePrivate->localized_name == NULL) {
+ CFStringRef child = NULL;
+ CFMutableStringRef local = NULL;
+
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */
+
+ if (interfacePrivate->interface != NULL) {
+ child = SCNetworkInterfaceGetLocalizedDisplayName(interfacePrivate->interface);
+ }
+
+ if (interfacePrivate->localized_key != NULL) {
+ CFStringRef fmt;
+
+ fmt = CFBundleCopyLocalizedString(bundle,
+ interfacePrivate->localized_key,
+ interfacePrivate->localized_key,
+ NETWORKINTERFACE_LOCALIZATIONS);
+ if (fmt != NULL) {
+ local = CFStringCreateMutable(NULL, 0);
+ CFStringAppendFormat(local,
+ NULL,
+ fmt,
+ interfacePrivate->localized_arg1,
+ interfacePrivate->localized_arg2);
+ CFRelease(fmt);
+ }
+ }
+
+ if (local == NULL) {
+ // create (non-)localized name based on the interface type
+ local = CFStringCreateMutableCopy(NULL, 0, interfacePrivate->interface_type);
+
+ // ... and, if this is a leaf node, the interface device
+ if ((interfacePrivate->entity_device != NULL) && (child == NULL)) {
+ CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device);
+ }
+ }
+
+ if (child == NULL) {
+ // no child, show just this interfaces localized name
+ interfacePrivate->localized_name = CFStringCreateCopy(NULL, local);
+ } else {
+ // show localized interface name layered over child
+ interfacePrivate->localized_name = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("%@ --> %@"),
+ local,
+ child);
+ }
+ CFRelease(local);
+ }
+
+ return interfacePrivate->localized_name;
+}
+
+
+CFTypeID
+SCNetworkInterfaceGetTypeID(void)
+{
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize); /* initialize runtime */
+ return __kSCNetworkInterfaceTypeID;
+}
+
+
+__private_extern__ Boolean
+__SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config, Boolean okToHold)
+{
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+ Boolean ok = FALSE;
+ CFArrayRef paths;
+
+ /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+ pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+ paths = copyConfigurationPaths(interfacePrivate);
+ if (paths != NULL) {
+ CFIndex i;
+ CFIndex n;
+ SCPreferencesRef prefs;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ servicePrivate = (SCNetworkServicePrivateRef)interfacePrivate->service;
+ prefs = servicePrivate->prefs;
+
+ n = CFArrayGetCount(paths);
+ for (i = 0; i < n; i++) {
+ CFStringRef path;
+
+ path = CFArrayGetValueAtIndex(paths, i);
+ ok = __setPrefsConfiguration(prefs, path, config, FALSE);
+ if (!ok) {
+ break;
+ }
+ }
+
+ CFRelease(paths);
+ } else if (okToHold) {
+ interfacePrivate->unsaved = config;
+ ok = TRUE;
+ } else {
+ _SCErrorSet(kSCStatusNoKey);
+ }
+
+ return ok;
+}
+
+
+Boolean
+SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config)
+{
+ return __SCNetworkInterfaceSetConfiguration(interface, config, FALSE);
+}
+
+
+/* ---------- SCNetworkInterface internal SPIs ---------- */
+
+
+__private_extern__ SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreateCopy(CFAllocatorRef allocator,
+ SCNetworkInterfaceRef interface,
+ SCNetworkServiceRef service)
+{
+ SCNetworkInterfacePrivateRef oldPrivate = (SCNetworkInterfacePrivateRef)interface;
+ SCNetworkInterfacePrivateRef newPrivate;
+
+ newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+ newPrivate->interface_type = CFRetain(oldPrivate->interface_type);
+ if (oldPrivate->interface != NULL) {
+ newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, // allocator
+ oldPrivate->interface, // interface
+ service); // [new] service
+ }
+ newPrivate->localized_name = (oldPrivate->localized_name != NULL) ? CFRetain(oldPrivate->localized_name) : NULL;
+ newPrivate->service = service;
+ newPrivate->unsaved = (oldPrivate->unsaved != NULL) ? CFRetain(oldPrivate->unsaved) : NULL;
+ newPrivate->entity_device = (oldPrivate->entity_device != NULL) ? CFRetain(oldPrivate->entity_device) : NULL;
+ newPrivate->entity_hardware = CFRetain(oldPrivate->entity_hardware);
+ newPrivate->entity_type = oldPrivate->entity_type;
+ newPrivate->entity_subtype = oldPrivate->entity_subtype;
+ if (oldPrivate->supported_interface_types != NULL) {
+ newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types);
+ }
+ if (oldPrivate->supported_protocol_types != NULL) {
+ newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types);
+ }
+ newPrivate->address = (oldPrivate->address != NULL) ? CFRetain(oldPrivate->address) : NULL;
+ newPrivate->builtin = oldPrivate->builtin;
+ newPrivate->path = (oldPrivate->path != NULL) ? CFRetain(oldPrivate->path) : NULL;
+ newPrivate->location = (oldPrivate->location != NULL) ? CFRetain(oldPrivate->location) : NULL;
+ newPrivate->supportsDeviceOnHold = oldPrivate->supportsDeviceOnHold;
+ newPrivate->supportsBond = oldPrivate->supportsBond;
+ newPrivate->supportsVLAN = oldPrivate->supportsVLAN;
+ newPrivate->sort_order = oldPrivate->sort_order;
+
+ return newPrivate;
+}
+
+
+__private_extern__ CFArrayRef
+__SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface)
+{
+ CFDictionaryRef config;
+ CFMutableArrayRef configs;
+
+ configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ while (interface != NULL) {
+ config = __SCNetworkInterfaceGetConfiguration(interface, TRUE);
+ CFArrayAppendValue(configs,
+ (config != NULL) ? config : (CFDictionaryRef)kCFNull);
+ interface = SCNetworkInterfaceGetInterface(interface);
+ }
+
+ return configs;
+}
+
+
+__private_extern__ void
+__SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface, CFArrayRef configs)
+{
+ CFIndex i;
+
+ for (i = 0; interface != NULL; i++) {
+ CFDictionaryRef config;
+
+ config = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL;
+ if (!isA_CFDictionary(config) || (CFDictionaryGetCount(config) == 0)) {
+ config = NULL;
+ }
+
+ (void) __SCNetworkInterfaceSetConfiguration(interface, config, TRUE);
+ interface = SCNetworkInterfaceGetInterface(interface);
+ }
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 13, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "SCNetworkConfiguration.h"
+#include "SCNetworkConfigurationInternal.h"
+
+#include <pthread.h>
+
+
+static CFStringRef __SCNetworkProtocolCopyDescription (CFTypeRef cf);
+static void __SCNetworkProtocolDeallocate (CFTypeRef cf);
+static Boolean __SCNetworkProtocolEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+
+const CFStringRef kSCNetworkProtocolTypeAppleTalk = CFSTR("AppleTalk");
+const CFStringRef kSCNetworkProtocolTypeDNS = CFSTR("DNS");
+const CFStringRef kSCNetworkProtocolTypeIPv4 = CFSTR("IPv4");
+const CFStringRef kSCNetworkProtocolTypeIPv6 = CFSTR("IPv6");
+const CFStringRef kSCNetworkProtocolTypeProxies = CFSTR("Proxies");
+
+
+static CFTypeID __kSCNetworkProtocolTypeID = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkProtocolClass = {
+ 0, // version
+ "SCNetworkProtocol", // className
+ NULL, // init
+ NULL, // copy
+ __SCNetworkProtocolDeallocate, // dealloc
+ __SCNetworkProtocolEqual, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __SCNetworkProtocolCopyDescription // copyDebugDesc
+};
+
+
+static pthread_once_t initialized = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkProtocol(CFTypeRef obj)
+{
+ return (isA_CFType(obj, SCNetworkProtocolGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkProtocolCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkProtocol %p [%p]> { "), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR("id=%@"), protocolPrivate->entityID);
+ CFStringAppendFormat(result, NULL, CFSTR(", service=%@"), protocolPrivate->service);
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__SCNetworkProtocolDeallocate(CFTypeRef cf)
+{
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
+
+ /* release resources */
+ CFRelease(protocolPrivate->entityID);
+
+ return;
+}
+
+
+static Boolean
+__SCNetworkProtocolEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+ SCNetworkProtocolPrivateRef p1 = (SCNetworkProtocolPrivateRef)cf1;
+ SCNetworkProtocolPrivateRef p2 = (SCNetworkProtocolPrivateRef)cf2;
+
+ if (p1 == p2)
+ return TRUE;
+
+ if (!CFEqual(p1->entityID, p2->entityID))
+ return FALSE; // if not the same protocol type
+
+ if (p1->service == p2->service)
+ return TRUE; // if both point to the same service
+
+ if ((p1->service != NULL) && (p2->service != NULL) && CFEqual(p1->service, p2->service))
+ return TRUE; // if both effectively point to the same service
+
+ return FALSE;
+}
+
+
+static void
+__SCNetworkProtocolInitialize(void)
+{
+ __kSCNetworkProtocolTypeID = _CFRuntimeRegisterClass(&__SCNetworkProtocolClass);
+ return;
+}
+
+
+__private_extern__ SCNetworkProtocolPrivateRef
+__SCNetworkProtocolCreatePrivate(CFAllocatorRef allocator,
+ CFStringRef entityID,
+ SCNetworkServiceRef service)
+{
+ SCNetworkProtocolPrivateRef protocolPrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&initialized, __SCNetworkProtocolInitialize);
+
+ /* allocate target */
+ size = sizeof(SCNetworkProtocolPrivate) - sizeof(CFRuntimeBase);
+ protocolPrivate = (SCNetworkProtocolPrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kSCNetworkProtocolTypeID,
+ size,
+ NULL);
+ if (protocolPrivate == NULL) {
+ return NULL;
+ }
+
+ protocolPrivate->entityID = CFStringCreateCopy(NULL, entityID);
+ protocolPrivate->service = service;
+
+ return protocolPrivate;
+}
+
+
+__private_extern__ Boolean
+__SCNetworkProtocolIsValidType(CFStringRef protocolType)
+{
+ int i;
+ static const CFStringRef *valid_types[] = {
+ &kSCNetworkProtocolTypeAppleTalk,
+ &kSCNetworkProtocolTypeDNS,
+ &kSCNetworkProtocolTypeIPv4,
+ &kSCNetworkProtocolTypeIPv6,
+ &kSCNetworkProtocolTypeProxies
+ };
+
+ for (i = 0; i < sizeof(valid_types)/sizeof(valid_types[0]); i++) {
+ if (CFEqual(protocolType, *valid_types[i])) {
+ // if known/valid protocol type
+ return TRUE;
+ }
+ }
+
+ if (CFStringFindWithOptions(protocolType,
+ CFSTR("."),
+ CFRangeMake(0, CFStringGetLength(protocolType)),
+ 0,
+ NULL)) {
+ // if user-defined protocol type (e.g. com.apple.myProtocol)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static CFStringRef
+copyProtocolConfigurationPath(SCNetworkProtocolPrivateRef protocolPrivate)
+{
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ protocolPrivate->entityID); // entity
+ return path;
+}
+
+
+/* ---------- SCNetworkProtocol APIs ---------- */
+
+
+CFTypeID
+SCNetworkProtocolGetTypeID()
+{
+ pthread_once(&initialized, __SCNetworkProtocolInitialize); /* initialize runtime */
+ return __kSCNetworkProtocolTypeID;
+}
+
+
+CFDictionaryRef
+SCNetworkProtocolGetConfiguration(SCNetworkProtocolRef protocol)
+{
+ CFDictionaryRef config;
+ CFStringRef path;
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+ path = copyProtocolConfigurationPath(protocolPrivate);
+ config = __getPrefsConfiguration(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ return config;
+}
+
+
+Boolean
+SCNetworkProtocolGetEnabled(SCNetworkProtocolRef protocol)
+{
+ Boolean enabled;
+ CFStringRef path;
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+ path = copyProtocolConfigurationPath(protocolPrivate);
+ enabled = __getPrefsEnabled(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ return enabled;
+}
+
+
+CFStringRef
+SCNetworkProtocolGetProtocolType(SCNetworkProtocolRef protocol)
+{
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+
+ return protocolPrivate->entityID;
+}
+
+
+Boolean
+SCNetworkProtocolSetConfiguration(SCNetworkProtocolRef protocol, CFDictionaryRef config)
+{
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+ path = copyProtocolConfigurationPath(protocolPrivate);
+ ok = __setPrefsConfiguration(servicePrivate->prefs, path, config, TRUE);
+ CFRelease(path);
+
+ return ok;
+}
+
+
+Boolean
+SCNetworkProtocolSetEnabled(SCNetworkProtocolRef protocol, Boolean enabled)
+{
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+ path = copyProtocolConfigurationPath(protocolPrivate);
+ ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
+ CFRelease(path);
+
+ return ok;
+}
/*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2004 Apple Computer, 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,
* 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@
*/
/*
* Modification History
*
+ * March 31, 2004 Allan Nathanson <ajn@apple.com>
+ * - use [SC] DNS configuration information
+ *
* January 19, 2003 Allan Nathanson <ajn@apple.com>
* - add advanced reachability APIs
*/
#include <CoreFoundation/CFRuntime.h>
#include <pthread.h>
+#include <notify.h>
+#include <dnsinfo.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <arpa/nameser.h>
#include <netdb.h>
#include <netdb_async.h>
#include <resolv.h>
#define s6_addr16 __u6_addr.__u6_addr16
#endif
-#include "ppp.h"
+#include <ppp/ppp_msg.h>
#define kSCNetworkFlagsFirstResolvePending (1<<31)
SCNetworkReachabilityContext rlsContext;
CFMutableArrayRef rlList;
- /* async DNS query info */
+ /* [async] DNS query info */
+ Boolean haveDNS;
CFMachPortRef dnsPort;
CFRunLoopSourceRef dnsRLS;
+ struct timeval dnsQueryStart;
} SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef;
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
-static Boolean needDNS = TRUE;
-/* host "something has changed" notifications */
+/*
+ * host "something has changed" notifications
+ */
+
static pthread_mutex_t hn_lock = PTHREAD_MUTEX_INITIALIZER;
static SCDynamicStoreRef hn_store = NULL;
static CFRunLoopSourceRef hn_storeRLS = NULL;
static CFMutableSetRef hn_targets = NULL;
-static __inline__ CFTypeRef
-isA_SCNetworkReachability(CFTypeRef obj)
-{
- return (isA_CFType(obj, SCNetworkReachabilityGetTypeID()));
-}
+/*
+ * DNS configuration
+ */
+typedef struct {
+ dns_config_t *config;
+ int refs;
+} dns_configuration_t;
-static void
-sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
-{
- bzero(buf, bufLen);
- switch (address->sa_family) {
- case AF_INET :
- (void)inet_ntop(((struct sockaddr_in *)address)->sin_family,
- &((struct sockaddr_in *)address)->sin_addr,
- buf,
- bufLen);
- break;
- case AF_INET6 : {
- (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family,
- &((struct sockaddr_in6 *)address)->sin6_addr,
- buf,
- bufLen);
- if (((struct sockaddr_in6 *)address)->sin6_scope_id != 0) {
- int n;
-
- n = strlen(buf);
- if ((n+IF_NAMESIZE+1) <= (int)bufLen) {
- buf[n++] = '%';
- if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]);
- }
- }
- break;
- }
- case AF_LINK :
- if (((struct sockaddr_dl *)address)->sdl_len < bufLen) {
- bufLen = ((struct sockaddr_dl *)address)->sdl_len;
- } else {
- bufLen = bufLen - 1;
- }
- bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen);
- break;
- default :
- snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
- break;
- }
+static pthread_mutex_t dns_lock = PTHREAD_MUTEX_INITIALIZER;
+static dns_configuration_t *dns_configuration = NULL;
+static int dns_token;
+static Boolean dns_token_valid = FALSE;
- return;
-}
-
-#ifndef CHECK_IPV6_REACHABILITY
-static char *
-__netdb_error(int error)
+static __inline__ CFTypeRef
+isA_SCNetworkReachability(CFTypeRef obj)
{
- char *msg;
-
- switch(error) {
- case NETDB_INTERNAL :
- msg = strerror(errno);
- break;
- case HOST_NOT_FOUND :
- msg = "Host not found.";
- break;
- case TRY_AGAIN :
- msg = "Try again.";
- break;
- case NO_RECOVERY :
- msg = "No recovery.";
- break;
- case NO_DATA :
- msg = "No data available.";
- break;
- default :
- msg = "Unknown";
- break;
- }
-
- return msg;
+ return (isA_CFType(obj, SCNetworkReachabilityGetTypeID()));
}
-#endif /* CHECK_IPV6_REACHABILITY */
static void
-__signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList)
+__log_query_time(Boolean found, Boolean async, struct timeval *start)
{
- CFRunLoopRef rl = NULL;
- CFRunLoopRef rl1 = NULL;
- CFIndex i;
- CFIndex n = CFArrayGetCount(rlList);
+ struct timeval dnsQueryComplete;
+ struct timeval dnsQueryElapsed;
- if (n == 0) {
+ if (!_sc_debug) {
return;
}
- /* get first runLoop for this object */
- for (i = 0; i < n; i += 3) {
- if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- continue;
- }
-
- rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
- break;
- }
-
- if (!rl1) {
- /* if not scheduled */
+ if (start->tv_sec == 0) {
return;
}
- /* check if we have another runLoop for this object */
- rl = rl1;
- for (i = i+3; i < n; i += 3) {
- CFRunLoopRef rl2;
+ (void) gettimeofday(&dnsQueryComplete, NULL);
+ timersub(&dnsQueryComplete, start, &dnsQueryElapsed);
+ SCLog(TRUE, LOG_DEBUG,
+ CFSTR("%ssync DNS complete%s (query time = %d.%3.3d)"),
+ async ? "a" : "",
+ found ? "" : ", host not found",
+ dnsQueryElapsed.tv_sec,
+ dnsQueryElapsed.tv_usec / 1000);
- if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- continue;
- }
-
- rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
- if (!CFEqual(rl1, rl2)) {
- /* we've got more than one runLoop */
- rl = NULL;
- break;
- }
- }
-
- if (rl) {
- /* if we only have one runLoop */
- CFRunLoopWakeUp(rl);
- return;
- }
-
- /* more than one different runLoop, so we must pick one */
- for (i = 0; i < n; i+=3) {
- CFStringRef rlMode;
-
- if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- continue;
- }
-
- rl = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
- rlMode = CFRunLoopCopyCurrentMode(rl);
- if (rlMode && CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode)) {
- /* we've found a runLoop that's "ready" */
- CFRelease(rlMode);
- CFRunLoopWakeUp(rl);
- return;
- }
- if (rlMode) CFRelease(rlMode);
- }
-
- /* didn't choose one above, so choose first */
- CFRunLoopWakeUp(rl1);
return;
}
CFIndex n;
CFStringRef ppp_if;
int sc_status = kSCStatusReachabilityUnknown;
- SCDynamicStoreRef store = (storeP) ? *storeP : NULL;
+ SCDynamicStoreRef store = (storeP != NULL) ? *storeP : NULL;
const void * values_q[N_QUICK];
const void ** values = values_q;
goto done;
}
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("updatePPPStatus SCDynamicStoreCreate() failed"));
goto done;
}
}
dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
CFRelease(patterns);
}
- if (!dict) {
+ if (dict == NULL) {
/* if we could not access the dynamic store */
goto done;
}
done :
- if (dict) CFRelease(dict);
- if (storeP) *storeP = store;
+ if (dict != NULL) CFRelease(dict);
+ if (storeP != NULL) *storeP = store;
return sc_status;
}
static int
updatePPPAvailable(SCDynamicStoreRef *storeP,
- const struct sockaddr *sa,
- SCNetworkConnectionFlags *flags)
+ const struct sockaddr *sa,
+ SCNetworkConnectionFlags *flags)
{
CFDictionaryRef dict = NULL;
CFStringRef entity;
const void ** keys = keys_q;
CFIndex n;
int sc_status = kSCStatusReachabilityUnknown;
- SCDynamicStoreRef store = (storeP) ? *storeP : NULL;
+ SCDynamicStoreRef store = (storeP != NULL) ? *storeP : NULL;
const void * values_q[N_QUICK];
const void ** values = values_q;
- switch (sa->sa_family) {
- case AF_INET :
- entity = kSCEntNetIPv4;
- break;
- case AF_INET6 :
- entity = kSCEntNetIPv6;
- break;
- default :
- goto done;
+ if (sa == NULL) {
+ entity = kSCEntNetIPv4;
+ } else {
+ switch (sa->sa_family) {
+ case AF_INET :
+ entity = kSCEntNetIPv4;
+ break;
+ case AF_INET6 :
+ entity = kSCEntNetIPv6;
+ break;
+ default :
+ goto done;
+ }
}
- if (!store) {
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
+ SCLog(_sc_debug, LOG_INFO, CFSTR(" status = unknown (could not access SCDynamicStore"));
goto done;
}
}
dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
CFRelease(patterns);
}
- if (!dict) {
+ if (dict == NULL) {
/* if we could not access the dynamic store */
goto done;
}
done :
- if (dict) CFRelease(dict);
- if (storeP) *storeP = store;
+ if (dict != NULL) CFRelease(dict);
+ if (storeP != NULL) *storeP = store;
return sc_status;
}
int sc_status = kSCStatusReachabilityUnknown;
struct sockaddr_dl *sdl;
int seq = (int)pthread_self();
- SCDynamicStoreRef store = (storeP) ? *storeP : NULL;
+ SCDynamicStoreRef store = (storeP != NULL) ? *storeP : NULL;
char *statusMessage = NULL;
#ifndef RTM_GET_SILENT
#warning Note: Using RTM_GET (and not RTM_GET_SILENT)
int sosize = 48 * 1024;
#endif
- if (!address || !flags) {
- sc_status = kSCStatusInvalidArgument;
- goto done;
+ *flags = 0;
+ if (if_index != NULL) {
+ *if_index = 0;
+ }
+
+ if (address == NULL) {
+ /* special case: check only for available paths off the system */
+ goto checkAvailable;
}
switch (address->sa_family) {
case AF_INET :
case AF_INET6 :
if (_sc_debug) {
- sockaddr_to_string(address, buf, sizeof(buf));
+ _SC_sockaddr_to_string(address, buf, sizeof(buf));
SCLog(TRUE, LOG_INFO, CFSTR("checkAddress(%s)"), buf);
}
break;
goto done;
}
- *flags = 0;
- if (if_index) {
- *if_index = 0;
- }
-
- if ((address->sa_family == AF_INET) && (((struct sockaddr_in *)address)->sin_addr.s_addr == 0)) {
- /* special case: check for available paths off the system */
- goto checkAvailable;
- }
-
bzero(&buf, sizeof(buf));
rtm = (struct rt_msghdr *)&buf;
for (i = 0; i < RTAX_MAX; i++) {
if (rti_info[i] != NULL) {
- sockaddr_to_string(rti_info[i], buf, sizeof(buf));
+ _SC_sockaddr_to_string(rti_info[i], buf, sizeof(buf));
SCLog(_sc_debug, LOG_DEBUG, CFSTR("%d: %s"), i, buf);
}
}
if ((rti_info[RTAX_IFP] == NULL) ||
(rti_info[RTAX_IFP]->sa_family != AF_LINK)) {
/* no interface info */
- goto done; // ???
+ goto done;
}
sdl = (struct sockaddr_dl *) rti_info[RTAX_IFP];
if ((sdl->sdl_nlen == 0) || (sdl->sdl_nlen > IFNAMSIZ)) {
/* no interface name */
- goto done; // ???
+ goto checkAvailable;
}
/* get the interface flags */
addr1 = &((struct sockaddr_in *)address)->sin_addr;
addr2 = &((struct sockaddr_in *)rti_info[RTAX_IFA])->sin_addr;
len = sizeof(struct in_addr);
+
+ /*
+ * check if 0.0.0.0
+ */
+ if (((struct sockaddr_in *)address)->sin_addr.s_addr == 0) {
+ statusMessage = "isReachable (this host)";
+ *flags |= kSCNetworkFlagsIsLocalAddress;
+ }
break;
case AF_INET6 :
addr1 = &((struct sockaddr_in6 *)address)->sin6_addr;
}
}
- if (rti_info[RTAX_GATEWAY] && (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) {
+ if (!(rtm->rtm_flags & RTF_GATEWAY) &&
+ (rti_info[RTAX_GATEWAY] != NULL) &&
+ (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) &&
+ !(ifr.ifr_flags & IFF_POINTOPOINT)) {
*flags |= kSCNetworkFlagsIsDirect;
}
if_name,
(sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ);
- if (if_index) {
+ if (if_index != NULL) {
*if_index = sdl->sdl_index;
}
SCLog(_sc_debug, LOG_INFO, CFSTR(" cannot be reached"));
}
- if (storeP) *storeP = store;
+ if (storeP != NULL) *storeP = store;
if (sc_status != kSCStatusOK) {
_SCErrorSet(sc_status);
return FALSE;
}
-static Boolean
-checkAddressZero(SCDynamicStoreRef *storeP,
- SCNetworkConnectionFlags *flags,
- uint16_t *if_index)
-{
- Boolean ok;
- struct sockaddr_in sin;
-
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = 0;
-
- ok = checkAddress(storeP, (struct sockaddr *)&sin, flags, if_index);
-
- return ok;
-}
-
-
-static Boolean
-isAddressZero(struct sockaddr *sa, SCNetworkConnectionFlags *flags)
-{
- /*
- * Check if 0.0.0.0
- */
- if (sa->sa_family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-
- if (sin->sin_addr.s_addr == 0) {
- SCLog(_sc_debug, LOG_INFO, CFSTR("isAddressZero(0.0.0.0)"));
- SCLog(_sc_debug, LOG_INFO, CFSTR(" status = isReachable (this host)"));
- *flags |= kSCNetworkFlagsReachable;
- *flags |= kSCNetworkFlagsIsLocalAddress;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-
static CFStringRef
__SCNetworkReachabilityCopyDescription(CFTypeRef cf)
{
case reachabilityTypeAddressPair : {
char buf[64];
- if (targetPrivate->localAddress) {
- sockaddr_to_string(targetPrivate->localAddress, buf, sizeof(buf));
+ if (targetPrivate->localAddress != NULL) {
+ _SC_sockaddr_to_string(targetPrivate->localAddress, buf, sizeof(buf));
CFStringAppendFormat(result, NULL, CFSTR("local address=%s"),
buf);
}
- if (targetPrivate->remoteAddress) {
- sockaddr_to_string(targetPrivate->remoteAddress, buf, sizeof(buf));
+ if (targetPrivate->remoteAddress != NULL) {
+ _SC_sockaddr_to_string(targetPrivate->remoteAddress, buf, sizeof(buf));
CFStringAppendFormat(result, NULL, CFSTR("%s%saddress=%s"),
targetPrivate->localAddress ? ", " : "",
(targetPrivate->type == reachabilityTypeAddressPair) ? "remote " : "",
case reachabilityTypeName : {
CFStringAppendFormat(result, NULL, CFSTR("name=%s"), targetPrivate->name);
if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
- if (targetPrivate->resolvedAddress) {
+ if (targetPrivate->resolvedAddress != NULL) {
if (isA_CFArray(targetPrivate->resolvedAddress)) {
CFIndex i;
CFIndex n = CFArrayGetCount(targetPrivate->resolvedAddress);
address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
sa = (struct sockaddr *)CFDataGetBytePtr(address);
- sockaddr_to_string(sa, buf, sizeof(buf));
+ _SC_sockaddr_to_string(sa, buf, sizeof(buf));
CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
i > 0 ? ", " : "",
buf);
CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)"));
}
} else {
-#ifdef CHECK_IPV6_REACHABILITY
CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
gai_strerror(targetPrivate->resolvedAddressError));
-#else /* CHECK_IPV6_REACHABILITY */
- CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
- __netdb_error(targetPrivate->resolvedAddressError));
-#endif /* CHECK_IPV6_REACHABILITY */
}
} else if (targetPrivate->dnsPort) {
CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)"));
break;
}
}
- if (targetPrivate->rls) {
+ if (targetPrivate->rls != NULL) {
CFStringAppendFormat(result,
NULL,
CFSTR(", flags=%8.8x, if_index=%hu"),
{
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)cf;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityDeallocate:"));
-
/* release resources */
pthread_mutex_destroy(&targetPrivate->lock);
- if (targetPrivate->name)
+ if (targetPrivate->name != NULL)
CFAllocatorDeallocate(NULL, (void *)targetPrivate->name);
- if (targetPrivate->resolvedAddress)
+ if (targetPrivate->resolvedAddress != NULL)
CFRelease(targetPrivate->resolvedAddress);
- if (targetPrivate->localAddress)
+ if (targetPrivate->localAddress != NULL)
CFAllocatorDeallocate(NULL, (void *)targetPrivate->localAddress);
- if (targetPrivate->remoteAddress)
+ if (targetPrivate->remoteAddress != NULL)
CFAllocatorDeallocate(NULL, (void *)targetPrivate->remoteAddress);
- if (targetPrivate->rlsContext.release) {
- targetPrivate->rlsContext.release(targetPrivate->rlsContext.info);
+ if (targetPrivate->rlsContext.release != NULL) {
+ (*targetPrivate->rlsContext.release)(targetPrivate->rlsContext.info);
}
return;
/* initialize runtime */
pthread_once(&initialized, __SCNetworkReachabilityInitialize);
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityCreatePrivate:"));
-
/* allocate target */
size = sizeof(SCNetworkReachabilityPrivate) - sizeof(CFRuntimeBase);
targetPrivate = (SCNetworkReachabilityPrivateRef)_CFRuntimeCreateInstance(allocator,
__kSCNetworkReachabilityTypeID,
size,
NULL);
- if (!targetPrivate) {
+ if (targetPrivate == NULL) {
return NULL;
}
targetPrivate->rlsContext.copyDescription = NULL;
targetPrivate->rlList = NULL;
+ targetPrivate->haveDNS = FALSE;
targetPrivate->dnsPort = NULL;
targetPrivate->dnsRLS = NULL;
{
SCNetworkReachabilityPrivateRef targetPrivate;
- if (!address ||
+ if ((address == NULL) ||
(address->sa_len == 0) ||
(address->sa_len > sizeof(struct sockaddr_storage))) {
_SCErrorSet(kSCStatusInvalidArgument);
}
targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
- if (!targetPrivate) {
+ if (targetPrivate == NULL) {
return NULL;
}
return NULL;
}
- if (localAddress) {
+ if (localAddress != NULL) {
if ((localAddress->sa_len == 0) ||
(localAddress->sa_len > sizeof(struct sockaddr_storage))) {
_SCErrorSet(kSCStatusInvalidArgument);
}
}
- if (remoteAddress) {
+ if (remoteAddress != NULL) {
if ((remoteAddress->sa_len == 0) ||
(remoteAddress->sa_len > sizeof(struct sockaddr_storage))) {
_SCErrorSet(kSCStatusInvalidArgument);
}
targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
- if (!targetPrivate) {
+ if (targetPrivate == NULL) {
return NULL;
}
targetPrivate->type = reachabilityTypeAddressPair;
- if (localAddress) {
+ if (localAddress != NULL) {
targetPrivate->localAddress = CFAllocatorAllocate(NULL, localAddress->sa_len, 0);
bcopy(localAddress, targetPrivate->localAddress, localAddress->sa_len);
}
- if (remoteAddress) {
+ if (remoteAddress != NULL) {
targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, remoteAddress->sa_len, 0);
bcopy(remoteAddress, targetPrivate->remoteAddress, remoteAddress->sa_len);
}
SCNetworkReachabilityCreateWithName(CFAllocatorRef allocator,
const char *nodename)
{
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
SCNetworkReachabilityPrivateRef targetPrivate;
- if (!nodename) {
+ if (nodename == NULL) {
_SCErrorSet(kSCStatusInvalidArgument);
return NULL;
}
+ /* check if this "nodename" is really an IP[v6] address in disguise */
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ if (inet_aton(nodename, &sin.sin_addr) == 1) {
+ /* if IPv4 address */
+ return SCNetworkReachabilityCreateWithAddress(allocator, (struct sockaddr *)&sin);
+ }
+
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ if (inet_pton(AF_INET6, nodename, &sin6.sin6_addr) == 1) {
+ /* if IPv6 address */
+ char *p;
+
+ p = strchr(nodename, '%');
+ if (p != NULL) {
+ sin6.sin6_scope_id = if_nametoindex(p+1);
+ }
+
+ return SCNetworkReachabilityCreateWithAddress(allocator, (struct sockaddr *)&sin6);
+ }
+
targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
- if (!targetPrivate) {
+ if (targetPrivate == NULL) {
return NULL;
}
}
if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
- if (targetPrivate->resolvedAddress) {
+ if (targetPrivate->resolvedAddress != NULL) {
return CFRetain(targetPrivate->resolvedAddress);
} else {
/* if status is known but no resolved addresses to return */
static void
-__SCNetworkReachabilitySetResolvedAddress(SCNetworkReachabilityRef target,
- CFArrayRef addresses,
- int error_num)
-{
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-
- if (targetPrivate->resolvedAddress) {
- CFRelease(targetPrivate->resolvedAddress);
- }
- targetPrivate->resolvedAddress = addresses ? CFRetain(addresses) : NULL;
- targetPrivate->resolvedAddressError = error_num;
- return;
-}
-
-
-#ifdef CHECK_IPV6_REACHABILITY
-static void
-__SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinfo *res, void *context)
+__SCNetworkReachabilitySetResolvedAddress(int32_t status,
+ struct addrinfo *res,
+ SCNetworkReachabilityRef target)
{
- Boolean ok;
struct addrinfo *resP;
- SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- ok = (status == 0) && (res != NULL);
+ if (targetPrivate->resolvedAddress != NULL) {
+ CFRelease(targetPrivate->resolvedAddress);
+ targetPrivate->resolvedAddress = NULL;
+ }
- SCLog(_sc_debug, LOG_DEBUG,
- CFSTR("process async DNS complete%s"),
- ok ? "" : ", host not found");
+ if ((status == 0) && (res != NULL)) {
- if (ok) {
CFMutableArrayRef addresses;
addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
}
/* save the resolved address[es] */
- __SCNetworkReachabilitySetResolvedAddress(target, addresses, NETDB_SUCCESS);
- CFRelease(addresses);
+ targetPrivate->resolvedAddress = addresses;
+ targetPrivate->resolvedAddressError = NETDB_SUCCESS;
} else {
SCLog(_sc_debug, LOG_INFO, CFSTR("getaddrinfo() failed: %s"), gai_strerror(status));
/* save the error associated with the attempt to resolve the name */
- __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, status);
+ targetPrivate->resolvedAddress = CFRetain(kCFNull);
+ targetPrivate->resolvedAddressError = status;
}
if (res) freeaddrinfo(res);
- if (targetPrivate->rls) {
+ if (targetPrivate->rls != NULL) {
SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed"));
CFRunLoopSourceSignal(targetPrivate->rls);
- __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+ _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
}
return;
}
-#else /* CHECK_IPV6_REACHABILITY */
-static void
-__SCNetworkReachabilityCallbackSetResolvedAddress(struct hostent *h, int error, void *context)
-{
- SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context;
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-
- SCLog(_sc_debug, LOG_DEBUG,
- CFSTR("process async DNS complete%s"),
- (h == NULL) ? ", host not found" : "");
-
- if (h && h->h_length) {
- CFMutableArrayRef addresses;
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- struct sockaddr_storage ss;
- } addr;
- char **ha = h->h_addr_list;
-
- addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
- bzero(&addr, sizeof(addr));
-
- while (*ha) {
- CFDataRef newAddress;
-
- switch (h->h_length) {
- case sizeof(struct in_addr) :
- addr.sin.sin_family = AF_INET;
- addr.sin.sin_len = sizeof(struct sockaddr_in);
- bcopy(*ha, &addr.sin.sin_addr, h->h_length);
- break;
- case sizeof(struct in6_addr) :
- addr.sin6.sin6_family = AF_INET6;
- addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
- bcopy(*ha, &addr.sin6.sin6_addr, h->h_length);
- break;
- }
-
- newAddress = CFDataCreate(NULL, (void *)&addr, addr.sa.sa_len);
- CFArrayAppendValue(addresses, newAddress);
- CFRelease(newAddress);
-
- ha++;
- }
-
- /* save the resolved address[es] */
- __SCNetworkReachabilitySetResolvedAddress(target, addresses, NETDB_SUCCESS);
- CFRelease(addresses);
- } else {
- SCLog(_sc_debug, LOG_INFO, CFSTR("getipnodebyname() failed: %s"), __netdb_error(error));
- /* save the error associated with the attempt to resolve the name */
- __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error);
- }
- if (h) freehostent(h);
+static void
+__SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinfo *res, void *context)
+{
+ SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)context;
+ SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
- if (targetPrivate->rls) {
- SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed"));
- CFRunLoopSourceSignal(targetPrivate->rls);
- __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
- }
+ __log_query_time(((status == 0) && (res != NULL)), // if successful query
+ TRUE, // async
+ &targetPrivate->dnsQueryStart); // start time
+ __SCNetworkReachabilitySetResolvedAddress(status, res, target);
return;
}
-#endif /* CHECK_IPV6_REACHABILITY */
/*
}
-#ifdef CHECK_IPV6_REACHABILITY
static void
getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
{
getaddrinfo_async_handle_reply(msg);
if (port == targetPrivate->dnsPort) {
+ CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
CFRelease(targetPrivate->dnsRLS);
targetPrivate->dnsRLS = NULL;
CFRelease(targetPrivate->dnsPort);
return;
}
-#else /* CHECK_IPV6_REACHABILITY */
-static void
-getipnodebyname_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
+
+
+static Boolean
+check_resolver_reachability(SCDynamicStoreRef *storeP,
+ dns_resolver_t *resolver,
+ SCNetworkConnectionFlags *flags,
+ Boolean *haveDNS)
{
- SCNetworkReachabilityRef target = (SCNetworkReachabilityRef)info;
- SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
+ int i;
+ Boolean ok = TRUE;
- pthread_mutex_lock(&targetPrivate->lock);
+ *flags = kSCNetworkFlagsReachable;
+ *haveDNS = FALSE;
- getipnodebyname_async_handleReply(msg);
+ for (i = 0; i < resolver->n_nameserver; i++) {
+ struct sockaddr *address = resolver->nameserver[i];
+ SCNetworkConnectionFlags ns_flags = 0;
- if (port == targetPrivate->dnsPort) {
- CFRelease(targetPrivate->dnsRLS);
- targetPrivate->dnsRLS = NULL;
- CFRelease(targetPrivate->dnsPort);
- targetPrivate->dnsPort = NULL;
+ *haveDNS = TRUE;
+
+ if (address->sa_family != AF_INET) {
+ /*
+ * we need to skip non-IPv4 DNS server
+ * addresses (at least until [3510431] has
+ * been resolved).
+ */
+ continue;
+ }
+
+ ok = checkAddress(storeP, address, &ns_flags, NULL);
+ if (!ok) {
+ /* not today */
+ goto done;
+ }
+
+ if (rankReachability(ns_flags) < rankReachability(*flags)) {
+ /* return the worst case result */
+ *flags = ns_flags;
+ }
}
- pthread_mutex_unlock(&targetPrivate->lock);
+ done :
+
+ return ok;
+}
+
+
+static Boolean
+check_matching_resolvers(SCDynamicStoreRef *storeP,
+ dns_config_t *dns_config,
+ const char *fqdn,
+ SCNetworkConnectionFlags *flags,
+ Boolean *haveDNS)
+{
+ int i;
+ Boolean matched = FALSE;
+ const char *name = fqdn;
+
+ while (!matched && (name != NULL)) {
+ int len;
+
+ /*
+ * check if the provided name (or sub-component)
+ * matches one of our resolver configurations.
+ */
+ len = strlen(name);
+ for (i = 0; i < dns_config->n_resolver; i++) {
+ char *domain;
+ dns_resolver_t *resolver;
+
+ resolver = dns_config->resolver[i];
+ domain = resolver->domain;
+ if (domain != NULL && (len == strlen(domain))) {
+ if (strcasecmp(name, domain) == 0) {
+ Boolean ok;
+
+ /*
+ * if name matches domain
+ */
+ matched = TRUE;
+ ok = check_resolver_reachability(storeP, resolver, flags, haveDNS);
+ if (!ok) {
+ /* not today */
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ if (!matched) {
+ /*
+ * we have not found a matching resolver, try
+ * a less qualified domain
+ */
+ name = strchr(name, '.');
+ if ((name != NULL) && (*name != '\0')) {
+ name++;
+ } else {
+ name = NULL;
+ }
+ }
+ }
+
+ return matched;
+}
+
+
+static dns_configuration_t *
+dns_configuration_retain()
+{
+ pthread_mutex_lock(&dns_lock);
+
+ if ((dns_configuration != NULL) && dns_token_valid) {
+ int check = 0;
+ uint32_t status;
+
+ /*
+ * check if the global [DNS] configuration snapshot needs
+ * to be updated
+ */
+ status = notify_check(dns_token, &check);
+ if (status != NOTIFY_STATUS_OK) {
+ SCLog(TRUE, LOG_INFO, CFSTR("notify_check() failed, status=%lu"), status);
+ }
+
+ if ((status != NOTIFY_STATUS_OK) || (check != 0)) {
+ /*
+ * if the snapshot needs to be refreshed
+ */
+ if (dns_configuration->refs == 0) {
+ dns_configuration_free(dns_configuration->config);
+ CFAllocatorDeallocate(NULL, dns_configuration);
+ }
+ dns_configuration = NULL;
+ }
+ }
+
+ if (dns_configuration == NULL) {
+ dns_config_t *new_config;
+ new_config = dns_configuration_copy();
+ if (new_config != NULL) {
+ dns_configuration = CFAllocatorAllocate(NULL, sizeof(dns_configuration_t), 0);
+ dns_configuration->config = new_config;
+ dns_configuration->refs = 0;
+ }
+ }
+
+ if (dns_configuration != NULL) {
+ dns_configuration->refs++;
+ }
+
+ pthread_mutex_unlock(&dns_lock);
+ return dns_configuration;
+}
+
+
+static void
+dns_configuration_release(dns_configuration_t *config)
+{
+ pthread_mutex_lock(&dns_lock);
+
+ config->refs--;
+ if (config->refs == 0) {
+ if ((dns_configuration != config)) {
+ dns_configuration_free(config->config);
+ CFAllocatorDeallocate(NULL, config);
+ }
+ }
+
+ pthread_mutex_unlock(&dns_lock);
return;
}
-#endif /* CHECK_IPV6_REACHABILITY */
static Boolean
-checkResolverReachability(SCDynamicStoreRef *storeP,
- SCNetworkConnectionFlags *flags,
- Boolean *haveDNS)
+dns_configuration_watch()
{
- int i;
- Boolean ok = TRUE;
+ int dns_check = 0;
+ const char *dns_key;
+ Boolean ok = FALSE;
+ uint32_t status;
+
+ pthread_mutex_lock(&dns_lock);
+
+ dns_key = dns_configuration_notify_key();
+ if (dns_key == NULL) {
+ SCLog(TRUE, LOG_INFO, CFSTR("dns_configuration_notify_key() failed"));
+ goto done;
+ }
+
+ status = notify_register_check(dns_key, &dns_token);
+ if (status == NOTIFY_STATUS_OK) {
+ dns_token_valid = TRUE;
+ } else {
+ SCLog(TRUE, LOG_INFO, CFSTR("notify_register_check() failed, status=%lu"), status);
+ goto done;
+ }
+
+ status = notify_check(dns_token, &dns_check);
+ if (status != NOTIFY_STATUS_OK) {
+ SCLog(TRUE, LOG_INFO, CFSTR("notify_check() failed, status=%lu"), status);
+ (void)notify_cancel(dns_token);
+ dns_token_valid = FALSE;
+ goto done;
+ }
+
+ ok = TRUE;
+
+ done :
+
+ pthread_mutex_unlock(&dns_lock);
+ return ok;
+}
+
+
+static void
+dns_configuration_unwatch()
+{
+ pthread_mutex_lock(&dns_lock);
+
+ (void)notify_cancel(dns_token);
+ dns_token_valid = FALSE;
+
+ if ((dns_configuration != NULL) && (dns_configuration->refs == 0)) {
+ dns_configuration_free(dns_configuration->config);
+ CFAllocatorDeallocate(NULL, dns_configuration);
+ dns_configuration = NULL;
+ }
+
+ pthread_mutex_unlock(&dns_lock);
+ return;
+}
+
+
+Boolean
+_SC_checkResolverReachability(SCDynamicStoreRef *storeP,
+ SCNetworkConnectionFlags *flags,
+ Boolean *haveDNS,
+ const char * nodename)
+{
+ dns_resolver_t *default_resolver;
+ dns_configuration_t *dns;
+ Boolean found = FALSE;
+ char *fqdn = (char *)nodename;
+ int i;
+ Boolean isFQDN = FALSE;
+ uint32_t len;
+ Boolean ok = TRUE;
/*
* We first assume that all of the configured DNS servers
*flags = kSCNetworkFlagsReachable;
*haveDNS = FALSE;
- if (needDNS) {
- if (hn_store) {
- /* if we are actively watching at least one host */
- needDNS = FALSE;
- }
- res_init();
+ len = strlen(fqdn);
+ if (len == 0) {
+ // if no nodename, return not reachable
+ *flags = 0;
+ return ok;
}
- for (i = 0; i < _res.nscount; i++) {
- SCNetworkConnectionFlags ns_flags = 0;
+ dns = dns_configuration_retain();
+ if (dns == NULL) {
+ // if error
+ goto done;
+ }
- if (_res.nsaddr_list[i].sin_addr.s_addr == 0) {
- continue;
- }
+ if (dns->config->n_resolver == 0) {
+ // if no resolver configuration
+ goto done;
+ }
- *haveDNS = TRUE;
+ *flags = kSCNetworkFlagsReachable;
- if (_res.nsaddr_list[i].sin_len == 0) {
- _res.nsaddr_list[i].sin_len = sizeof(_res.nsaddr_list[i]);
- }
+ if (fqdn[len - 1] == '.') {
+ isFQDN = TRUE;
- ok = checkAddress(storeP, (struct sockaddr *)&_res.nsaddr_list[i], &ns_flags, NULL);
- if (!ok) {
- /* not today */
- break;
+ // trim trailing '.''s
+ while ((len > 0) && (fqdn[len-1] == '.')) {
+ if (fqdn == nodename) {
+ fqdn = strdup(nodename);
+ }
+ fqdn[--len] = '\0';
}
- if (rankReachability(ns_flags) < rankReachability(*flags)) {
- /* return the worst case result */
- *flags = ns_flags;
+ }
+
+ default_resolver = dns->config->resolver[0];
+
+ /*
+ * try the provided name
+ */
+ found = check_matching_resolvers(storeP, dns->config, fqdn, flags, haveDNS);
+ if (!found && !isFQDN && (dns->config->n_resolver > 1)) {
+ /*
+ * FQDN not specified, try w/search or default domain(s) too
+ */
+ if (default_resolver->n_search > 0) {
+ for (i = 0; !found && (i < default_resolver->n_search); i++) {
+ int ret;
+ char *search_fqdn = NULL;
+
+ ret = asprintf(&search_fqdn, "%s.%s", fqdn, default_resolver->search[i]);
+ if (ret == -1) {
+ continue;
+ }
+
+ // try the provided name with the search domain appended
+ found = check_matching_resolvers(storeP, dns->config, search_fqdn, flags, haveDNS);
+ free(search_fqdn);
+ }
+ } else if (default_resolver->domain != NULL) {
+ char *dp;
+ int domain_parts = 1;
+
+ for (dp = default_resolver->domain; *dp != '\0'; dp++) {
+ if (*dp == '.') {
+ domain_parts++;
+ }
+ }
+
+ dp = default_resolver->domain;
+ for (i = LOCALDOMAINPARTS; !found && (i <= domain_parts); i++) {
+ int ret;
+ char *search_fqdn = NULL;
+
+ ret = asprintf(&search_fqdn, "%s.%s", fqdn, dp);
+ if (ret == -1) {
+ continue;
+ }
+
+ // try the provided name with the [default] domain appended
+ found = check_matching_resolvers(storeP, dns->config, search_fqdn, flags, haveDNS);
+ free(search_fqdn);
+
+ // move to the next component of the [default] domain
+ dp = strchr(dp, '.') + 1;
+ }
}
}
- if (!*haveDNS) {
- /* if no DNS server addresses */
- *flags = 0;
+ if (!found) {
+ /*
+ * check the reachability of the default resolver
+ */
+ ok = check_resolver_reachability(storeP, default_resolver, flags, haveDNS);
+ }
+
+ if (fqdn != nodename) free(fqdn);
+
+ done :
+
+ if (dns != NULL) {
+ dns_configuration_release(dns);
}
return ok;
startAsyncDNSQuery(SCNetworkReachabilityRef target) {
CFMachPortContext context = { 0, (void *)target, CFRetain, CFRelease, CFCopyDescription };
int error;
-#ifdef CHECK_IPV6_REACHABILITY
struct addrinfo hints;
-#endif /* CHECK_IPV6_REACHABILITY */
CFIndex i;
CFIndex n;
mach_port_t port;
SCNetworkReachabilityPrivateRef targetPrivate = (SCNetworkReachabilityPrivateRef)target;
-#ifdef CHECK_IPV6_REACHABILITY
+ (void) gettimeofday(&targetPrivate->dnsQueryStart, NULL);
+
bzero(&hints, sizeof(hints));
hints.ai_flags = AI_ADDRCONFIG;
+#ifdef AI_PARALLEL
+ hints.ai_flags |= AI_PARALLEL;
+#endif /* AI_PARALLEL */
error = getaddrinfo_async_start(&port,
targetPrivate->name,
(void *)target);
if (error != 0) {
/* save the error associated with the attempt to resolve the name */
- __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error);
+ __SCNetworkReachabilityCallbackSetResolvedAddress(error, NULL, (void *)target);
return FALSE;
}
getaddrinfo_async_handleCFReply,
&context,
NULL);
-#else /* CHECK_IPV6_REACHABILITY */
- port = getipnodebyname_async_start(targetPrivate->name,
- AF_INET,
- 0,
- &error,
- __SCNetworkReachabilityCallbackSetResolvedAddress,
- (void *)target);
- if (port == MACH_PORT_NULL) {
- /* save the error associated with the attempt to resolve the name */
- __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error);
- return FALSE;
- }
-
- targetPrivate->dnsPort = CFMachPortCreateWithPort(NULL,
- port,
- getipnodebyname_async_handleCFReply,
- &context,
- NULL);
-#endif /* CHECK_IPV6_REACHABILITY */
-
targetPrivate->dnsRLS = CFMachPortCreateRunLoopSource(NULL, targetPrivate->dnsPort, 0);
n = CFArrayGetCount(targetPrivate->rlList);
Boolean ok = TRUE;
*flags = 0;
- if (if_index) {
+ if (if_index != NULL) {
*if_index = 0;
}
/*
* Check "local" address
*/
- if (targetPrivate->localAddress) {
- /*
- * Check if 0.0.0.0
- */
- if (isAddressZero(targetPrivate->localAddress, &my_flags)) {
- goto checkRemote;
- }
-
+ if (targetPrivate->localAddress != NULL) {
/*
* Check "local" address
*/
}
}
- checkRemote :
-
/*
* Check "remote" address
*/
- if (targetPrivate->remoteAddress) {
+ if (targetPrivate->remoteAddress != NULL) {
/*
* in cases where we have "local" and "remote" addresses
* we need to re-initialize the to-be-returned flags.
my_flags = 0;
my_index = 0;
- /*
- * Check if 0.0.0.0
- */
- if (isAddressZero(targetPrivate->remoteAddress, &my_flags)) {
- break;
- }
-
/*
* Check "remote" address
*/
}
case reachabilityTypeName : {
+ struct timeval dnsQueryStart;
int error;
-#ifndef CHECK_IPV6_REACHABILITY
- struct hostent *h;
-#endif /* CHECK_IPV6_REACHABILITY */
- Boolean haveDNS = FALSE;
-#ifdef CHECK_IPV6_REACHABILITY
struct addrinfo hints;
-#endif /* CHECK_IPV6_REACHABILITY */
SCNetworkConnectionFlags ns_flags;
-#ifdef CHECK_IPV6_REACHABILITY
struct addrinfo *res;
-#endif /* CHECK_IPV6_REACHABILITY */
addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
- if (addresses || (error != NETDB_SUCCESS)) {
+ if ((addresses != NULL) || (error != NETDB_SUCCESS)) {
/* if resolved or an error had been detected */
goto checkResolvedAddress;
}
/* check the reachability of the DNS servers */
- ok = checkResolverReachability(storeP, &ns_flags, &haveDNS);\
+ ok = _SC_checkResolverReachability(storeP,
+ &ns_flags,
+ &targetPrivate->haveDNS,
+ targetPrivate->name);
if (!ok) {
/* if we could not get DNS server info */
goto error;
* flags based on the availability of configured (but not
* active) services.
*/
- if (!checkAddressZero(storeP, &my_flags, &my_index)) {
+ if (!checkAddress(storeP, NULL, &my_flags, &my_index)) {
goto error;
}
- if (async && targetPrivate->rls) {
+ if (async && (targetPrivate->rls != NULL)) {
/*
- * return HOST_NOT_FOUND, set flags appropriately,
+ * return "host not found", set flags appropriately,
* and schedule notification.
*/
-#ifdef CHECK_IPV6_REACHABILITY
__SCNetworkReachabilityCallbackSetResolvedAddress(EAI_NODATA,
NULL,
(void *)target);
-#else /* CHECK_IPV6_REACHABILITY */
- __SCNetworkReachabilityCallbackSetResolvedAddress(NULL,
- HOST_NOT_FOUND,
- (void *)target);
-#endif /* CHECK_IPV6_REACHABILITY */
-
my_flags |= (targetPrivate->flags & kSCNetworkFlagsFirstResolvePending);
SCLog(_sc_debug, LOG_INFO, CFSTR("no DNS servers are reachable"));
CFRunLoopSourceSignal(targetPrivate->rls);
- __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+ _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
}
break;
}
* OK, all of the DNS name servers are available. Let's
* resolve the nodename into an address.
*/
-#ifdef CHECK_IPV6_REACHABILITY
+ if (_sc_debug) {
+ (void) gettimeofday(&dnsQueryStart, NULL);
+ }
+
bzero(&hints, sizeof(hints));
hints.ai_flags = AI_ADDRCONFIG;
+#ifdef AI_PARALLEL
+ hints.ai_flags |= AI_PARALLEL;
+#endif /* AI_PARALLEL */
error = getaddrinfo(targetPrivate->name, NULL, &hints, &res);
- __SCNetworkReachabilityCallbackSetResolvedAddress(error, res, (void *)target);
-#else /* CHECK_IPV6_REACHABILITY */
- h = getipnodebyname(targetPrivate->name, AF_INET, 0, &error);
- __SCNetworkReachabilityCallbackSetResolvedAddress(h, error, (void *)target);
-#endif /* CHECK_IPV6_REACHABILITY */
+
+ __log_query_time(((error == 0) && (res != NULL)),// if successful query
+ FALSE, // sync
+ &dnsQueryStart); // start time
+
+ __SCNetworkReachabilitySetResolvedAddress(error, res, target);
addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
struct sockaddr *sa;
sa = (struct sockaddr *)CFDataGetBytePtr(CFArrayGetValueAtIndex(addresses, i));
+
ok = checkAddress(storeP, sa, &ns_flags, &ns_if_index);
if (!ok) {
goto error; /* not today */
}
}
} else {
- if ((error == HOST_NOT_FOUND) && !haveDNS) {
+ if ((error == EAI_NODATA) && !targetPrivate->haveDNS) {
/*
* No DNS servers are defined. Set flags based on
* the availability of configured (but not active)
* services.
*/
- ok = checkAddressZero(storeP, &my_flags, &my_index);
+ ok = checkAddress(storeP, NULL, &my_flags, &my_index);
if (!ok) {
goto error; /* not today */
}
}
*flags = my_flags;
- if (if_index) {
+ if (if_index != NULL) {
*if_index = my_index;
}
error :
- if (addresses) CFRelease(addresses);
+ if (addresses != NULL) CFRelease(addresses);
return ok;
}
return FALSE;
}
- if (targetPrivate->rlList) {
- /* if being watched, return current (OK, last known) status */
+ if (targetPrivate->rlList != NULL) {
+ // if being watched, return the last known (and what should be current) status
*flags = targetPrivate->flags & ~kSCNetworkFlagsFirstResolvePending;
return TRUE;
}
ok = __SCNetworkReachabilityGetFlags(&store, target, flags, NULL, FALSE);
*flags &= ~kSCNetworkFlagsFirstResolvePending;
- if (store) CFRelease(store);
+ if (store != NULL) CFRelease(store);
return ok;
}
static void
__SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store)
{
+ CFStringRef dns_key;
CFStringRef key;
CFMutableArrayRef keys;
CFStringRef pattern;
keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- /*
- * Setup:/Network/Global/IPv4 (for the ServiceOrder)
- */
+ // Setup:/Network/Global/IPv4 (for the ServiceOrder)
key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
kSCDynamicStoreDomainSetup,
kSCEntNetIPv4);
CFArrayAppendValue(keys, key);
CFRelease(key);
- /*
- * State:/Network/Global/DNS
- */
- key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
- kSCDynamicStoreDomainState,
- kSCEntNetDNS);
+ // Notify:com.apple.SystemConfiguration.dns_configuration
+ dns_key = CFStringCreateWithCString(NULL,
+ dns_configuration_notify_key(),
+ kCFStringEncodingASCII);
+ key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), dns_key);
+ CFRelease(dns_key);
CFArrayAppendValue(keys, key);
CFRelease(key);
- /*
- * State:/Network/Global/IPv4
- */
+ // State:/Network/Global/IPv4 (default route)
key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
kSCDynamicStoreDomainState,
kSCEntNetIPv4);
CFArrayAppendValue(keys, key);
CFRelease(key);
- /* Setup: per-service IPv4 info */
+ // Setup: per-service IPv4 info
pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
kSCDynamicStoreDomainSetup,
kSCCompAnyRegex,
CFArrayAppendValue(patterns, pattern);
CFRelease(pattern);
- /* Setup: per-service Interface info */
+ // Setup: per-service Interface info
pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
kSCDynamicStoreDomainSetup,
kSCCompAnyRegex,
CFArrayAppendValue(patterns, pattern);
CFRelease(pattern);
- /* Setup: per-service PPP info */
+ // Setup: per-service PPP info (for kSCPropNetPPPDialOnDemand)
pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
kSCDynamicStoreDomainSetup,
kSCCompAnyRegex,
CFArrayAppendValue(patterns, pattern);
CFRelease(pattern);
- /* State: per-service IPv4 info */
- pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
- kSCDynamicStoreDomainState,
- kSCCompAnyRegex,
- kSCEntNetIPv4);
- CFArrayAppendValue(patterns, pattern);
- CFRelease(pattern);
-
- /* State: per-interface IPv4 info */
+ // State: per-interface IPv4 info
pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
kSCCompAnyRegex,
CFArrayAppendValue(patterns, pattern);
CFRelease(pattern);
- /* State: per-interface IPv6 info */
+ // State: per-interface IPv6 info
pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
kSCCompAnyRegex,
CFArrayRef changedKeys,
void *info)
{
- Boolean dnsChanged = FALSE;
+ Boolean dnsConfigChanged = FALSE;
+ CFStringRef dnsKey;
CFIndex i;
CFStringRef key;
CFIndex nTargets;
const void * targets_q[N_QUICK];
- const void ** targets = targets_q;
+ const void ** targets = targets_q;
pthread_mutex_lock(&hn_lock);
SCLog(_sc_debug, LOG_INFO, CFSTR("process configuration change"));
- key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
- kSCDynamicStoreDomainState,
- kSCEntNetDNS);
+ dnsKey = CFStringCreateWithCString(NULL,
+ dns_configuration_notify_key(),
+ kCFStringEncodingASCII);
+ key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), dnsKey);
+ CFRelease(dnsKey);
if (CFArrayContainsValue(changedKeys,
CFRangeMake(0, CFArrayGetCount(changedKeys)),
key)) {
- dnsChanged = TRUE; /* the DNS server(s) have changed */
- needDNS = TRUE; /* ... and we need to res_init() on the next query */
- }
- CFRelease(key);
+ dnsConfigChanged = TRUE; /* the DNS server(s) have changed */
- if (!dnsChanged) {
- /*
- * if the DNS configuration didn't change we still need to
- * check that the DNS servers are accessible.
- */
- Boolean haveDNS = FALSE;
- SCNetworkConnectionFlags ns_flags;
- Boolean ok;
-
- /* check the reachability of the DNS servers */
- ok = checkResolverReachability(&store, &ns_flags, &haveDNS);\
- if (!ok || (rankReachability(ns_flags) < 2)) {
- /* if DNS servers are not reachable */
- dnsChanged = TRUE;
- }
}
+ CFRelease(key);
- SCLog(_sc_debug && dnsChanged, LOG_INFO, CFSTR(" DNS changed"));
+ SCLog(_sc_debug && dnsConfigChanged, LOG_INFO, CFSTR(" DNS configuration changed"));
if (nTargets > (CFIndex)(sizeof(targets_q) / sizeof(CFTypeRef)))
targets = CFAllocatorAllocate(NULL, nTargets * sizeof(CFTypeRef), 0);
pthread_mutex_lock(&targetPrivate->lock);
- if (dnsChanged) {
- if (targetPrivate->dnsPort) {
- /* cancel the outstanding DNS query */
-#ifdef CHECK_IPV6_REACHABILITY
- lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#else /* CHECK_IPV6_REACHABILITY */
- getipnodebyname_async_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#endif /* CHECK_IPV6_REACHABILITY */
- CFRelease(targetPrivate->dnsRLS);
- targetPrivate->dnsRLS = NULL;
- CFRelease(targetPrivate->dnsPort);
- targetPrivate->dnsPort = NULL;
+ if (targetPrivate->type == reachabilityTypeName) {
+ Boolean dnsChanged = dnsConfigChanged;
+
+ if (!dnsChanged) {
+ /*
+ * if the DNS configuration didn't change we still need to
+ * check that the DNS servers are accessible.
+ */
+ SCNetworkConnectionFlags ns_flags;
+ Boolean ok;
+
+ /* check the reachability of the DNS servers */
+ ok = _SC_checkResolverReachability(&store,
+ &ns_flags,
+ &targetPrivate->haveDNS,
+ targetPrivate->name);
+ if (!ok || (rankReachability(ns_flags) < 2)) {
+ /* if DNS servers are not reachable */
+ dnsChanged = TRUE;
+ }
}
- /* schedule request to resolve the name again */
- __SCNetworkReachabilitySetResolvedAddress(target, NULL, NETDB_SUCCESS);
+ if (dnsChanged) {
+ if (targetPrivate->dnsPort) {
+ /* cancel the outstanding DNS query */
+ lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
+ CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
+ CFRelease(targetPrivate->dnsRLS);
+ targetPrivate->dnsRLS = NULL;
+ CFRelease(targetPrivate->dnsPort);
+ targetPrivate->dnsPort = NULL;
+ }
+
+ /* schedule request to resolve the name again */
+ if (targetPrivate->resolvedAddress != NULL) {
+ CFRelease(targetPrivate->resolvedAddress);
+ targetPrivate->resolvedAddress = NULL;
+ }
+ targetPrivate->resolvedAddress = NULL;
+ targetPrivate->resolvedAddressError = NETDB_SUCCESS;
+ }
}
CFRunLoopSourceSignal(targetPrivate->rls);
- __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+ _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
pthread_mutex_unlock(&targetPrivate->lock);
}
}
-static Boolean
-__isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
- CFIndex i;
- CFIndex n = CFArrayGetCount(rlList);
-
- for (i = 0; i < n; i += 3) {
- if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- continue;
- }
- if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
- continue;
- }
- if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
- continue;
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-static void
-__schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
- CFArrayAppendValue(rlList, obj);
- CFArrayAppendValue(rlList, runLoop);
- CFArrayAppendValue(rlList, runLoopMode);
-
- return;
-}
-
-
-static Boolean
-__unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
-{
- CFIndex i = 0;
- Boolean found = FALSE;
- CFIndex n = CFArrayGetCount(rlList);
-
- while (i < n) {
- if (obj && !CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
- i += 3;
- continue;
- }
- if (runLoop && !CFEqual(runLoop, CFArrayGetValueAtIndex(rlList, i+1))) {
- i += 3;
- continue;
- }
- if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
- i += 3;
- continue;
- }
-
- found = TRUE;
-
- CFArrayRemoveValueAtIndex(rlList, i + 2);
- CFArrayRemoveValueAtIndex(rlList, i + 1);
- CFArrayRemoveValueAtIndex(rlList, i);
-
- if (!all) {
- return found;
- }
-
- n -= 3;
- }
-
- return found;
-}
-
-
static void
rlsPerform(void *info)
{
/* update reachability, notify if status changed */
ok = __SCNetworkReachabilityGetFlags(&store, target, &flags, &if_index, TRUE);
- if (store) CFRelease(store);
+ if (store != NULL) CFRelease(store);
if (!ok) {
/* if reachability status not available */
flags = 0;
if ((targetPrivate->flags == flags) && (targetPrivate->if_index == if_index)) {
/* if reachability flags and interface have not changed */
pthread_mutex_unlock(&targetPrivate->lock);
- SCLog(_sc_debug, LOG_DEBUG, CFSTR("flags/interface match"));
+ SCLog(_sc_debug, LOG_DEBUG,
+ CFSTR("flags/interface match (now %8.8x/%hu)"),
+ flags, if_index);
return;
+ } else {
+ SCLog(_sc_debug, LOG_DEBUG,
+ CFSTR("flags/interface have changed (was %8.8x/%hu, now %8.8x/%hu)"),
+ targetPrivate->flags, targetPrivate->if_index,
+ flags, if_index);
}
/* update flags / interface */
/* callout */
rlsFunction = targetPrivate->rlsFunction;
- if (NULL != targetPrivate->rlsContext.retain) {
- context_info = (void *)targetPrivate->rlsContext.retain(targetPrivate->rlsContext.info);
+ if (targetPrivate->rlsContext.retain != NULL) {
+ context_info = (void *)(*targetPrivate->rlsContext.retain)(targetPrivate->rlsContext.info);
context_release = targetPrivate->rlsContext.release;
} else {
context_info = targetPrivate->rlsContext.info;
pthread_mutex_unlock(&targetPrivate->lock);
- if (rlsFunction) {
- SCLog(_sc_debug, LOG_DEBUG, CFSTR("flags/interface have changed"));
+ if (rlsFunction != NULL) {
(*rlsFunction)(target, flags, context_info);
}
- if (context_release) {
- context_release(context_info);
+ if (context_release != NULL) {
+ (*context_release)(context_info);
}
return;
pthread_mutex_lock(&targetPrivate->lock);
- if (targetPrivate->rlsContext.release) {
+ if (targetPrivate->rlsContext.release != NULL) {
/* let go of the current context */
- targetPrivate->rlsContext.release(targetPrivate->rlsContext.info);
+ (*targetPrivate->rlsContext.release)(targetPrivate->rlsContext.info);
}
targetPrivate->rlsFunction = callout;
targetPrivate->rlsContext.copyDescription = NULL;
if (context) {
bcopy(context, &targetPrivate->rlsContext, sizeof(SCNetworkReachabilityContext));
- if (context->retain) {
- targetPrivate->rlsContext.info = (void *)context->retain(context->info);
+ if (context->retain != NULL) {
+ targetPrivate->rlsContext.info = (void *)(*context->retain)(context->info);
}
}
pthread_mutex_lock(&hn_lock);
pthread_mutex_lock(&targetPrivate->lock);
- if (!hn_store) {
+ if (hn_store == NULL) {
/*
- * if we are not monitoring any hosts
+ * if we are not monitoring any hosts, start watching
*/
+ if (!dns_configuration_watch()) {
+ // if error
+ _SCErrorSet(kSCStatusFailed);
+ goto done;
+ }
+
hn_store = SCDynamicStoreCreate(NULL,
CFSTR("SCNetworkReachability"),
__SCNetworkReachabilityReachabilityHandleChanges,
NULL);
- if (!hn_store) {
+ if (hn_store == NULL) {
SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
goto done;
}
hn_targets = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
}
- if (!targetPrivate->rls) {
+ if (targetPrivate->rls == NULL) {
CFRunLoopSourceContext context = { 0 // version
, (void *)target // info
, CFRetain // retain
init = TRUE;
}
- if (!__isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
+ if (!_SC_isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
/*
* if we do not already have host notifications scheduled with
* this runLoop / runLoopMode
*/
CFRunLoopAddSource(runLoop, targetPrivate->rls, runLoopMode);
- if (targetPrivate->dnsRLS) {
+ if (targetPrivate->dnsRLS != NULL) {
/* if we have an active async DNS query too */
CFRunLoopAddSource(runLoop, targetPrivate->dnsRLS, runLoopMode);
}
}
- __schedule(target, runLoop, runLoopMode, targetPrivate->rlList);
+ _SC_schedule(target, runLoop, runLoopMode, targetPrivate->rlList);
/* schedule the SCNetworkReachability run loop source */
- if (!__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
+ if (!_SC_isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
/*
* if we do not already have SC notifications scheduled with
* this runLoop / runLoopMode
CFRunLoopAddSource(runLoop, hn_storeRLS, runLoopMode);
}
- __schedule(target, runLoop, runLoopMode, hn_rlList);
+ _SC_schedule(target, runLoop, runLoopMode, hn_rlList);
CFSetAddValue(hn_targets, target);
if (init) {
targetPrivate->flags = flags;
targetPrivate->if_index = if_index;
CFRunLoopSourceSignal(targetPrivate->rls);
- __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+ _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
} else {
/* if reachability status not available, async lookup started */
targetPrivate->flags = 0;
targetPrivate->if_index = 0;
}
- if (store) CFRelease(store);
+ if (store != NULL) CFRelease(store);
}
ok = TRUE;
pthread_mutex_lock(&hn_lock);
pthread_mutex_lock(&targetPrivate->lock);
- if (!targetPrivate->rls) {
+ if (targetPrivate->rls == NULL) {
/* if not currently scheduled */
goto done;
}
- if (!__unschedule(NULL, runLoop, runLoopMode, targetPrivate->rlList, FALSE)) {
+ if (!_SC_unschedule(NULL, runLoop, runLoopMode, targetPrivate->rlList, FALSE)) {
/* if not currently scheduled */
goto done;
}
n = CFArrayGetCount(targetPrivate->rlList);
- if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
+ if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
/*
* if this host is no longer scheduled for this runLoop / runLoopMode
*/
CFRunLoopRemoveSource(runLoop, targetPrivate->rls, runLoopMode);
- if (targetPrivate->dnsRLS) {
+ if (targetPrivate->dnsRLS != NULL) {
/* if we have an active async DNS query too */
CFRunLoopRemoveSource(runLoop, targetPrivate->dnsRLS, runLoopMode);
}
/*
* if this host is no longer scheduled
*/
- CFRelease(targetPrivate->rls); /* cleanup SCNetworkReachability resources */
+ CFRunLoopSourceInvalidate(targetPrivate->rls); /* cleanup SCNetworkReachability resources */
+ CFRelease(targetPrivate->rls);
targetPrivate->rls = NULL;
CFRelease(targetPrivate->rlList);
targetPrivate->rlList = NULL;
- CFSetRemoveValue(hn_targets, target); /* cleanup notification resources */
+ CFSetRemoveValue(hn_targets, target); /* cleanup notification resources */
if (targetPrivate->dnsPort) {
/* if we have an active async DNS query too */
-#ifdef CHECK_IPV6_REACHABILITY
lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#else /* CHECK_IPV6_REACHABILITY */
- getipnodebyname_async_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#endif /* CHECK_IPV6_REACHABILITY */
+ CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
CFRelease(targetPrivate->dnsRLS);
targetPrivate->dnsRLS = NULL;
CFRelease(targetPrivate->dnsPort);
}
}
- (void)__unschedule(target, runLoop, runLoopMode, hn_rlList, FALSE);
+ (void)_SC_unschedule(target, runLoop, runLoopMode, hn_rlList, FALSE);
n = CFArrayGetCount(hn_rlList);
- if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
+ if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
/*
* if we no longer have any addresses scheduled for
* this runLoop / runLoopMode
* if we are no longer monitoring any addresses
*/
CFRelease(hn_targets);
+ hn_targets = NULL;
CFRelease(hn_rlList);
+ hn_rlList = NULL;
+ CFRunLoopSourceInvalidate(hn_storeRLS);
CFRelease(hn_storeRLS);
+ hn_storeRLS = NULL;
CFRelease(hn_store);
hn_store = NULL;
/*
* until we start monitoring again, ensure that
- * all subsequent reachability-by-name checks
- * call res_init()
+ * any resources associated with tracking the
+ * DNS configuration have been released.
*/
- needDNS = TRUE;
+ dns_configuration_unwatch();
}
}
/*!
@header SCNetworkReachability
- The SCNetworkReachabilityXXX() APIs allow an application to determine the status
- of a system's current network configuration and the reachability
- of a target host. In addition, the reachability can be monitored
- with a notification being provided when/if the status has changed.
-
- The term "reachable" reflects whether a data packet, sent by
- an application into the network stack, can be sent to the
- the target host/address. Please note that there is no
- guarantee that the data packet will actually be received by
- the host.
+ @discussion The SCNetworkReachability API allows an application to
+ determine the status of a system's current network
+ configuration and the reachability of a target host.
+ In addition, reachability can be monitored with notifications
+ that are sent when the status has changed.
+
+ "Reachability" reflects whether a data packet, sent by
+ an application into the network stack, can leave the local
+ computer.
+ Note that reachability does <i>not</i> guarantee that the data
+ packet will actually be received by the host.
*/
/*!
@typedef SCNetworkReachabilityRef
- @discussion This is the handle to a network address/name.
+ @discussion This is the handle to a network address or name.
*/
-typedef const struct __SCNetworkReachability * SCNetworkReachabilityRef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef const struct __SCNetworkReachability * SCNetworkReachabilityRef;
/*!
@typedef SCNetworkReachabilityContext
+ Structure containing user-specified data and callbacks for SCNetworkReachability.
+ @field version The version number of the structure type being passed
+ in as a parameter to the SCDynamicStore creation function.
+ This structure is version 0.
+ @field info A C pointer to a user-specified block of data.
+ @field retain The callback used to add a retain for the info field.
+ If this parameter is not a pointer to a function of the correct
+ prototype, the behavior is undefined. The value may be NULL.
+ @field release The calllback used to remove a retain previously added
+ for the info field. If this parameter is not a pointer to a
+ function of the correct prototype, the behavior is undefined.
+ The value may be NULL.
+ @field copyDescription The callback used to provide a description of
+ the info field.
*/
typedef struct {
CFIndex version;
const void *(*retain)(const void *info);
void (*release)(const void *info);
CFStringRef (*copyDescription)(const void *info);
-} SCNetworkReachabilityContext AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+} SCNetworkReachabilityContext;
/*!
@typedef SCNetworkReachabilityCallBack
@discussion Type of the callback function used when the
- reachability of a network address/name changes.
- @param target The SCNetworkReachability reference being monitored for changes.
+ reachability of a network address or name changes.
+ @param target The SCNetworkReachability reference being monitored
+ for changes.
@param flags The new SCNetworkConnectionFlags representing the
reachability status of the network address/name.
- @param info ....
+ @param info A C pointer to a user-specified block of data.
*/
typedef void (*SCNetworkReachabilityCallBack) (
SCNetworkReachabilityRef target,
SCNetworkConnectionFlags flags,
void *info
- ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+ );
__BEGIN_DECLS
/*!
@function SCNetworkReachabilityCreateWithAddress
@discussion Creates a reference to the specified network
- address. This reference can later be used to monitor
- the reachability of the target host.
+ address. This reference can be used later to monitor the
+ reachability of the target host.
@param address The address of the desired host.
- @result A reference to the new immutable SCNetworkReachabilityRef.
+ @result Returns a reference to the new immutable SCNetworkReachabilityRef.
You must release the returned value.
*/
/*!
@function SCNetworkReachabilityCreateWithAddressPair
@discussion Creates a reference to the specified network
- address. This reference can later be used to monitor
- the reachability of the target host.
+ address. This reference can be used later to monitor the
+ reachability of the target host.
@param localAddress The local address associated with a network
connection. If NULL, only the remote address is of interest.
@param remoteAddress The remote address associated with a network
connection. If NULL, only the local address is of interest.
- @result A reference to the new immutable SCNetworkReachabilityRef.
+ @result Returns a reference to the new immutable SCNetworkReachabilityRef.
You must release the returned value.
*/
/*!
@function SCNetworkReachabilityCreateWithName
- @discussion Creates a reference to the specified network host/node
- name. This reference can later be used to monitor the
+ @discussion Creates a reference to the specified network host or node
+ name. This reference can be used later to monitor the
reachability of the target host.
- @param nodename The node name of the desired host. This name would
- be the same as that passed to gethostbyname() or getaddrinfo().
- @result A reference to the new immutable SCNetworkReachabilityRef.
+ @param nodename The node name of the desired host.
+ This name would be the same as that passed to the
+ gethostbyname(3) or getaddrinfo(3) functions.
+ @result Returns a reference to the new immutable SCNetworkReachabilityRef.
You must release the returned value.
*/
/*!
@function SCNetworkReachabilityGetTypeID
- Returns the type identifier of all SCNetworkReachability instances.
+ @discussion Returns the type identifier of all SCNetworkReachability
+ instances.
*/
CFTypeID
SCNetworkReachabilityGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
@function SCNetworkReachabilityGetFlags
@discussion Determines if the given target is reachable using the
current network configuration.
- @param target The network reference associated with the address/name
+ @param target The network reference associated with the address or name
to be checked for reachability.
@param flags A pointer to memory that will be filled with the
SCNetworkConnectionFlags detailing the reachability
of the specified target.
- @result TRUE if the network connection flags are valid; FALSE if the
- status could not be determined.
+ @result Returns TRUE if the network connection flags are valid;
+ FALSE if the status could not be determined.
*/
Boolean
SCNetworkReachabilityGetFlags (
@function SCNetworkReachabilitySetCallback
@discussion Assigns a client to a target, which receives callbacks
when the reachability of the target changes.
- @param target The network reference associated with the address/name
- to be checked for reachability.
- @param callout The function to be called when the reachability of
+ @param target The network reference associated with the address or
+ name to be checked for reachability.
+ @param callout The function to be called when the reachability of the
target changes. If NULL, the current client for the target
is removed.
@param context The SCNetworkReachabilityContext associated with
- the callout.
- @result TRUE if the notification client was successfully set.
+ the callout. The value may be NULL.
+ @result Returns TRUE if the notification client was successfully set.
*/
Boolean
SCNetworkReachabilitySetCallback (
/*!
@function SCNetworkReachabilityScheduleWithRunLoop
- @discussion Schedule the given target from the given run loop and mode.
- @param target The address/name which is set up for asynchronous mode. Must be non-NULL.
- @param runLoop A reference to a runloop on which the target should be scheduled. Must be non-NULL.
- @param runLoopMode The mode on which to schedule the target. Must be non-NULL.
+ @discussion Schedules the given target with the given run loop and mode.
+ @param target The address or name that is set up for asynchronous
+ notifications. Must be non-NULL.
+ @param runLoop A reference to a run loop on which the target should
+ be scheduled. Must be non-NULL.
+ @param runLoopMode The mode on which to schedule the target.
+ Must be non-NULL.
+ @result Returns TRUE if the target is scheduled successfully;
+ FALSE otherwise.
*/
Boolean
SCNetworkReachabilityScheduleWithRunLoop (
/*!
@function SCNetworkReachabilityUnscheduleFromRunLoop
- @discussion Unschedule the given target from the given run loop and mode.
- @param target The address/name which is set up for asynchronous mode. Must be non-NULL.
- @param runLoop A reference to a runloop on which the target should be scheduled. Must be non-NULL.
- @param runLoopMode The mode on which to schedule the target. Must be non-NULL.
+ @discussion Unschedules the given target from the given run loop
+ and mode.
+ @param target The address or name that is set up for asynchronous
+ notifications. Must be non-NULL.
+ @param runLoop A reference to a run loop from which the target
+ should be unscheduled. Must be non-NULL.
+ @param runLoopMode The mode on which to unschedule the target.
+ Must be non-NULL.
+ @result Returns TRUE if the target is unscheduled successfully;
+ FALSE otherwise.
*/
Boolean
SCNetworkReachabilityUnscheduleFromRunLoop (
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 13, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include <pthread.h>
+
+
+static CFStringRef __SCNetworkServiceCopyDescription (CFTypeRef cf);
+static void __SCNetworkServiceDeallocate (CFTypeRef cf);
+static Boolean __SCNetworkServiceEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static CFTypeID __kSCNetworkServiceTypeID = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkServiceClass = {
+ 0, // version
+ "SCNetworkService", // className
+ NULL, // init
+ NULL, // copy
+ __SCNetworkServiceDeallocate, // dealloc
+ __SCNetworkServiceEqual, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __SCNetworkServiceCopyDescription // copyDebugDesc
+};
+
+
+static pthread_once_t initialized = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkService(CFTypeRef obj)
+{
+ return (isA_CFType(obj, SCNetworkServiceGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkServiceCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkService %p [%p]> { "), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR("id=%@"), servicePrivate->serviceID);
+// CFStringAppendFormat(result, NULL, CFSTR(", prefs=%@"), servicePrivate->prefs);
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__SCNetworkServiceDeallocate(CFTypeRef cf)
+{
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf;
+
+ /* release resources */
+
+ CFRelease(servicePrivate->serviceID);
+ if (servicePrivate->interface != NULL) CFRelease(servicePrivate->interface);
+ CFRelease(servicePrivate->prefs);
+
+ return;
+}
+
+
+static Boolean
+__SCNetworkServiceEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+ SCNetworkServicePrivateRef s1 = (SCNetworkServicePrivateRef)cf1;
+ SCNetworkServicePrivateRef s2 = (SCNetworkServicePrivateRef)cf2;
+
+ if (s1 == s2)
+ return TRUE;
+
+ if (s1->prefs != s2->prefs)
+ return FALSE; // if not the same prefs
+
+ if (!CFEqual(s1->serviceID, s2->serviceID))
+ return FALSE; // if not the same service identifier
+
+ return TRUE;
+}
+
+
+static void
+__SCNetworkServiceInitialize(void)
+{
+ __kSCNetworkServiceTypeID = _CFRuntimeRegisterClass(&__SCNetworkServiceClass);
+ return;
+}
+
+
+__private_extern__ SCNetworkServicePrivateRef
+__SCNetworkServiceCreatePrivate(CFAllocatorRef allocator,
+ CFStringRef serviceID,
+ SCNetworkInterfaceRef interface,
+ SCPreferencesRef prefs)
+{
+ SCNetworkServicePrivateRef servicePrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&initialized, __SCNetworkServiceInitialize);
+
+ /* allocate target */
+ size = sizeof(SCNetworkServicePrivate) - sizeof(CFRuntimeBase);
+ servicePrivate = (SCNetworkServicePrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kSCNetworkServiceTypeID,
+ size,
+ NULL);
+ if (servicePrivate == NULL) {
+ return NULL;
+ }
+
+ servicePrivate->prefs = CFRetain(prefs);
+ servicePrivate->serviceID = CFStringCreateCopy(NULL, serviceID);
+ servicePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
+
+ return servicePrivate;
+}
+
+
+/* ---------- SCNetworkService APIs ---------- */
+
+
+#define N_QUICK 64
+
+
+Boolean
+SCNetworkServiceAddProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
+{
+ CFDictionaryRef entity;
+ CFDictionaryRef newEntity = NULL;
+ Boolean ok = FALSE;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ if (!__SCNetworkProtocolIsValidType(protocolType)) {
+ _SCErrorSet(kSCStatusInvalidArgument);
+ return FALSE;
+ }
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ protocolType); // entity
+
+ entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ if (entity != NULL) {
+ // if "protocol" already exists
+ _SCErrorSet(kSCStatusKeyExists);
+ goto done;
+ }
+
+ if (servicePrivate->interface != NULL) {
+ SCNetworkInterfaceRef childInterface;
+ CFStringRef childInterfaceType = NULL;
+ CFStringRef interfaceType;
+
+ interfaceType = SCNetworkInterfaceGetInterfaceType(servicePrivate->interface);
+ childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
+ if (childInterface != NULL) {
+ childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
+ }
+
+ newEntity = __copyProtocolTemplate(interfaceType, childInterfaceType, protocolType);
+ }
+
+ if (newEntity == NULL) {
+ newEntity = CFDictionaryCreate(NULL,
+ NULL,
+ NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
+ CFRelease(newEntity);
+
+ done :
+
+ CFRelease(path);
+ return ok;
+}
+
+
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkServiceCopyAll(SCPreferencesRef prefs)
+{
+ CFMutableArrayRef array;
+ CFIndex n;
+ CFStringRef path;
+ CFDictionaryRef services;
+
+ path = SCPreferencesPathKeyCreateNetworkServices(NULL);
+ services = SCPreferencesPathGetValue(prefs, path);
+ CFRelease(path);
+
+ if ((services != NULL) && !isA_CFDictionary(services)) {
+ return NULL;
+ }
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ n = (services != NULL) ? CFDictionaryGetCount(services) : 0;
+ if (n > 0) {
+ CFIndex i;
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+ const void * vals_q[N_QUICK];
+ const void ** vals = vals_q;
+
+ if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(services, keys, vals);
+ for (i = 0; i < n; i++) {
+ CFDictionaryRef entity;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ if (!isA_CFDictionary(vals[i])) {
+ SCLog(TRUE,
+ LOG_INFO,
+ CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
+ keys[i]);
+ continue;
+ }
+
+ entity = CFDictionaryGetValue(vals[i], kSCEntNetInterface);
+ if (!isA_CFDictionary(entity)) {
+ // if no "interface"
+ SCLog(TRUE,
+ LOG_INFO,
+ CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
+ kSCEntNetInterface,
+ keys[i]);
+ continue;
+ }
+
+ servicePrivate = __SCNetworkServiceCreatePrivate(NULL, keys[i], NULL, prefs);
+ CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
+ CFRelease(servicePrivate);
+ }
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ CFAllocatorDeallocate(NULL, vals);
+ }
+ }
+
+ return array;
+}
+
+
+/*
+ * build a list of all of a servives entity types that are associated
+ * with the services interface. The list will include :
+ *
+ * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
+ * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
+ * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
+ */
+static CFSetRef
+_copyInterfaceEntityTypes(CFDictionaryRef protocols)
+{
+ CFDictionaryRef interface;
+ CFMutableSetRef interface_entity_types;
+
+ interface_entity_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+ interface = CFDictionaryGetValue(protocols, kSCEntNetInterface);
+ if (isA_CFDictionary(interface)) {
+ CFStringRef entities[] = { kSCPropNetInterfaceType,
+ kSCPropNetInterfaceSubType,
+ kSCPropNetInterfaceHardware };
+ int i;
+
+ // include the "Interface" entity itself
+ CFSetAddValue(interface_entity_types, kSCEntNetInterface);
+
+ // include the entities associated with the interface
+ for (i = 0; i < sizeof(entities)/sizeof(entities[0]); i++) {
+ CFStringRef entity;
+
+ entity = CFDictionaryGetValue(interface, entities[i]);
+ if (isA_CFString(entity)) {
+ CFSetAddValue(interface_entity_types, entity);
+ }
+ }
+
+ /*
+ * and, because we've found some misguided network preference code
+ * developers leaving [PPP] entity dictionaries around even though
+ * they are unused and/or unneeded...
+ */
+ CFSetAddValue(interface_entity_types, kSCEntNetPPP);
+ }
+
+ return interface_entity_types;
+}
+
+
+SCNetworkServiceRef
+SCNetworkServiceCopy(SCPreferencesRef prefs, CFStringRef serviceID)
+{
+ CFDictionaryRef entity;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ serviceID, // service
+ kSCEntNetInterface); // entity
+ entity = SCPreferencesPathGetValue(prefs, path);
+ CFRelease(path);
+
+ if (!isA_CFDictionary(entity)) {
+ // a "service" must have an "interface"
+ _SCErrorSet(kSCStatusNoKey);
+ return NULL;
+ }
+
+ servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
+ return (SCNetworkServiceRef)servicePrivate;
+}
+
+
+SCNetworkProtocolRef
+SCNetworkServiceCopyProtocol(SCNetworkServiceRef service, CFStringRef protocolType)
+{
+ CFSetRef non_protocol_entities;
+ CFStringRef path;
+ CFDictionaryRef protocols;
+ SCNetworkProtocolPrivateRef protocolPrivate = NULL;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ if ((protocols != NULL) && !isA_CFDictionary(protocols)) {
+ // if corrupt prefs
+ _SCErrorSet(kSCStatusFailed);
+ return NULL;
+ }
+
+ non_protocol_entities = _copyInterfaceEntityTypes(protocols);
+ if (CFSetContainsValue(non_protocol_entities, protocolType)) {
+ // if the "protocolType" matches an interface entity type
+ _SCErrorSet(kSCStatusInvalidArgument);
+ goto done;
+ }
+
+ if (!CFDictionaryContainsKey(protocols, protocolType)) {
+ // if the "protocolType" entity does not exist
+ _SCErrorSet(kSCStatusNoKey);
+ goto done;
+ }
+
+ protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, protocolType, service);
+
+ done :
+
+ CFRelease(non_protocol_entities);
+
+ return (SCNetworkProtocolRef)protocolPrivate;
+}
+
+
+CFArrayRef /* of SCNetworkProtocolRef's */
+SCNetworkServiceCopyProtocols(SCNetworkServiceRef service)
+{
+ CFMutableArrayRef array;
+ CFIndex n;
+ CFSetRef non_protocol_entities;
+ CFStringRef path;
+ CFDictionaryRef protocols;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ if (!isA_CFDictionary(protocols)) {
+ return NULL;
+ }
+
+ non_protocol_entities = _copyInterfaceEntityTypes(protocols);
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ n = CFDictionaryGetCount(protocols);
+ if (n > 0) {
+ CFIndex i;
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+ const void * vals_q[N_QUICK];
+ const void ** vals = vals_q;
+
+ if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(protocols, keys, vals);
+ for (i = 0; i < n; i++) {
+ SCNetworkProtocolPrivateRef protocolPrivate;
+
+ if (!isA_CFDictionary(vals[i])) {
+ // if it's not a dictionary then it can't be a protocol entity
+ continue;
+ }
+
+ if (CFSetContainsValue(non_protocol_entities, keys[i])) {
+ // skip any non-protocol (interface) entities
+ continue;
+ }
+
+ protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, keys[i], service);
+ CFArrayAppendValue(array, (SCNetworkProtocolRef)protocolPrivate);
+
+ CFRelease(protocolPrivate);
+ }
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ CFAllocatorDeallocate(NULL, vals);
+ }
+ }
+
+ CFRelease(non_protocol_entities);
+
+ return array;
+}
+
+
+static Boolean
+__SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service,
+ SCNetworkInterfaceRef interface)
+{
+ CFMutableDictionaryRef entity;
+ SCNetworkInterfacePrivateRef interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ kSCEntNetInterface); // entity
+ entity = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (interfacePrivate->entity_type != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceType,
+ interfacePrivate->entity_type);
+ }
+ if (interfacePrivate->entity_subtype != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceSubType,
+ interfacePrivate->entity_subtype);
+ }
+ if (interfacePrivate->entity_device != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceDeviceName,
+ interfacePrivate->entity_device);
+ }
+ if (interfacePrivate->entity_hardware != NULL) {
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceHardware,
+ interfacePrivate->entity_hardware);
+ }
+ if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
+ interfacePrivate->supportsDeviceOnHold) {
+ int one = 1;
+ CFNumberRef num;
+
+ num = CFNumberCreate(NULL, kCFNumberIntType, &one);
+ CFDictionarySetValue(entity,
+ kSCPropNetInterfaceSupportsModemOnHold,
+ num);
+ CFRelease(num);
+ }
+ ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity);
+ CFRelease(entity);
+ CFRelease(path);
+
+ return ok;
+}
+
+
+SCNetworkServiceRef
+SCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface)
+{
+ CFArrayRef components;
+ CFArrayRef interface_config;
+ SCNetworkInterfaceRef newInterface;
+ CFStringRef path;
+ CFStringRef prefix;
+ CFStringRef serviceID;
+ SCNetworkServicePrivateRef servicePrivate;
+
+ // establish the service
+ prefix = SCPreferencesPathKeyCreateNetworkServices(NULL);
+ path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
+ CFRelease(prefix);
+ if (path == NULL) {
+ return NULL;
+ }
+
+ components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
+ CFRelease(path);
+
+ serviceID = CFArrayGetValueAtIndex(components, 2);
+ servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
+ CFRelease(components);
+
+ // duplicate the interface and associate the copy with the new service
+ newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL,
+ interface,
+ (SCNetworkServiceRef)servicePrivate);
+ servicePrivate->interface = newInterface;
+
+ // establish "default" configuration(s) for the interface
+ for (interface = newInterface;
+ interface != NULL;
+ interface = SCNetworkInterfaceGetInterface(interface)) {
+ SCNetworkInterfaceRef childInterface;
+ CFStringRef childInterfaceType = NULL;
+ CFDictionaryRef config;
+ CFStringRef interfaceType;
+
+ interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+ childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
+ if (childInterface != NULL) {
+ childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
+ }
+
+ config = __copyInterfaceTemplate(interfaceType, childInterfaceType);
+ if (config != NULL) {
+ (void) __SCNetworkInterfaceSetConfiguration(interface, config, TRUE);
+ CFRelease(config);
+ }
+ }
+
+ // add the interface [entity] to the service
+ (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef)servicePrivate,
+ servicePrivate->interface);
+
+ // push the [deep] interface configuration into into the service.
+ interface_config = __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate->interface);
+ __SCNetworkInterfaceSetDeepConfiguration(servicePrivate->interface, interface_config);
+
+ return (SCNetworkServiceRef)servicePrivate;
+}
+
+
+Boolean
+SCNetworkServiceGetEnabled(SCNetworkServiceRef service)
+{
+ Boolean enabled;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ enabled = __getPrefsEnabled(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ return enabled;
+}
+
+
+SCNetworkInterfaceRef
+SCNetworkServiceGetInterface(SCNetworkServiceRef service)
+{
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ if (servicePrivate->interface == NULL) {
+ CFDictionaryRef entity;
+ CFStringRef path;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ kSCEntNetInterface); // entity
+ entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ if (isA_CFDictionary(entity)) {
+ servicePrivate->interface = __SCNetworkInterfaceCreateWithEntity(NULL, entity, service);
+ }
+ }
+
+ return servicePrivate->interface;
+}
+
+
+CFStringRef
+SCNetworkServiceGetName(SCNetworkServiceRef service)
+{
+ CFDictionaryRef entity;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+ CFStringRef name = NULL;
+ CFStringRef path;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ if (isA_CFDictionary(entity)) {
+ name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
+ }
+
+ return isA_CFString(name) ? name : NULL;
+}
+
+
+CFStringRef
+SCNetworkServiceGetServiceID(SCNetworkServiceRef service)
+{
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ return servicePrivate->serviceID;
+}
+
+
+CFTypeID
+SCNetworkServiceGetTypeID(void)
+{
+ pthread_once(&initialized, __SCNetworkServiceInitialize); /* initialize runtime */
+ return __kSCNetworkServiceTypeID;
+}
+
+
+Boolean
+SCNetworkServiceRemove(SCNetworkServiceRef service)
+{
+ Boolean ok = FALSE;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+ CFArrayRef sets;
+ CFStringRef path;
+
+ // remove service from all sets
+
+ sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+ if (sets != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ n = CFArrayGetCount(sets);
+ for (i = 0; i < n; i++) {
+ SCNetworkSetRef set;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ ok = SCNetworkSetRemoveService(set, service);
+ if (!ok && (SCError() != kSCStatusNoKey)) {
+ break;
+ }
+ }
+ CFRelease(sets);
+ }
+
+ // remove service
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
+ CFRelease(path);
+
+ return ok;
+}
+
+
+Boolean
+SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
+{
+ CFDictionaryRef entity;
+ Boolean ok = FALSE;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ protocolType); // entity
+
+ entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ if (entity == NULL) {
+ // if "protocol" does not exist
+ _SCErrorSet(kSCStatusNoKey);
+ goto done;
+ }
+
+ ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
+
+ done :
+
+ CFRelease(path);
+ return ok;
+}
+
+
+Boolean
+SCNetworkServiceSetEnabled(SCNetworkServiceRef service, Boolean enabled)
+{
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
+ CFRelease(path);
+
+ return ok;
+}
+
+
+Boolean
+SCNetworkServiceSetName(SCNetworkServiceRef service, CFStringRef name)
+{
+ CFDictionaryRef entity;
+ Boolean ok = FALSE;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+
+#define PREVENT_DUPLICATE_SERVICE_NAMES
+#ifdef PREVENT_DUPLICATE_SERVICE_NAMES
+ if (isA_CFString(name)) {
+ CFArrayRef sets;
+
+ // ensure that each service is uniquely named within its sets
+
+ sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+ if (sets != NULL) {
+ CFIndex set_index;
+ CFIndex set_count;
+
+ set_count = CFArrayGetCount(sets);
+ for (set_index = 0; set_index < set_count; set_index++) {
+ CFIndex service_index;
+ Boolean isDup = FALSE;
+ Boolean isMember = FALSE;
+ CFIndex service_count;
+ CFArrayRef services;
+ SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, set_index);
+
+ services = SCNetworkSetCopyServices(set);
+
+ service_count = CFArrayGetCount(services);
+ for (service_index = 0; service_index < service_count; service_index++) {
+ CFStringRef otherID;
+ CFStringRef otherName;
+ SCNetworkServiceRef otherService;
+
+ otherService = CFArrayGetValueAtIndex(services, service_index);
+
+ otherID = SCNetworkServiceGetServiceID(otherService);
+ if (CFEqual(servicePrivate->serviceID, otherID)) {
+ // if the service is a member of this set
+ isMember = TRUE;
+ continue;
+ }
+
+ otherName = SCNetworkServiceGetName(otherService);
+ if ((otherName != NULL) && CFEqual(name, otherName)) {
+ isDup = TRUE;
+ continue;
+ }
+ }
+
+ CFRelease(services);
+
+ if (isMember && isDup) {
+ /*
+ * if this service is a member of the set and
+ * the "name" is not unique.
+ */
+ CFRelease(sets);
+ _SCErrorSet(kSCStatusKeyExists);
+ return FALSE;
+ }
+ }
+
+ CFRelease(sets);
+ }
+ }
+#endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
+
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+ if ((entity == NULL) && (name != NULL)) {
+ entity = CFDictionaryCreate(NULL,
+ NULL,
+ NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ if (isA_CFDictionary(entity)) {
+ CFMutableDictionaryRef newEntity;
+
+ newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+ if (isA_CFString(name)) {
+ CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
+ } else {
+ CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
+ }
+ ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
+ CFRelease(newEntity);
+ }
+ CFRelease(path);
+
+ return ok;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * May 13, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "SCNetworkConfiguration.h"
+#include "SCNetworkConfigurationInternal.h"
+
+#include <pthread.h>
+
+
+static CFStringRef __SCNetworkSetCopyDescription (CFTypeRef cf);
+static void __SCNetworkSetDeallocate (CFTypeRef cf);
+static Boolean __SCNetworkSetEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static CFTypeID __kSCNetworkSetTypeID = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkSetClass = {
+ 0, // version
+ "SCNetworkSet", // className
+ NULL, // init
+ NULL, // copy
+ __SCNetworkSetDeallocate, // dealloc
+ __SCNetworkSetEqual, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
+ __SCNetworkSetCopyDescription // copyDebugDesc
+};
+
+
+static pthread_once_t initialized = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkSet(CFTypeRef obj)
+{
+ return (isA_CFType(obj, SCNetworkSetGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkSetCopyDescription(CFTypeRef cf)
+{
+ CFAllocatorRef allocator = CFGetAllocator(cf);
+ CFMutableStringRef result;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)cf;
+
+ result = CFStringCreateMutable(allocator, 0);
+ CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkSet %p [%p]> { "), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR("id=%@"), setPrivate->setID);
+// CFStringAppendFormat(result, NULL, CFSTR(", prefs=%@"), setPrivate->prefs);
+ CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+ return result;
+}
+
+
+static void
+__SCNetworkSetDeallocate(CFTypeRef cf)
+{
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)cf;
+
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkSetDeallocate:"));
+
+ /* release resources */
+
+ CFRelease(setPrivate->setID);
+ CFRelease(setPrivate->prefs);
+
+ return;
+}
+
+
+static Boolean
+__SCNetworkSetEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+ SCNetworkSetPrivateRef s1 = (SCNetworkSetPrivateRef)cf1;
+ SCNetworkSetPrivateRef s2 = (SCNetworkSetPrivateRef)cf2;
+
+ if (s1 == s2)
+ return TRUE;
+
+ if (s1->prefs != s2->prefs)
+ return FALSE; // if not the same prefs
+
+ if (!CFEqual(s1->setID, s2->setID))
+ return FALSE; // if not the same set identifier
+
+ return TRUE;
+}
+
+
+static void
+__SCNetworkSetInitialize(void)
+{
+ __kSCNetworkSetTypeID = _CFRuntimeRegisterClass(&__SCNetworkSetClass);
+ return;
+}
+
+
+static SCNetworkSetPrivateRef
+__SCNetworkSetCreatePrivate(CFAllocatorRef allocator,
+ SCPreferencesRef prefs,
+ CFStringRef setID)
+{
+ SCNetworkSetPrivateRef setPrivate;
+ uint32_t size;
+
+ /* initialize runtime */
+ pthread_once(&initialized, __SCNetworkSetInitialize);
+
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkSetCreatePrivate:"));
+
+ /* allocate target */
+ size = sizeof(SCNetworkSetPrivate) - sizeof(CFRuntimeBase);
+ setPrivate = (SCNetworkSetPrivateRef)_CFRuntimeCreateInstance(allocator,
+ __kSCNetworkSetTypeID,
+ size,
+ NULL);
+ if (setPrivate == NULL) {
+ return NULL;
+ }
+
+ setPrivate->setID = CFStringCreateCopy(NULL, setID);
+ setPrivate->prefs = CFRetain(prefs);
+
+ return setPrivate;
+}
+
+
+#define N_QUICK 16
+
+
+Boolean
+SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service)
+{
+ SCNetworkInterfaceRef interface;
+ CFArrayRef interface_config = NULL;
+ CFStringRef link;
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+#define PREVENT_DUPLICATE_SETS
+#ifdef PREVENT_DUPLICATE_SETS
+ CFArrayRef sets;
+
+ // ensure that each service is only a member of ONE set
+
+ sets = SCNetworkSetCopyAll(setPrivate->prefs);
+ if (sets != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ n = CFArrayGetCount(sets);
+ for (i = 0; i < n; i++) {
+ Boolean found;
+ CFArrayRef services;
+ SCNetworkSetRef set;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ services = SCNetworkSetCopyServices(set);
+ found = CFArrayContainsValue(services,
+ CFRangeMake(0, CFArrayGetCount(services)),
+ service);
+ CFRelease(services);
+
+ if (found) {
+ CFRelease(sets);
+ _SCErrorSet(kSCStatusKeyExists);
+ return FALSE;
+ }
+ }
+ CFRelease(sets);
+ }
+#endif /* PREVENT_DUPLICATE_SETS */
+
+ // get the [deep] interface configuration settings
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface != NULL) {
+ interface_config = __SCNetworkInterfaceCopyDeepConfiguration(interface);
+ }
+
+ // create the link between "set" and the "service"
+ path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator
+ setPrivate->setID, // set
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ link = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ servicePrivate->serviceID, // service
+ NULL); // entity
+ ok = SCPreferencesPathSetLink(setPrivate->prefs, path, link);
+ CFRelease(path);
+ CFRelease(link);
+ if (!ok) {
+ return ok;
+ }
+
+ // push the [deep] interface configuration into all sets which contain this service.
+ if (interface != NULL) {
+ __SCNetworkInterfaceSetDeepConfiguration(interface, interface_config);
+ }
+
+ return ok;
+}
+
+
+SCNetworkSetRef
+SCNetworkSetCopy(SCPreferencesRef prefs, CFStringRef setID)
+{
+ CFDictionaryRef entity;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate;
+
+ path = SCPreferencesPathKeyCreateSet(NULL, setID);
+ entity = SCPreferencesPathGetValue(prefs, path);
+ CFRelease(path);
+
+ if (!isA_CFDictionary(entity)) {
+ _SCErrorSet(kSCStatusNoKey);
+ return NULL;
+ }
+
+ setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+ return (SCNetworkSetRef)setPrivate;
+}
+
+
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkSetCopyAll(SCPreferencesRef prefs)
+{
+ CFMutableArrayRef array;
+ CFIndex n;
+ CFStringRef path;
+ CFDictionaryRef sets;
+
+ path = SCPreferencesPathKeyCreateSets(NULL);
+ sets = SCPreferencesPathGetValue(prefs, path);
+ CFRelease(path);
+
+ if ((sets != NULL) && !isA_CFDictionary(sets)) {
+ return NULL;
+ }
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ n = (sets != NULL) ? CFDictionaryGetCount(sets) : 0;
+ if (n > 0) {
+ CFIndex i;
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+ const void * vals_q[N_QUICK];
+ const void ** vals = vals_q;
+
+ if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(sets, keys, vals);
+ for (i = 0; i < n; i++) {
+ SCNetworkSetPrivateRef setPrivate;
+
+ if (!isA_CFDictionary(vals[i])) {
+ SCLog(TRUE,
+ LOG_INFO,
+ CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"),
+ keys[i]);
+ continue;
+ }
+
+ setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, keys[i]);
+ CFArrayAppendValue(array, (SCNetworkSetRef)setPrivate);
+ CFRelease(setPrivate);
+ }
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ CFAllocatorDeallocate(NULL, vals);
+ }
+ }
+
+ return array;
+}
+
+
+SCNetworkSetRef
+SCNetworkSetCopyCurrent(SCPreferencesRef prefs)
+{
+ CFArrayRef components;
+ CFStringRef currentID;
+ SCNetworkSetPrivateRef setPrivate = NULL;
+
+ currentID = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+ if (!isA_CFString(currentID)) {
+ return NULL;
+ }
+
+ components = CFStringCreateArrayBySeparatingStrings(NULL, currentID, CFSTR("/"));
+ if (CFArrayGetCount(components) == 3) {
+ CFStringRef setID;
+ CFStringRef path;
+
+ setID = CFArrayGetValueAtIndex(components, 2);
+ path = SCPreferencesPathKeyCreateSet(NULL, setID);
+ if (CFEqual(path, currentID)) {
+ setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+ } else {
+ SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkSetCopyCurrent(): preferences are non-conformant"));
+ }
+ CFRelease(path);
+ }
+ CFRelease(components);
+
+ return (SCNetworkSetRef)setPrivate;
+}
+
+
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkSetCopyServices(SCNetworkSetRef set)
+{
+ CFMutableArrayRef array;
+ CFDictionaryRef dict;
+ CFIndex n;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ path = SCPreferencesPathKeyCreateSetNetworkService(NULL, setPrivate->setID, NULL);
+ dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
+ CFRelease(path);
+ if ((dict != NULL) && !isA_CFDictionary(dict)) {
+ return NULL;
+ }
+
+ array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ n = (dict != NULL) ? CFDictionaryGetCount(dict) : 0;
+ if (n > 0) {
+ CFIndex i;
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+
+ if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(dict, keys, NULL);
+ for (i = 0; i < n; i++) {
+ CFArrayRef components;
+ CFStringRef link;
+
+ path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,
+ setPrivate->setID,
+ (CFStringRef)keys[i],
+ NULL);
+ link = SCPreferencesPathGetLink(setPrivate->prefs, path);
+ CFRelease(path);
+ if (link == NULL) {
+ SCLog(TRUE,
+ LOG_INFO,
+ CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"),
+ keys[i],
+ setPrivate->setID);
+ continue; // if the service is not a link
+ }
+
+ components = CFStringCreateArrayBySeparatingStrings(NULL, link, CFSTR("/"));
+ if (CFArrayGetCount(components) == 3) {
+ CFStringRef serviceID;
+
+ serviceID = CFArrayGetValueAtIndex(components, 2);
+ path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
+ serviceID, // service
+ NULL); // entity
+ if (CFEqual(path, link)) {
+ SCNetworkServicePrivateRef servicePrivate;
+
+ servicePrivate = __SCNetworkServiceCreatePrivate(NULL,
+ serviceID,
+ NULL,
+ setPrivate->prefs);
+ CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
+ CFRelease(servicePrivate);
+ }
+ CFRelease(path);
+ }
+ CFRelease(components);
+ }
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ }
+ }
+
+ return array;
+}
+
+
+SCNetworkSetRef
+SCNetworkSetCreate(SCPreferencesRef prefs)
+{
+ CFArrayRef components;
+ CFStringRef path;
+ CFStringRef prefix;
+ CFStringRef setID;
+ SCNetworkSetPrivateRef setPrivate;
+
+ prefix = SCPreferencesPathKeyCreateSets(NULL);
+ path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
+ CFRelease(prefix);
+ if (path == NULL) {
+ return NULL;
+ }
+
+ components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
+ CFRelease(path);
+
+ setID = CFArrayGetValueAtIndex(components, 2);
+ setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+ CFRelease(components);
+
+ return (SCNetworkSetRef)setPrivate;
+}
+
+
+CFStringRef
+SCNetworkSetGetSetID(SCNetworkSetRef set)
+{
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ return setPrivate->setID;
+}
+
+
+CFStringRef
+SCNetworkSetGetName(SCNetworkSetRef set)
+{
+ CFDictionaryRef entity;
+ CFStringRef name = NULL;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+ entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
+ CFRelease(path);
+
+ if (isA_CFDictionary(entity)) {
+ name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
+ }
+
+ return isA_CFString(name) ? name : NULL;
+}
+
+
+CFArrayRef /* of serviceID CFStringRef's */
+SCNetworkSetGetServiceOrder(SCNetworkSetRef set)
+{
+ CFDictionaryRef dict;
+ CFStringRef path;
+ CFArrayRef serviceOrder;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4);
+ if (path == NULL) {
+ return NULL;
+ }
+
+ dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
+ CFRelease(path);
+ if (!isA_CFDictionary(dict)) {
+ return NULL;
+ }
+
+ serviceOrder = CFDictionaryGetValue(dict, kSCPropNetServiceOrder);
+ serviceOrder = isA_CFArray(serviceOrder);
+
+ return serviceOrder;
+}
+
+
+CFTypeID
+SCNetworkSetGetTypeID(void)
+{
+ pthread_once(&initialized, __SCNetworkSetInitialize); /* initialize runtime */
+ return __kSCNetworkSetTypeID;
+}
+
+
+Boolean
+SCNetworkSetRemove(SCNetworkSetRef set)
+{
+ CFStringRef currentPath;
+ Boolean ok = FALSE;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ currentPath = SCPreferencesGetValue(setPrivate->prefs, kSCPrefCurrentSet);
+ path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+ if (!isA_CFString(currentPath) || !CFEqual(currentPath, path)) {
+ ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path);
+ }
+ CFRelease(path);
+
+ return ok;
+}
+
+
+Boolean
+SCNetworkSetRemoveService(SCNetworkSetRef set, SCNetworkServiceRef service)
+{
+ SCNetworkInterfaceRef interface;
+ CFArrayRef interface_config = NULL;
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ // get the [deep] interface configuration settings
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface != NULL) {
+ interface_config = __SCNetworkInterfaceCopyDeepConfiguration(interface);
+ if (interface_config != NULL) {
+ // remove the interface configuration from all sets which contain this service.
+ __SCNetworkInterfaceSetDeepConfiguration(interface, NULL);
+ }
+ }
+
+ // remove the link between "set" and the "service"
+ path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,
+ setPrivate->setID,
+ servicePrivate->serviceID,
+ NULL);
+ ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path);
+ CFRelease(path);
+ if (!ok) {
+ goto done;
+ }
+
+ // push the [deep] interface configuration [back] into all sets which contain the service.
+ if (interface_config != NULL) {
+ __SCNetworkInterfaceSetDeepConfiguration(interface, interface_config);
+ }
+
+ done :
+
+ if (interface_config != NULL) CFRelease(interface_config);
+ return ok;
+}
+
+
+Boolean
+SCNetworkSetSetCurrent(SCNetworkSetRef set)
+{
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+ ok = SCPreferencesSetValue(setPrivate->prefs, kSCPrefCurrentSet, path);
+ CFRelease(path);
+ return ok;
+}
+
+
+Boolean
+SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
+{
+ CFDictionaryRef entity;
+ Boolean ok = FALSE;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+#define PREVENT_DUPLICATE_SET_NAMES
+#ifdef PREVENT_DUPLICATE_SET_NAMES
+ if (isA_CFString(name)) {
+ CFArrayRef sets;
+
+ // ensure that each set is uniquely named
+
+ sets = SCNetworkSetCopyAll(setPrivate->prefs);
+ if (sets != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ n = CFArrayGetCount(sets);
+ for (i = 0; i < n; i++) {
+ CFStringRef otherID;
+ CFStringRef otherName;
+ SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, i);
+
+ otherID = SCNetworkSetGetSetID(set);
+ if (CFEqual(setPrivate->setID, otherID)) {
+ continue; // skip current set
+ }
+
+ otherName = SCNetworkSetGetName(set);
+ if ((otherName != NULL) && CFEqual(name, otherName)) {
+ // if "name" not unique
+ CFRelease(sets);
+ _SCErrorSet(kSCStatusKeyExists);
+ return FALSE;
+ }
+ }
+ CFRelease(sets);
+ }
+ }
+#endif /* PREVENT_DUPLICATE_SET_NAMES */
+
+ // update the "name"
+
+ path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+ entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
+ if ((entity == NULL) && (name != NULL)) {
+ entity = CFDictionaryCreate(NULL,
+ NULL,
+ NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ if (isA_CFDictionary(entity)) {
+ CFMutableDictionaryRef newEntity;
+
+ newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+ if (isA_CFString(name)) {
+ CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
+ } else {
+ CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
+ }
+ ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newEntity);
+ CFRelease(newEntity);
+ }
+ CFRelease(path);
+
+ return ok;
+}
+
+
+Boolean
+SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
+{
+ CFDictionaryRef dict;
+ CFMutableDictionaryRef newDict;
+ Boolean ok;
+ CFStringRef path;
+ SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
+
+ path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4);
+ if (path == NULL) {
+ return FALSE;
+ }
+
+ dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
+ if (dict != NULL) {
+ newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+ } else {
+ newDict = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+
+ CFDictionarySetValue(newDict, kSCPropNetServiceOrder, newOrder);
+ ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newDict);
+ CFRelease(newDict);
+ CFRelease(path);
+
+ return ok;
+}
/*
- * Copyright(c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright(c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
CFDataRef
-SCPreferencesGetSignature(SCPreferencesRef session)
+SCPreferencesGetSignature(SCPreferencesRef prefs)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesGetSignature:"));
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return NULL;
+ }
+
+ __SCPreferencesAccess(prefs);
- sessionPrivate->accessed = TRUE;
- return sessionPrivate->signature;
+ return prefsPrivate->signature;
}
CFStringRef user,
int keyType)
{
- CFStringRef key = NULL;
- char *pathStr;
- char *typeStr;
+ CFStringRef keyStr;
+ char *path;
+ CFStringRef pathStr;
+ CFStringRef storeKey;
- pathStr = __SCPreferencesPath(allocator, prefsID, perUser, user, TRUE);
- if (pathStr == NULL) {
- return NULL;
- }
-
- /* create notification key */
switch (keyType) {
case kSCPreferencesKeyLock :
- typeStr = "lock";
+ keyStr = CFSTR("lock");
break;
case kSCPreferencesKeyCommit :
- typeStr = "commit";
+ keyStr = CFSTR("commit");
break;
case kSCPreferencesKeyApply :
- typeStr = "apply";
+ keyStr = CFSTR("apply");
break;
default :
- typeStr = "?";
+ return NULL;
}
- key = CFStringCreateWithFormat(allocator,
- NULL,
- CFSTR("%@%s:%s"),
- kSCDynamicStoreDomainPrefs,
- typeStr,
- pathStr);
+ path = __SCPreferencesPath(allocator, prefsID, perUser, user, TRUE);
+ if (path == NULL) {
+ return NULL;
+ }
- CFAllocatorDeallocate(NULL, pathStr);
- return key;
+ pathStr = CFStringCreateWithCStringNoCopy(allocator,
+ path,
+ kCFStringEncodingASCII,
+ kCFAllocatorNull);
+
+ storeKey = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("%@%@:%@"),
+ kSCDynamicStoreDomainPrefs,
+ keyStr,
+ pathStr);
+
+ CFRelease(pathStr);
+ CFAllocatorDeallocate(NULL, path);
+ return storeKey;
}
#include "SCPreferencesInternal.h"
Boolean
-SCPreferencesAddValue(SCPreferencesRef session, CFStringRef key, CFPropertyListRef value)
+SCPreferencesAddValue(SCPreferencesRef prefs, CFStringRef key, CFPropertyListRef value)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesAddValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
}
- sessionPrivate->accessed = TRUE;
+ __SCPreferencesAccess(prefs);
- if (CFDictionaryContainsKey(sessionPrivate->prefs, key)) {
+ if (CFDictionaryContainsKey(prefsPrivate->prefs, key)) {
_SCErrorSet(kSCStatusKeyExists);
return FALSE;
}
- CFDictionaryAddValue(sessionPrivate->prefs, key, value);
- sessionPrivate->changed = TRUE;
+ CFDictionaryAddValue(prefsPrivate->prefs, key, value);
+ prefsPrivate->changed = TRUE;
return TRUE;
}
#include "SCPreferencesInternal.h"
Boolean
-SCPreferencesApplyChanges(SCPreferencesRef session)
+SCPreferencesApplyChanges(SCPreferencesRef prefs)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
Boolean wasLocked;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges:"));
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
/*
* Determine if the we have exclusive access to the preferences
* and acquire the lock if necessary.
*/
- wasLocked = sessionPrivate->locked;
+ wasLocked = prefsPrivate->locked;
if (!wasLocked) {
- if (!SCPreferencesLock(session, TRUE)) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" SCPreferencesLock() failed"));
+ if (!SCPreferencesLock(prefs, TRUE)) {
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges SCPreferencesLock() failed"));
return FALSE;
}
}
- if (!sessionPrivate->isRoot) {
+ if (!prefsPrivate->isRoot) {
/* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
goto perUser;
}
- /* if necessary, create the session "apply" key */
- if (sessionPrivate->sessionKeyApply == NULL) {
- sessionPrivate->sessionKeyApply = _SCPNotificationKey(NULL,
- sessionPrivate->prefsID,
- sessionPrivate->perUser,
- sessionPrivate->user,
- kSCPreferencesKeyApply);
- }
-
/* post notification */
- if (!SCDynamicStoreNotifyValue(sessionPrivate->session,
- sessionPrivate->sessionKeyApply)) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" SCDynamicStoreNotifyValue() failed"));
+ if (!SCDynamicStoreNotifyValue(prefsPrivate->session,
+ prefsPrivate->sessionKeyApply)) {
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges SCDynamicStoreNotifyValue() failed"));
_SCErrorSet(kSCStatusFailed);
goto error;
}
perUser :
- if (!wasLocked) (void) SCPreferencesUnlock(session);
+ if (!wasLocked) (void) SCPreferencesUnlock(prefs);
return TRUE;
error :
- if (!wasLocked) (void) SCPreferencesUnlock(session);
+ if (!wasLocked) (void) SCPreferencesUnlock(prefs);
return FALSE;
}
Boolean
-SCPreferencesCommitChanges(SCPreferencesRef session)
+SCPreferencesCommitChanges(SCPreferencesRef prefs)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
Boolean wasLocked;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCommitChanges:"));
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
/*
* Determine if the we have exclusive access to the preferences
* and acquire the lock if necessary.
*/
- wasLocked = sessionPrivate->locked;
+ wasLocked = prefsPrivate->locked;
if (!wasLocked) {
- if (!SCPreferencesLock(session, TRUE)) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR(" SCPreferencesLock() failed"));
+ if (!SCPreferencesLock(prefs, TRUE)) {
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges SCPreferencesLock() failed"));
return FALSE;
}
}
/*
* if necessary, apply changes
*/
- if (sessionPrivate->changed) {
+ if (prefsPrivate->changed) {
int fd;
CFDataRef newPrefs;
char * path;
struct stat statBuf;
char * thePath;
- if (stat(sessionPrivate->path, &statBuf) == -1) {
+ if (stat(prefsPrivate->path, &statBuf) == -1) {
if (errno == ENOENT) {
bzero(&statBuf, sizeof(statBuf));
statBuf.st_mode = 0644;
statBuf.st_uid = geteuid();
statBuf.st_gid = getegid();
} else {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges stat() failed: %s"), strerror(errno));
goto error;
}
}
/* create the (new) preferences file */
- path = sessionPrivate->newPath ? sessionPrivate->newPath : sessionPrivate->path;
+ path = prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path;
pathLen = strlen(path) + sizeof("-new");
thePath = CFAllocatorAllocate(NULL, pathLen, 0);
snprintf(thePath, pathLen, "%s-new", path);
fd = open(thePath, O_WRONLY|O_CREAT, statBuf.st_mode);
if (fd == -1) {
if ((errno == ENOENT) &&
- ((sessionPrivate->prefsID == NULL) || !CFStringHasPrefix(sessionPrivate->prefsID, CFSTR("/")))) {
+ ((prefsPrivate->prefsID == NULL) || !CFStringHasPrefix(prefsPrivate->prefsID, CFSTR("/")))) {
char *ch;
ch = strrchr(thePath, '/');
}
}
}
- SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPCommit open() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges open() failed: %s"), strerror(errno));
CFAllocatorDeallocate(NULL, thePath);
goto error;
}
(void) fchmod(fd, statBuf.st_mode);
/* write the new preferences */
- newPrefs = CFPropertyListCreateXMLData(NULL, sessionPrivate->prefs);
+ newPrefs = CFPropertyListCreateXMLData(NULL, prefsPrivate->prefs);
if (!newPrefs) {
_SCErrorSet(kSCStatusFailed);
- SCLog(_sc_verbose, LOG_ERR, CFSTR(" CFPropertyListCreateXMLData() failed"));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges CFPropertyListCreateXMLData() failed"));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR(" prefs = %s"), path);
CFAllocatorDeallocate(NULL, thePath);
(void) close(fd);
goto error;
}
if (writen(fd, (void *)CFDataGetBytePtr(newPrefs), CFDataGetLength(newPrefs)) == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_ERR, CFSTR("write() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges write() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR(" path = %s"), thePath);
+ (void) unlink(thePath);
+ CFAllocatorDeallocate(NULL, thePath);
+ (void) close(fd);
+ CFRelease(newPrefs);
+ goto error;
+ }
+ if (fsync(fd) == -1) {
+ _SCErrorSet(errno);
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges fsync() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR(" path = %s"), thePath);
(void) unlink(thePath);
CFAllocatorDeallocate(NULL, thePath);
(void) close(fd);
CFRelease(newPrefs);
goto error;
}
- (void) close(fd);
+ if (close(fd) == -1) {
+ _SCErrorSet(errno);
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges close() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR(" path = %s"), thePath);
+ (void) unlink(thePath);
+ CFAllocatorDeallocate(NULL, thePath);
+ CFRelease(newPrefs);
+ goto error;
+ }
CFRelease(newPrefs);
/* rename new->old */
if (rename(thePath, path) == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_ERR, CFSTR("rename() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges rename() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR(" path = %s --> %s"), thePath, path);
CFAllocatorDeallocate(NULL, thePath);
goto error;
}
CFAllocatorDeallocate(NULL, thePath);
- if (sessionPrivate->newPath) {
+ if (prefsPrivate->newPath) {
/* prefs file saved in "new" directory */
- (void) unlink(sessionPrivate->path);
- (void) symlink(sessionPrivate->newPath, sessionPrivate->path);
- CFAllocatorDeallocate(NULL, sessionPrivate->path);
- sessionPrivate->path = path;
- sessionPrivate->newPath = NULL;
+ (void) unlink(prefsPrivate->path);
+ (void) symlink(prefsPrivate->newPath, prefsPrivate->path);
+ CFAllocatorDeallocate(NULL, prefsPrivate->path);
+ prefsPrivate->path = path;
+ prefsPrivate->newPath = NULL;
}
/* update signature */
if (stat(path, &statBuf) == -1) {
_SCErrorSet(errno);
- SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges stat() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_ERR, CFSTR(" path = %s"), thePath);
goto error;
}
- CFRelease(sessionPrivate->signature);
- sessionPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
+ CFRelease(prefsPrivate->signature);
+ prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
}
- if (!sessionPrivate->isRoot) {
+ if (!prefsPrivate->isRoot) {
/* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
goto perUser;
}
- /* if necessary, create the session "commit" key */
- if (sessionPrivate->sessionKeyCommit == NULL) {
- sessionPrivate->sessionKeyCommit = _SCPNotificationKey(NULL,
- sessionPrivate->prefsID,
- sessionPrivate->perUser,
- sessionPrivate->user,
- kSCPreferencesKeyCommit);
- }
-
/* post notification */
- if (!SCDynamicStoreNotifyValue(sessionPrivate->session,
- sessionPrivate->sessionKeyCommit)) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR(" SCDynamicStoreNotifyValue() failed"));
+ if (!SCDynamicStoreNotifyValue(prefsPrivate->session,
+ prefsPrivate->sessionKeyCommit)) {
+ SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges SCDynamicStoreNotifyValue() failed"));
_SCErrorSet(kSCStatusFailed);
goto error;
}
perUser :
- if (!wasLocked) (void) SCPreferencesUnlock(session);
- sessionPrivate->changed = FALSE;
+ if (!wasLocked) (void) SCPreferencesUnlock(prefs);
+ prefsPrivate->changed = FALSE;
return TRUE;
error :
- if (!wasLocked) (void) SCPreferencesUnlock(session);
+ if (!wasLocked) (void) SCPreferencesUnlock(prefs);
return FALSE;
}
#include "SCPreferencesInternal.h"
CFPropertyListRef
-SCPreferencesGetValue(SCPreferencesRef session, CFStringRef key)
+SCPreferencesGetValue(SCPreferencesRef prefs, CFStringRef key)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
CFPropertyListRef value;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesGetValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return NULL;
}
- sessionPrivate->accessed = TRUE;
- value = CFDictionaryGetValue(sessionPrivate->prefs, key);
- if (!value) {
+ __SCPreferencesAccess(prefs);
+
+ value = CFDictionaryGetValue(prefsPrivate->prefs, key);
+ if (value == NULL) {
_SCErrorSet(kSCStatusNoKey);
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), value);
return value;
}
#include "SCPreferencesInternal.h"
CFArrayRef
-SCPreferencesCopyKeyList(SCPreferencesRef session)
+SCPreferencesCopyKeyList(SCPreferencesRef prefs)
{
- CFAllocatorRef allocator = CFGetAllocator(session);
+ CFAllocatorRef allocator = CFGetAllocator(prefs);
CFArrayRef keys;
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
CFIndex prefsCnt;
const void ** prefsKeys;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCopyKeyList:"));
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return NULL;
+ }
+
+ __SCPreferencesAccess(prefs);
- prefsCnt = CFDictionaryGetCount(sessionPrivate->prefs);
+ prefsCnt = CFDictionaryGetCount(prefsPrivate->prefs);
if (prefsCnt > 0) {
prefsKeys = CFAllocatorAllocate(allocator, prefsCnt * sizeof(CFStringRef), 0);
- CFDictionaryGetKeysAndValues(sessionPrivate->prefs, prefsKeys, NULL);
+ CFDictionaryGetKeysAndValues(prefsPrivate->prefs, prefsKeys, NULL);
keys = CFArrayCreate(allocator, prefsKeys, prefsCnt, &kCFTypeArrayCallBacks);
CFAllocatorDeallocate(allocator, prefsKeys);
} else {
keys = CFArrayCreate(allocator, NULL, 0, &kCFTypeArrayCallBacks);
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" keys = %@"), keys);
-
- sessionPrivate->accessed = TRUE;
return keys;
}
#include <fcntl.h>
#include <unistd.h>
+#include <pthread.h>
#include <sys/errno.h>
Boolean
-SCPreferencesLock(SCPreferencesRef session, Boolean wait)
+SCPreferencesLock(SCPreferencesRef prefs, Boolean wait)
{
- CFAllocatorRef allocator = CFGetAllocator(session);
+ CFAllocatorRef allocator = CFGetAllocator(prefs);
CFArrayRef changes;
- CFDataRef currentSignature = NULL;
Boolean haveLock = FALSE;
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
- struct stat statBuf;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
CFDateRef value = NULL;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesLock:"));
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
- if (sessionPrivate->locked) {
+ if (prefsPrivate->locked) {
/* sorry, you already have the lock */
_SCErrorSet(kSCStatusLocked);
return FALSE;
}
- if (!sessionPrivate->isRoot) {
- if (!sessionPrivate->perUser) {
+ if (!prefsPrivate->isRoot) {
+ if (!prefsPrivate->perUser) {
_SCErrorSet(kSCStatusAccessError);
return FALSE;
} else {
}
}
- if (sessionPrivate->session == NULL) {
- /* open a session */
- sessionPrivate->session = SCDynamicStoreCreate(allocator,
- CFSTR("SCPreferencesLock"),
- NULL,
- NULL);
- if (!sessionPrivate->session) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
- return FALSE;
- }
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ if (prefsPrivate->session == NULL) {
+ __SCPreferencesAddSession(prefs);
}
- if (sessionPrivate->sessionKeyLock == NULL) {
+ if (prefsPrivate->sessionKeyLock == NULL) {
/* create the session "lock" key */
- sessionPrivate->sessionKeyLock = _SCPNotificationKey(allocator,
- sessionPrivate->prefsID,
- sessionPrivate->perUser,
- sessionPrivate->user,
- kSCPreferencesKeyLock);
+ prefsPrivate->sessionKeyLock = _SCPNotificationKey(allocator,
+ prefsPrivate->prefsID,
+ prefsPrivate->perUser,
+ prefsPrivate->user,
+ kSCPreferencesKeyLock);
}
- if (!SCDynamicStoreAddWatchedKey(sessionPrivate->session,
- sessionPrivate->sessionKeyLock,
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ if (!SCDynamicStoreAddWatchedKey(prefsPrivate->session,
+ prefsPrivate->sessionKeyLock,
FALSE)) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreAddWatchedKey() failed"));
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreAddWatchedKey() failed"));
goto error;
}
- value = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent());
+ value = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent());
while (TRUE) {
CFArrayRef changedKeys;
/*
* Attempt to acquire the lock
*/
- if (SCDynamicStoreAddTemporaryValue(sessionPrivate->session,
- sessionPrivate->sessionKeyLock,
+ if (SCDynamicStoreAddTemporaryValue(prefsPrivate->session,
+ prefsPrivate->sessionKeyLock,
value)) {
haveLock = TRUE;
goto done;
/*
* Wait for the lock to be released
*/
- if (!SCDynamicStoreNotifyWait(sessionPrivate->session)) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreNotifyWait() failed"));
+ if (!SCDynamicStoreNotifyWait(prefsPrivate->session)) {
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreNotifyWait() failed"));
goto error;
}
- changedKeys = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session);
+ changedKeys = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
if (!changedKeys) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreCopyNotifiedKeys() failed"));
goto error;
}
CFRelease(changedKeys);
CFRelease(value);
value = NULL;
- if (!SCDynamicStoreRemoveWatchedKey(sessionPrivate->session,
- sessionPrivate->sessionKeyLock,
+ if (!SCDynamicStoreRemoveWatchedKey(prefsPrivate->session,
+ prefsPrivate->sessionKeyLock,
0)) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveWatchedKey() failed"));
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreRemoveWatchedKey() failed"));
goto error;
}
- changes = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session);
+ changes = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
if (!changes) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreCopyNotifiedKeys() failed"));
goto error;
}
CFRelease(changes);
perUser:
- /*
- * Check the signature
- */
- if (stat(sessionPrivate->path, &statBuf) == -1) {
- if (errno == ENOENT) {
- bzero(&statBuf, sizeof(statBuf));
- } else {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("stat() failed: %s"), strerror(errno));
- _SCErrorSet(kSCStatusStale);
- goto error;
+ if (prefsPrivate->accessed) {
+ CFDataRef currentSignature;
+ Boolean match;
+ struct stat statBuf;
+
+ /*
+ * the preferences have been accessed since the
+ * session was created so we need to compare
+ * the signature of the stored preferences.
+ */
+ if (stat(prefsPrivate->path, &statBuf) == -1) {
+ if (errno == ENOENT) {
+ bzero(&statBuf, sizeof(statBuf));
+ } else {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesLock stat() failed: %s"), strerror(errno));
+ _SCErrorSet(kSCStatusStale);
+ goto error;
+ }
}
- }
- currentSignature = __SCPSignatureFromStatbuf(&statBuf);
- if (!CFEqual(sessionPrivate->signature, currentSignature)) {
- if (sessionPrivate->accessed) {
+ currentSignature = __SCPSignatureFromStatbuf(&statBuf);
+ match = CFEqual(prefsPrivate->signature, currentSignature);
+ CFRelease(currentSignature);
+ if (!match) {
/*
- * the preferences have been accessed since the
- * session was created so we've got no choice
+ * the preferences have been updated since the
+ * session was accessed so we've got no choice
* but to deny the lock request.
*/
_SCErrorSet(kSCStatusStale);
goto error;
- } else {
- /*
- * the file contents have changed but since we
- * haven't accessed any of the preferences we
- * don't need to return an error. Simply reload
- * the stored data and proceed.
- */
- SCPreferencesRef newPrefs;
- SCPreferencesPrivateRef newPrivate;
-
- newPrefs = __SCPreferencesCreate(allocator,
- sessionPrivate->name,
- sessionPrivate->prefsID,
- sessionPrivate->perUser,
- sessionPrivate->user);
- if (!newPrefs) {
- /* if updated preferences could not be loaded */
- _SCErrorSet(kSCStatusStale);
- goto error;
- }
-
- /* synchronize this sessions prefs/signature */
- newPrivate = (SCPreferencesPrivateRef)newPrefs;
- CFRelease(sessionPrivate->prefs);
- sessionPrivate->prefs = newPrivate->prefs;
- CFRetain(sessionPrivate->prefs);
- CFRelease(sessionPrivate->signature);
- sessionPrivate->signature = CFRetain(newPrivate->signature);
- CFRelease(newPrefs);
}
+// } else {
+// /*
+// * the file contents have changed but since we
+// * haven't accessed any of the preference data we
+// * don't need to return an error. Simply proceed.
+// */
}
- CFRelease(currentSignature);
- sessionPrivate->locked = TRUE;
+ prefsPrivate->locked = TRUE;
return TRUE;
error :
if (haveLock) {
- SCDynamicStoreRemoveValue(sessionPrivate->session,
- sessionPrivate->sessionKeyLock);
+ SCDynamicStoreRemoveValue(prefsPrivate->session,
+ prefsPrivate->sessionKeyLock);
}
- if (currentSignature) CFRelease(currentSignature);
if (value) CFRelease(value);
return FALSE;
/*
- * Copyright(c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright(c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * February 16, 2004 Allan Nathanson <ajn@apple.com>
+ * - add preference notification APIs
+ *
* June 1, 2001 Allan Nathanson <ajn@apple.com>
* - public API conversion
*
#include <unistd.h>
#include <sys/errno.h>
+
static CFStringRef
__SCPreferencesCopyDescription(CFTypeRef cf) {
CFAllocatorRef allocator = CFGetAllocator(cf);
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)cf;
CFMutableStringRef result;
result = CFStringCreateMutable(allocator, 0);
- CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {\n"), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {"), cf, allocator);
+ CFStringAppendFormat(result, NULL, CFSTR("name = %@"), prefsPrivate->name);
+ CFStringAppendFormat(result, NULL, CFSTR(", id = %@"), prefsPrivate->prefsID);
+ if (prefsPrivate->perUser) {
+ CFStringAppendFormat(result, NULL, CFSTR(" (for user %@)"), prefsPrivate->user);
+ }
+ CFStringAppendFormat(result, NULL, CFSTR(", path = %s"),
+ prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path);
+ if (prefsPrivate->accessed) {
+ CFStringAppendFormat(result, NULL, CFSTR(", accessed"));
+ }
+ if (prefsPrivate->changed) {
+ CFStringAppendFormat(result, NULL, CFSTR(", changed"));
+ }
+ if (prefsPrivate->locked) {
+ CFStringAppendFormat(result, NULL, CFSTR(", locked"));
+ }
CFStringAppendFormat(result, NULL, CFSTR("}"));
return result;
static void
__SCPreferencesDeallocate(CFTypeRef cf)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)cf;
-
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesDeallocate:"));
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)cf;
/* release resources */
- if (sessionPrivate->name) CFRelease(sessionPrivate->name);
- if (sessionPrivate->prefsID) CFRelease(sessionPrivate->prefsID);
- if (sessionPrivate->user) CFRelease(sessionPrivate->user);
- if (sessionPrivate->path) CFAllocatorDeallocate(NULL, sessionPrivate->path);
- if (sessionPrivate->newPath) CFAllocatorDeallocate(NULL, sessionPrivate->newPath);
- if (sessionPrivate->signature) CFRelease(sessionPrivate->signature);
- if (sessionPrivate->session) CFRelease(sessionPrivate->session);
- if (sessionPrivate->sessionKeyLock) CFRelease(sessionPrivate->sessionKeyLock);
- if (sessionPrivate->sessionKeyCommit) CFRelease(sessionPrivate->sessionKeyCommit);
- if (sessionPrivate->sessionKeyApply) CFRelease(sessionPrivate->sessionKeyApply);
- if (sessionPrivate->prefs) CFRelease(sessionPrivate->prefs);
+
+ pthread_mutex_destroy(&prefsPrivate->lock);
+
+ if (prefsPrivate->name) CFRelease(prefsPrivate->name);
+ if (prefsPrivate->prefsID) CFRelease(prefsPrivate->prefsID);
+ if (prefsPrivate->user) CFRelease(prefsPrivate->user);
+ if (prefsPrivate->path) CFAllocatorDeallocate(NULL, prefsPrivate->path);
+ if (prefsPrivate->newPath) CFAllocatorDeallocate(NULL, prefsPrivate->newPath);
+ if (prefsPrivate->signature) CFRelease(prefsPrivate->signature);
+ if (prefsPrivate->session) CFRelease(prefsPrivate->session);
+ if (prefsPrivate->sessionKeyLock) CFRelease(prefsPrivate->sessionKeyLock);
+ if (prefsPrivate->sessionKeyCommit) CFRelease(prefsPrivate->sessionKeyCommit);
+ if (prefsPrivate->sessionKeyApply) CFRelease(prefsPrivate->sessionKeyApply);
+ if (prefsPrivate->rlsContext.release != NULL) {
+ (*prefsPrivate->rlsContext.release)(prefsPrivate->rlsContext.info);
+ }
+ if (prefsPrivate->prefs) CFRelease(prefsPrivate->prefs);
return;
}
static const CFRuntimeClass __SCPreferencesClass = {
- 0, // version
- "SCPreferences", // className
- NULL, // init
- NULL, // copy
+ 0, // version
+ "SCPreferences", // className
+ NULL, // init
+ NULL, // copy
__SCPreferencesDeallocate, // dealloc
- NULL, // equal
- NULL, // hash
- NULL, // copyFormattingDesc
+ NULL, // equal
+ NULL, // hash
+ NULL, // copyFormattingDesc
__SCPreferencesCopyDescription // copyDebugDesc
};
/* initialize runtime */
pthread_once(&initialized, __SCPreferencesInitialize);
- /* allocate session */
+ /* allocate prefs session */
size = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase);
prefsPrivate = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
__kSCPreferencesTypeID,
size,
NULL);
- if (!prefsPrivate) {
+ if (prefsPrivate == NULL) {
return NULL;
}
- prefsPrivate->name = NULL;
- prefsPrivate->prefsID = NULL;
- prefsPrivate->perUser = FALSE;
- prefsPrivate->user = NULL;
- prefsPrivate->path = NULL;
- prefsPrivate->newPath = NULL; // new prefs path
- prefsPrivate->signature = NULL;
- prefsPrivate->session = NULL;
- prefsPrivate->sessionKeyLock = NULL;
- prefsPrivate->sessionKeyCommit = NULL;
- prefsPrivate->sessionKeyApply = NULL;
- prefsPrivate->prefs = NULL;
- prefsPrivate->accessed = FALSE;
- prefsPrivate->changed = FALSE;
- prefsPrivate->locked = FALSE;
- prefsPrivate->isRoot = (geteuid() == 0);
+ pthread_mutex_init(&prefsPrivate->lock, NULL);
+
+ prefsPrivate->name = NULL;
+ prefsPrivate->prefsID = NULL;
+ prefsPrivate->perUser = FALSE;
+ prefsPrivate->user = NULL;
+ prefsPrivate->path = NULL;
+ prefsPrivate->newPath = NULL; // new prefs path
+ prefsPrivate->signature = NULL;
+ prefsPrivate->session = NULL;
+ prefsPrivate->sessionKeyLock = NULL;
+ prefsPrivate->sessionKeyCommit = NULL;
+ prefsPrivate->sessionKeyApply = NULL;
+ prefsPrivate->rls = NULL;
+ prefsPrivate->rlsFunction = NULL;
+ prefsPrivate->rlsContext.info = NULL;
+ prefsPrivate->rlsContext.retain = NULL;
+ prefsPrivate->rlsContext.release = NULL;
+ prefsPrivate->rlsContext.copyDescription = NULL;
+ prefsPrivate->rlList = NULL;
+ prefsPrivate->prefs = NULL;
+ prefsPrivate->accessed = FALSE;
+ prefsPrivate->changed = FALSE;
+ prefsPrivate->locked = FALSE;
+ prefsPrivate->isRoot = (geteuid() == 0);
return prefsPrivate;
}
int fd = -1;
SCPreferencesPrivateRef prefsPrivate;
int sc_status = kSCStatusOK;
- struct stat statBuf;
- CFMutableDataRef xmlData;
- CFStringRef xmlError;
/*
- * allocate and initialize a new session
+ * allocate and initialize a new prefs session
*/
prefsPrivate = __SCPreferencesCreatePrivate(allocator);
- if (!prefsPrivate) {
+ if (prefsPrivate == NULL) {
return NULL;
}
* open file
*/
fd = open(prefsPrivate->path, O_RDONLY, 0644);
- if (fd == -1) {
+ if (fd != -1) {
+ (void) close(fd);
+ } else {
switch (errno) {
case ENOENT :
/* no prefs file */
}
}
- /* start fresh */
- bzero(&statBuf, sizeof(statBuf));
- goto create_1;
+ /* no preference data, start fresh */
+ goto done;
case EACCES :
sc_status = kSCStatusAccessError;
break;
sc_status = kSCStatusFailed;
break;
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("open() failed: %s"), strerror(errno));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
goto error;
}
+ done :
+
/*
- * check file, create signature
+ * all OK
*/
- if (fstat(fd, &statBuf) == -1) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("fstat() failed: %s"), strerror(errno));
- sc_status = kSCStatusFailed;
+ prefsPrivate->name = CFStringCreateCopy(allocator, name);
+ if (prefsID != NULL) prefsPrivate->prefsID = CFStringCreateCopy(allocator, prefsID);
+ prefsPrivate->perUser = perUser;
+ if (user != NULL) prefsPrivate->user = CFStringCreateCopy(allocator, user);
+ return (SCPreferencesRef)prefsPrivate;
+
+ error :
+
+ if (fd != -1) (void) close(fd);
+ CFRelease(prefsPrivate);
+ _SCErrorSet(sc_status);
+ return NULL;
+}
+
+
+__private_extern__ Boolean
+__SCPreferencesAccess(SCPreferencesRef prefs)
+{
+ CFAllocatorRef allocator = CFGetAllocator(prefs);
+ int fd = -1;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+ int sc_status = kSCStatusOK;
+ struct stat statBuf;
+
+ if (prefsPrivate->accessed) {
+ // if preference data has already been accessed
+ return TRUE;
+ }
+
+ fd = open(prefsPrivate->path, O_RDONLY, 0644);
+ if (fd != -1) {
+ // create signature
+ if (fstat(fd, &statBuf) == -1) {
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess fstat() failed: %s"), strerror(errno));
+ sc_status = kSCStatusFailed;
+ goto error;
+ }
+ } else {
+ switch (errno) {
+ case ENOENT :
+ /* no preference data, start fresh */
+ bzero(&statBuf, sizeof(statBuf));
+ goto create_1;
+ case EACCES :
+ sc_status = kSCStatusAccessError;
+ break;
+ default :
+ sc_status = kSCStatusFailed;
+ break;
+ }
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess open() failed: %s"), strerror(errno));
goto error;
}
create_1 :
+ if (prefsPrivate->signature != NULL) CFRelease(prefsPrivate->signature);
prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
if (statBuf.st_size > 0) {
- CFDictionaryRef dict;
+ CFDictionaryRef dict;
+ CFMutableDataRef xmlData;
+ CFStringRef xmlError;
/*
* extract property list
CFDataSetLength(xmlData, statBuf.st_size);
if (read(fd, (void *)CFDataGetBytePtr(xmlData), statBuf.st_size) != statBuf.st_size) {
/* corrupt prefs file, start fresh */
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen read(): could not load preference data."));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess read(): could not load preference data."));
CFRelease(xmlData);
xmlData = NULL;
goto create_2;
kCFPropertyListImmutable,
&xmlError);
CFRelease(xmlData);
- if (!dict) {
+ if (dict == NULL) {
/* corrupt prefs file, start fresh */
- if (xmlError) {
+ if (xmlError != NULL) {
SCLog(TRUE, LOG_ERR,
- CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
+ CFSTR("__SCPreferencesAccess CFPropertyListCreateFromXMLData(): %@"),
xmlError);
CFRelease(xmlError);
}
*/
if (!isA_CFDictionary(dict)) {
/* corrupt prefs file, start fresh */
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess CFGetTypeID(): not a dictionary."));
CFRelease(dict);
goto create_2;
}
/*
* new file, create empty preferences
*/
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary."));
+ SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess(): creating new dictionary."));
prefsPrivate->prefs = CFDictionaryCreateMutable(allocator,
0,
&kCFTypeDictionaryKeyCallBacks,
prefsPrivate->changed = TRUE;
}
- /*
- * all OK
- */
- prefsPrivate->name = CFStringCreateCopy(allocator, name);
- if (prefsID) prefsPrivate->prefsID = CFStringCreateCopy(allocator, prefsID);
- prefsPrivate->perUser = perUser;
- if (user) prefsPrivate->user = CFStringCreateCopy(allocator, user);
- return (SCPreferencesRef)prefsPrivate;
+ prefsPrivate->accessed = TRUE;
+ return TRUE;
error :
if (fd != -1) (void) close(fd);
- CFRelease(prefsPrivate);
_SCErrorSet(sc_status);
- return NULL;
+ return FALSE;
+
}
CFStringRef name,
CFStringRef prefsID)
{
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesCreate:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID);
- }
-
return __SCPreferencesCreate(allocator, name, prefsID, FALSE, NULL);
}
CFStringRef prefsID,
CFStringRef user)
{
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCUserPreferencesCreate:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" prefsID = %@"), prefsID);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" user = %@"), user);
- }
-
return __SCPreferencesCreate(allocator, name, prefsID, TRUE, user);
}
pthread_once(&initialized, __SCPreferencesInitialize); /* initialize runtime */
return __kSCPreferencesTypeID;
}
+
+
+static void
+prefsNotify(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+ void *context_info;
+ void (*context_release)(const void *);
+ CFIndex i;
+ CFIndex n;
+ SCPreferencesNotification notify = 0;
+ SCPreferencesRef prefs = (SCPreferencesRef)info;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+ SCPreferencesCallBack rlsFunction;
+
+ n = (changedKeys != NULL) ? CFArrayGetCount(changedKeys) : 0;
+ for (i = 0; i < n; i++) {
+ CFStringRef key;
+
+ key = CFArrayGetValueAtIndex(changedKeys, i);
+ if (CFEqual(key, prefsPrivate->sessionKeyCommit)) {
+ // if preferences have been saved
+ notify |= kSCPreferencesNotificationCommit;
+ }
+ if (CFEqual(key, prefsPrivate->sessionKeyApply)) {
+ // if stored preferences should be applied to current configuration
+ notify |= kSCPreferencesNotificationApply;
+ }
+ }
+
+ if (notify == 0) {
+ // if no changes
+ return;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ /* callout */
+ rlsFunction = prefsPrivate->rlsFunction;
+ if (prefsPrivate->rlsContext.retain != NULL) {
+ context_info = (void *)prefsPrivate->rlsContext.retain(prefsPrivate->rlsContext.info);
+ context_release = prefsPrivate->rlsContext.release;
+ } else {
+ context_info = prefsPrivate->rlsContext.info;
+ context_release = NULL;
+ }
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ if (rlsFunction != NULL) {
+ (*rlsFunction)(prefs, notify, context_info);
+ }
+
+ if (context_release != NULL) {
+ (*context_release)(context_info);
+ }
+
+ return;
+}
+
+
+__private_extern__ Boolean
+__SCPreferencesAddSession(SCPreferencesRef prefs)
+{
+ CFAllocatorRef allocator = CFGetAllocator(prefs);
+ SCDynamicStoreContext context = { 0
+ , (void *)prefs
+ , NULL
+ , NULL
+ , NULL
+ };
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+ /* establish a dynamic store session */
+ prefsPrivate->session = SCDynamicStoreCreate(allocator,
+ CFSTR("SCPreferences"),
+ prefsNotify,
+ &context);
+ if (prefsPrivate->session == NULL) {
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("__SCPreferencesAddSession SCDynamicStoreCreate() failed"));
+ return FALSE;
+ }
+
+ /* create the session "commit" key */
+ prefsPrivate->sessionKeyCommit = _SCPNotificationKey(NULL,
+ prefsPrivate->prefsID,
+ prefsPrivate->perUser,
+ prefsPrivate->user,
+ kSCPreferencesKeyCommit);
+
+ /* create the session "apply" key */
+ prefsPrivate->sessionKeyApply = _SCPNotificationKey(NULL,
+ prefsPrivate->prefsID,
+ prefsPrivate->perUser,
+ prefsPrivate->user,
+ kSCPreferencesKeyApply);
+
+ return TRUE;
+}
+
+
+Boolean
+SCPreferencesSetCallback(SCPreferencesRef prefs,
+ SCPreferencesCallBack callout,
+ SCPreferencesContext *context)
+{
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ if (prefsPrivate->rlsContext.release != NULL) {
+ /* let go of the current context */
+ (*prefsPrivate->rlsContext.release)(prefsPrivate->rlsContext.info);
+ }
+
+ prefsPrivate->rlsFunction = callout;
+ prefsPrivate->rlsContext.info = NULL;
+ prefsPrivate->rlsContext.retain = NULL;
+ prefsPrivate->rlsContext.release = NULL;
+ prefsPrivate->rlsContext.copyDescription = NULL;
+ if (context != NULL) {
+ bcopy(context, &prefsPrivate->rlsContext, sizeof(SCPreferencesContext));
+ if (context->retain != NULL) {
+ prefsPrivate->rlsContext.info = (void *)(*context->retain)(context->info);
+ }
+ }
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+
+ return TRUE;
+}
+
+
+Boolean
+SCPreferencesScheduleWithRunLoop(SCPreferencesRef prefs,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode)
+{
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ if (prefsPrivate->rls == NULL) {
+ CFMutableArrayRef keys;
+
+ if (prefsPrivate->session == NULL) {
+ __SCPreferencesAddSession(prefs);
+ }
+
+ CFRetain(prefs); // hold a reference to the prefs
+
+ keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFArrayAppendValue(keys, prefsPrivate->sessionKeyCommit);
+ CFArrayAppendValue(keys, prefsPrivate->sessionKeyApply);
+ (void)SCDynamicStoreSetNotificationKeys(prefsPrivate->session, keys, NULL);
+ CFRelease(keys);
+
+ prefsPrivate->rls = SCDynamicStoreCreateRunLoopSource(NULL, prefsPrivate->session, 0);
+ prefsPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ if (!_SC_isScheduled(NULL, runLoop, runLoopMode, prefsPrivate->rlList)) {
+ /*
+ * if we do not already have notifications scheduled with
+ * this runLoop / runLoopMode
+ */
+ CFRunLoopAddSource(runLoop, prefsPrivate->rls, runLoopMode);
+ }
+
+ _SC_schedule(prefs, runLoop, runLoopMode, prefsPrivate->rlList);
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+ return TRUE;
+}
+
+
+Boolean
+SCPreferencesUnscheduleFromRunLoop(SCPreferencesRef prefs,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode)
+{
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+ CFIndex n;
+ Boolean ok = FALSE;
+
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&prefsPrivate->lock);
+
+ if (prefsPrivate->rls == NULL) {
+ /* if not currently scheduled */
+ goto done;
+ }
+
+ if (!_SC_unschedule(NULL, runLoop, runLoopMode, prefsPrivate->rlList, FALSE)) {
+ /* if not currently scheduled */
+ goto done;
+ }
+
+ n = CFArrayGetCount(prefsPrivate->rlList);
+ if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, prefsPrivate->rlList)) {
+ /*
+ * if we are no longer scheduled to receive notifications for
+ * this runLoop / runLoopMode
+ */
+ CFRunLoopRemoveSource(runLoop, prefsPrivate->rls, runLoopMode);
+
+ if (n == 0) {
+ CFArrayRef changedKeys;
+
+ /*
+ * if *all* notifications have been unscheduled
+ */
+ CFRunLoopSourceInvalidate(prefsPrivate->rls);
+ CFRelease(prefsPrivate->rls);
+ prefsPrivate->rls = NULL;
+ CFRelease(prefsPrivate->rlList);
+ prefsPrivate->rlList = NULL;
+
+ CFRelease(prefs); // release our reference to the prefs
+
+ // no need to track changes
+ (void)SCDynamicStoreSetNotificationKeys(prefsPrivate->session, NULL, NULL);
+
+ // clear out any pending notifications
+ changedKeys = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
+ if (changedKeys != NULL) {
+ CFRelease(changedKeys);
+ }
+ }
+ }
+
+ ok = TRUE;
+
+ done :
+
+ pthread_mutex_unlock(&prefsPrivate->lock);
+ return ok;
+}
+
+
+void
+SCPreferencesSynchronize(SCPreferencesRef prefs)
+{
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return;
+ }
+
+ if (prefsPrivate->prefs != NULL) {
+ CFRelease(prefsPrivate->prefs);
+ prefsPrivate->prefs = NULL;
+ }
+ if (prefsPrivate->signature != NULL) {
+ CFRelease(prefsPrivate->signature);
+ prefsPrivate->signature = NULL;
+ }
+ prefsPrivate->accessed = FALSE;
+ prefsPrivate->changed = FALSE;
+ return;
+}
static Boolean
-getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
+getPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef *entity)
{
CFStringRef element;
CFArrayRef elements;
CFIndex nElements;
CFIndex nLinks = 0;
Boolean ok = FALSE;
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
CFDictionaryRef value = NULL;
elements = normalizePath(path);
return FALSE;
}
+ __SCPreferencesAccess(prefs);
+
restart :
nElements = CFArrayGetCount(elements);
for (i = 0; i < nElements; i++) {
element = CFArrayGetValueAtIndex(elements, i);
if (i == 0) {
- sessionPrivate->accessed = TRUE;
- value = CFDictionaryGetValue(sessionPrivate->prefs,
+ value = CFDictionaryGetValue(prefsPrivate->prefs,
CFArrayGetValueAtIndex(elements, 0));
} else {
value = CFDictionaryGetValue(value, element);
static Boolean
-setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
+setPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef entity)
{
CFStringRef element;
CFArrayRef elements;
CFDictionaryRef node = NULL;
CFMutableArrayRef nodes;
Boolean ok = FALSE;
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
elements = normalizePath(path);
if (elements == NULL) {
return FALSE;
}
+ __SCPreferencesAccess(prefs);
+
restart :
nElements = CFArrayGetCount(elements);
for (i = 0; i < nElements - 1; i++) {
element = CFArrayGetValueAtIndex(elements, i);
if (i == 0) {
- sessionPrivate->accessed = TRUE;
- node = CFDictionaryGetValue(sessionPrivate->prefs, element);
+ node = CFDictionaryGetValue(prefsPrivate->prefs, element);
} else {
node = CFDictionaryGetValue(node, element);
element = CFArrayGetValueAtIndex(elements, i);
if (i == 0) {
if (newEntity) {
- CFDictionarySetValue(sessionPrivate->prefs, element, newEntity);
+ CFDictionarySetValue(prefsPrivate->prefs, element, newEntity);
} else {
- CFDictionaryRemoveValue(sessionPrivate->prefs, element);
+ CFDictionaryRemoveValue(prefsPrivate->prefs, element);
}
- sessionPrivate->changed = TRUE;
+ prefsPrivate->changed = TRUE;
ok = TRUE;
} else {
CFMutableDictionaryRef newNode;
CFStringRef
-SCPreferencesPathCreateUniqueChild(SCPreferencesRef session,
+SCPreferencesPathCreateUniqueChild(SCPreferencesRef prefs,
CFStringRef prefix)
{
CFStringRef child;
CFUUIDRef uuid;
CFDictionaryRef entity;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathCreateUniqueChild:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" prefix = %@"), prefix);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return NULL;
}
- if (getPath(session, prefix, &entity)) {
+ if (getPath(prefs, prefix, &entity)) {
// if prefix path exists
if (CFDictionaryContainsKey(entity, kSCResvLink)) {
/* the path is a link... */
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
- if (setPath(session, newPath, newDict)) {
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" child = %@"), newPath);
- } else {
+ if (!setPath(prefs, newPath, newDict)) {
CFRelease(newPath);
newPath = NULL;
}
CFDictionaryRef
-SCPreferencesPathGetValue(SCPreferencesRef session,
+SCPreferencesPathGetValue(SCPreferencesRef prefs,
CFStringRef path)
{
CFDictionaryRef entity;
CFStringRef entityLink;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathGetValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return NULL;
}
- if (!getPath(session, path, &entity)) {
+ if (!getPath(prefs, path, &entity)) {
return NULL;
}
if (isA_CFDictionary(entity) &&
(CFDictionaryGetValueIfPresent(entity, kSCResvLink, (const void **)&entityLink))) {
/* if this is a dictionary AND it is a link */
- if (!getPath(session, entityLink, &entity)) {
+ if (!getPath(prefs, entityLink, &entity)) {
/* if it was a bad link */
return NULL;
}
}
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), entity);
return entity;
}
CFStringRef
-SCPreferencesPathGetLink(SCPreferencesRef session,
+SCPreferencesPathGetLink(SCPreferencesRef prefs,
CFStringRef path)
{
CFDictionaryRef entity;
CFStringRef entityLink;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathGetLink:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return NULL;
}
- if (!getPath(session, path, &entity)) {
+ if (!getPath(prefs, path, &entity)) {
return NULL;
}
if (isA_CFDictionary(entity) &&
(CFDictionaryGetValueIfPresent(entity, kSCResvLink, (const void **)&entityLink))) {
/* if this is a dictionary AND it is a link */
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" link = %@"), entityLink);
return entityLink;
}
Boolean
-SCPreferencesPathSetValue(SCPreferencesRef session,
+SCPreferencesPathSetValue(SCPreferencesRef prefs,
CFStringRef path,
CFDictionaryRef value)
{
Boolean ok;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathSetValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
}
if (!value) {
return FALSE;
}
- ok = setPath(session, path, value);
+ ok = setPath(prefs, path, value);
return ok;
}
Boolean
-SCPreferencesPathSetLink(SCPreferencesRef session,
+SCPreferencesPathSetLink(SCPreferencesRef prefs,
CFStringRef path,
CFStringRef link)
{
CFDictionaryRef entity;
Boolean ok;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathSetLink:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" link = %@"), link);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
}
if (!link) {
return FALSE;
}
- if (!getPath(session, link, &entity)) {
+ if (!getPath(prefs, link, &entity)) {
// if bad link
return FALSE;
}
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(dict, kSCResvLink, link);
- ok = setPath(session, path, dict);
+ ok = setPath(prefs, path, dict);
CFRelease(dict);
return ok;
Boolean
-SCPreferencesPathRemoveValue(SCPreferencesRef session,
+SCPreferencesPathRemoveValue(SCPreferencesRef prefs,
CFStringRef path)
{
CFArrayRef elements = NULL;
Boolean ok = FALSE;
CFDictionaryRef value;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathRemoveValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %@"), path);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
}
- if (!getPath(session, path, &value)) {
+ if (!getPath(prefs, path, &value)) {
// if no such path
return FALSE;
}
return FALSE;
}
- ok = setPath(session, path, NULL);
+ ok = setPath(prefs, path, NULL);
CFRelease(elements);
return ok;
#include "SCPreferencesInternal.h"
Boolean
-SCPreferencesRemoveValue(SCPreferencesRef session, CFStringRef key)
+SCPreferencesRemoveValue(SCPreferencesRef prefs, CFStringRef key)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesRemoveValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
}
- sessionPrivate->accessed = TRUE;
+ __SCPreferencesAccess(prefs);
- if (!CFDictionaryContainsKey(sessionPrivate->prefs, key)) {
+ if (!CFDictionaryContainsKey(prefsPrivate->prefs, key)) {
_SCErrorSet(kSCStatusNoKey);
return FALSE;
}
- CFDictionaryRemoveValue(sessionPrivate->prefs, key);
- sessionPrivate->changed = TRUE;
+ CFDictionaryRemoveValue(prefsPrivate->prefs, key);
+ prefsPrivate->changed = TRUE;
return TRUE;
}
#include "SCPreferencesInternal.h"
Boolean
-SCPreferencesSetValue(SCPreferencesRef session, CFStringRef key, CFPropertyListRef value)
+SCPreferencesSetValue(SCPreferencesRef prefs, CFStringRef key, CFPropertyListRef value)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
- if (_sc_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesSetValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), value);
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
}
- CFDictionarySetValue(sessionPrivate->prefs, key, value);
- sessionPrivate->accessed = TRUE;
- sessionPrivate->changed = TRUE;
+ __SCPreferencesAccess(prefs);
+
+ CFDictionarySetValue(prefsPrivate->prefs, key, value);
+ prefsPrivate->changed = TRUE;
return TRUE;
}
#include "SCPreferencesInternal.h"
Boolean
-SCPreferencesUnlock(SCPreferencesRef session)
+SCPreferencesUnlock(SCPreferencesRef prefs)
{
- SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session;
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesUnlock:"));
+ if (prefs == NULL) {
+ /* sorry, you must provide a session */
+ _SCErrorSet(kSCStatusNoPrefsSession);
+ return FALSE;
+ }
- if (!sessionPrivate->locked) {
+ if (!prefsPrivate->locked) {
/* sorry, you don't have the lock */
_SCErrorSet(kSCStatusNeedLock);
return FALSE;
}
- if (!sessionPrivate->isRoot) {
+ if (!prefsPrivate->isRoot) {
/* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
goto perUser;
}
- if (!SCDynamicStoreRemoveValue(sessionPrivate->session, sessionPrivate->sessionKeyLock)) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveValue() failed"));
+ if (!SCDynamicStoreRemoveValue(prefsPrivate->session, prefsPrivate->sessionKeyLock)) {
+ SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesUnlock SCDynamicStoreRemoveValue() failed"));
return FALSE;
}
perUser:
- sessionPrivate->locked = FALSE;
+ prefsPrivate->locked = FALSE;
return TRUE;
}
#include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCDynamicStore.h>
/*!
@header SCPreferences
- The SCPreferencesXXX() APIs allow an application to load and
- store XML configuration data in a controlled manner and provide
- the necessary notifications to other applications that need to
- be aware of configuration changes.
-
- The stored XML configuration data is accessed using a prefsID. A
- NULL value indicates that the default system preferences are to
- be accessed.
- A string which starts with a leading "/" character specifies the
- path to the file containing te preferences to be accessed.
- A string which does not start with a leading "/" character
- specifies a file relative to the default system preferences
- directory.
+ @discussion The SCPreferences API allows an application to load and
+ store XML configuration data in a controlled manner and provide
+ the necessary notifications to other applications that need to
+ be aware of configuration changes.
+
+ To access configuration preferences, you must first establish a
+ preferences session using the SCPreferencesCreate function.
+ To identify a specific set of preferences to access, you pass a
+ value in the prefsID parameter.
+ A NULL value indicates that the default system preferences are
+ to be accessed.
+ A string that starts with a leading "/" character specifies
+ the absolute path to the file containing the preferences to
+ be accessed.
+ A string that does not start with a leading "/" character
+ specifies a file relative to the default system preferences
+ directory.
+
+ When you are finished with the preferences session, use
+ CFRelease to close it.
*/
/*!
@typedef SCPreferencesRef
- @discussion This is the handle to an open "session" for
+ @discussion This is the handle to an open preferences session for
accessing system configuration preferences.
*/
typedef const struct __SCPreferences * SCPreferencesRef;
+/*!
+ @enum SCPreferencesNotification
+ @discussion Used with the SCPreferencesCallBack callback
+ to describe the type of notification.
+ @constant kSCPreferencesNotificationCommit Indicates when new
+ preferences have been saved.
+ @constant kSCPreferencesNotificationApply Key Indicates when a
+ request has been made to apply the currently saved
+ preferences to the active system configuration.
+ */
+enum {
+ kSCPreferencesNotificationCommit = 1<<0,
+ kSCPreferencesNotificationApply = 1<<1
+};
+typedef uint32_t SCPreferencesNotification;
+
+/*!
+ @typedef SCPreferencesContext
+ Structure containing user-specified data and callbacks for SCPreferences.
+ @field version The version number of the structure type being passed
+ in as a parameter to the SCPreferencesSetCallback function.
+ This structure is version 0.
+ @field info A C pointer to a user-specified block of data.
+ @field retain The callback used to add a retain for the info field.
+ If this parameter is not a pointer to a function of the correct
+ prototype, the behavior is undefined.
+ The value may be NULL.
+ @field release The calllback used to remove a retain previously added
+ for the info field.
+ If this parameter is not a pointer to a function of the
+ correct prototype, the behavior is undefined.
+ The value may be NULL.
+ @field copyDescription The callback used to provide a description of
+ the info field.
+ */
+typedef struct {
+ CFIndex version;
+ void * info;
+ const void *(*retain)(const void *info);
+ void (*release)(const void *info);
+ CFStringRef (*copyDescription)(const void *info);
+} SCPreferencesContext;
+
+/*!
+ @typedef SCPreferencesCallBack
+ @discussion Type of the callback function used when the
+ preferences have been updated and/or applied.
+ @param prefs The preferences session.
+ @param notificationType The type of notification, such as changes
+ committed, changes applied, etc.
+ @param info A C pointer to a user-specified block of data.
+ */
+typedef void (*SCPreferencesCallBack) (
+ SCPreferencesRef prefs,
+ SCPreferencesNotification notificationType,
+ void *info
+ );
+
__BEGIN_DECLS
/*!
@function SCPreferencesGetTypeID
- Returns the type identifier of all SCPreferences instances.
+ @discussion Returns the type identifier of all SCPreferences instances.
*/
CFTypeID
SCPreferencesGetTypeID (void);
-
/*!
@function SCPreferencesCreate
@discussion Initiates access to the per-system set of configuration
preferences.
- @param allocator ...
+ @param allocator The CFAllocator that should be used to allocate
+ memory for this preferences session.
+ This parameter may be NULL in which case the current
+ default CFAllocator is used.
+ If this reference is not a valid CFAllocator, the behavior
+ is undefined.
@param name A string that describes the name of the calling
process.
@param prefsID A string that identifies the name of the
- group of preferences to be accessed/updated.
- @result prefs A pointer to memory that will be filled with an
- SCPreferencesRef handle to be used for all subsequent requests.
- If a session cannot be established, the contents of
- memory pointed to by this parameter are undefined.
+ group of preferences to be accessed or updated.
+ @result Returns a reference to the new SCPreferences.
+ You must release the returned value.
*/
SCPreferencesRef
SCPreferencesCreate (
@function SCPreferencesLock
@discussion Locks access to the configuration preferences.
- This function obtains exclusive access to the configuration
- preferences associated with this prefsID. Clients attempting
- to obtain exclusive access to the preferences will either receive
- an kSCStatusPrefsBusy error or block waiting for the lock to be
- released.
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
+ This function obtains exclusive access to the configuration
+ preferences. Clients attempting to obtain exclusive access
+ to the preferences will either receive a kSCStatusPrefsBusy
+ error or block waiting for the lock to be released.
+ @param prefs The preferences session.
@param wait A boolean flag indicating whether the calling process
should block waiting for another process to complete its update
operation and release its lock.
- @result TRUE if the lock was obtained; FALSE if an error occurred.
+ @result Returns TRUE if the lock was obtained;
+ FALSE if an error occurred.
*/
Boolean
SCPreferencesLock (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
Boolean wait
);
/*!
@function SCPreferencesCommitChanges
@discussion Commits changes made to the configuration preferences to
- persitent storage.
-
- This function commits any changes to permanent storage. An
- implicit call to SCPreferencesLock/SCPreferencesUnlock will
- be made if exclusive access has not already been established.
-
- Note: This routine commits changes to persistent storage.
- Call SCPreferencesApplyChanges() to apply the changes
- to the running system.
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
- @result TRUE if the lock was obtained; FALSE if an error occurred.
+ persistent storage.
+
+ This function commits any changes to permanent storage.
+ Implicit calls to the SCPreferencesLock and SCPreferencesUnlock
+ functions will be made if exclusive access has not already been
+ established.
+
+ Note: This routine commits changes to persistent storage.
+ Call the SCPreferencesApplyChanges function to apply the
+ changes to the running system.
+ @param prefs The preferences session.
+ @result Returns TRUE if the lock was obtained;
+ FALSE if an error occurred.
*/
Boolean
SCPreferencesCommitChanges (
- SCPreferencesRef session
+ SCPreferencesRef prefs
);
/*!
@function SCPreferencesApplyChanges
@discussion Requests that the currently stored configuration
preferences be applied to the active configuration.
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
- @result TRUE if the lock was obtained; FALSE if an error occurred.
+ @param prefs The preferences session.
+ @result Returns TRUE if the lock was obtained;
+ FALSE if an error occurred.
*/
Boolean
SCPreferencesApplyChanges (
- SCPreferencesRef session
+ SCPreferencesRef prefs
);
/*!
@function SCPreferencesUnlock
@discussion Releases exclusive access to the configuration preferences.
- This function releases the exclusive access "lock" for this prefsID.
- Other clients will be now be able to establish exclusive access to
- the preferences.
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
- @result TRUE if the lock was obtained; FALSE if an error occurred.
+ This function releases the exclusive access lock to the
+ preferences. Other clients will be now be able to establish
+ exclusive access to the preferences.
+ @param prefs The preferences session.
+ @result Returns TRUE if the lock was obtained;
+ FALSE if an error occurred.
*/
Boolean
SCPreferencesUnlock (
- SCPreferencesRef session
+ SCPreferencesRef prefs
);
/*!
@function SCPreferencesGetSignature
@discussion Returns a sequence of bytes that can be used to determine
if the saved configuration preferences have changed.
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
- @param signature A pointer to a CFDataRef that will reflect
- the signature of the configuration preferences at the time
- of the call to SCPreferencesCreate().
- @result A CFDataRef that reflects the signature of the configuration
- preferences at the time of the call to SCPreferencesCreate().
+ @param prefs The preferences session.
+ @result Returns a CFDataRef that reflects the signature of the configuration
+ preferences at the time of the call to the SCPreferencesCreate function.
*/
CFDataRef
SCPreferencesGetSignature (
- SCPreferencesRef session
+ SCPreferencesRef prefs
);
/*!
@function SCPreferencesCopyKeyList
@discussion Returns an array of currently defined preference keys.
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
- @result The list of keys. You must release the returned value.
+ @param prefs The preferences session.
+ @result Returns the list of keys.
+ You must release the returned value.
*/
CFArrayRef
SCPreferencesCopyKeyList (
- SCPreferencesRef session
+ SCPreferencesRef prefs
);
/*!
@function SCPreferencesGetValue
@discussion Returns the data associated with a preference key.
- This function retrieves data associated with a key for the prefsID.
+ This function retrieves data associated with the specified
+ key.
- Note: You could read stale data and not know it, unless you
- first call SCPreferencesLock().
- @param session An SCPreferencesRef handle that should be used for
- all API calls.
+ Note: To avoid inadvertantly reading stale data, first call
+ the SCPreferencesLock function.
+ @param prefs The preferences session.
@param key The preference key to be returned.
- @result The value associated with the specified preference key; If no
- value was located, NULL is returned.
+ @result Returns the value associated with the specified preference key;
+ NULL if no value was located.
*/
CFPropertyListRef
SCPreferencesGetValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef key
);
@function SCPreferencesAddValue
@discussion Adds data for a preference key.
- This function associates new data with the specified key. In order
- to commit these changes to permanent storage a call must be made to
- SCPreferencesCommitChanges().
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ This function associates new data with the specified key.
+ To commit these changes to permanent storage, a call must
+ be made to the SCPreferencesCommitChanges function.
+ @param prefs The preferences session.
@param key The preference key to be updated.
@param value The CFPropertyListRef object containing the
value to be associated with the specified preference key.
- @result TRUE if the value was added; FALSE if the key already exists or
+ @result Returns TRUE if the value was added;
+ FALSE if the key already exists or
if an error occurred.
*/
Boolean
SCPreferencesAddValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef key,
CFPropertyListRef value
);
@function SCPreferencesSetValue
@discussion Updates the data associated with a preference key.
- This function adds or replaces the value associated with the
- specified key. In order to commit these changes to permanent
- storage a call must be made to SCPreferencesCommitChanges().
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ This function adds or replaces the value associated with the
+ specified key. To commit these changes to permanent storage
+ a call must be made to the SCPreferencesCommitChanges function.
+ @param prefs The preferences session.
@param key The preference key to be updated.
@param value The CFPropertyListRef object containing the
data to be associated with the specified preference key.
- @result TRUE if the value was set; FALSE if an error occurred.
+ @result Returns TRUE if the value was set;
+ FALSE if an error occurred.
*/
Boolean
SCPreferencesSetValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef key,
CFPropertyListRef value
);
@function SCPreferencesRemoveValue
@discussion Removes the data associated with a preference key.
- This function removes the data associated with the specified
- key. In order to commit these changes to permanent storage a
- call must be made to SCPreferencesCommitChanges().
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ This function removes the data associated with the specified
+ key. To commit these changes to permanent storage a call must
+ be made to the SCPreferencesCommitChanges function.
+ @param prefs The preferences session.
@param key The preference key to be removed.
- @result TRUE if the value was removed; FALSE if the key did not exist or
- if an error occurred.
+ @result Returns TRUE if the value was removed;
+ FALSE if the key did not exist or if an error occurred.
*/
Boolean
SCPreferencesRemoveValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef key
);
+/*!
+ @function SCPreferencesSetCallback
+ @discussion Assigns a callback to a preferences session. The function
+ is called when the changes to the preferences have been
+ committed or applied.
+ @param prefs The preferences session.
+ @param callout The function to be called when the preferences have
+ been changed or applied.
+ If NULL, the current callback is removed.
+ @param context The SCPreferencesContext associated with
+ the callout.
+ @result Returns TRUE if the notification client was successfully set.
+ */
+Boolean
+SCPreferencesSetCallback (
+ SCPreferencesRef prefs,
+ SCPreferencesCallBack callout,
+ SCPreferencesContext *context
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesScheduleWithRunLoop
+ @discussion Schedule commit and apply notifications for the specified
+ preferences session using the specified run loop and mode.
+ @param prefs The preferences session.
+ @param runLoop A reference to a run loop on which the notification
+ should be scheduled.
+ Must be non-NULL.
+ @param runLoopMode The mode on which to schedule the notification.
+ Must be non-NULL.
+ @result Returns TRUE if the notifications are successfully scheduled;
+ FALSE otherwise.
+ */
+Boolean
+SCPreferencesScheduleWithRunLoop (
+ SCPreferencesRef prefs,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesUnscheduleFromRunLoop
+ @discussion Unschedule commit and apply notifications for the specified
+ preferences session from the specified run loop and mode.
+ @param prefs The preferences session.
+ @param runLoop A reference to a run loop from which the notification
+ should be unscheduled.
+ Must be non-NULL.
+ @param runLoopMode The mode on which to unschedule the notification.
+ Must be non-NULL.
+ @result Returns TRUE if the notifications are successfully unscheduled;
+ FALSE otherwise.
+ */
+Boolean
+SCPreferencesUnscheduleFromRunLoop (
+ SCPreferencesRef prefs,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesSynchronize
+ @discussion Synchronizes accessed preferences with committed changes.
+
+ Any references to preference values returned by calls to the
+ SCPreferencesGetValue function are no longer valid unless they
+ were explicitly retained or copied. Any preference values
+ that were updated (add, set, remove) but not committed will
+ be discarded.
+ @param prefs The preferences session.
+ */
+void
+SCPreferencesSynchronize (
+ SCPreferencesRef prefs
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
__END_DECLS
#endif /* _SCPREFERENCES_H */
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, 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@
+ */
+
+#ifndef _SCPREFERENCESGETSPECIFICPRIVATE_H
+#define _SCPREFERENCESGETSPECIFICPRIVATE_H
+
+#include <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPreferences.h>
+
+
+/*!
+ @header SCPreferencesGetSpecificPrivate
+ @discussion The functions in the SCPreferencesGetSpecificPrivate API allow
+ an application to get specific configuration information
+ about the current system (for example, the host name).
+
+ To access configuration preferences, you must first establish
+ a preferences session using the SCPreferencesCreate function.
+ */
+
+
+__BEGIN_DECLS
+
+/*!
+ @function SCPreferencesGetHostName
+ @discussion Gets the host name preference.
+ @param prefs The preferences session.
+ @result name The host name to be set;
+ NULL if the name has not been set or if an error was encountered.
+ */
+CFStringRef
+SCPreferencesGetHostName (
+ SCPreferencesRef prefs
+ );
+
+__END_DECLS
+
+#endif /* _SCPREFERENCESGETSPECIFICPRIVATE_H */
/* base CFType information */
CFRuntimeBase cfBase;
+ /* lock */
+ pthread_mutex_t lock;
+
/* session name */
CFStringRef name;
Boolean perUser;
CFStringRef user;
- /* configuration file path */
+ /* configuration file */
char *path;
char *newPath;
CFStringRef sessionKeyCommit;
CFStringRef sessionKeyApply;
+ /* run loop source, callout, context, rl scheduling info */
+ CFRunLoopSourceRef rls;
+ SCPreferencesCallBack rlsFunction;
+ SCPreferencesContext rlsContext;
+ CFMutableArrayRef rlList;
+
/* preferences */
CFMutableDictionaryRef prefs;
Boolean perUser,
CFStringRef user);
+Boolean
+__SCPreferencesAccess (SCPreferencesRef prefs);
+
+Boolean
+__SCPreferencesAddSession (SCPreferencesRef prefs);
+
CFDataRef
__SCPSignatureFromStatbuf (const struct stat *statBuf);
/*!
@header SCPreferencesPath
- The SCPreferencesPathXXX() APIs allow an application to
- load and store XML configuration data in a controlled
- manner and provide the necessary notifications to other
- applications that need to be aware of configuration
- changes.
-
- The SCPreferencesPathXXX() APIs make certain assumptions
- about the layout of the preferences data. These APIs view
- the data as a collection of dictionaries of key/value pairs
- and an associated path name. The root path ("/") identifies
- the top-level dictionary. Additional path components
- specify the keys for sub-dictionaries.
-
- For example, the following dictionary can be accessed via
- two paths. The root ("/") path would return a dictionary
- with all keys and values. The path "/path1" would only
- return the dictionary with the "key3" and "key4" properties.
-
- <PRE>
- <BR> <dict>
- <BR> <key>key1</key>
- <BR> <string>val1</string>
- <BR> <key>key2</key>
- <BR> <string>val2</string>
- <BR> <key>path1</key>
- <BR> <dict>
- <BR> <key>key3</key>
- <BR> <string>val3</string>
- <BR> <key>key4</key>
- <BR> <string>val4</string>
- <BR> </dict>
- <BR> </dict>
- </PRE>
-
- Each dictionary can also include the kSCResvLink key. The
- value associated with this key is interpreted as a "link" to
+ @discussion The SCPreferencesPath API allows an application to
+ load and store XML configuration data in a controlled
+ manner and provide the necessary notifications to other
+ applications that need to be aware of configuration
+ changes.
+
+ The functions in the SCPreferencesPath API make certain
+ assumptions about the layout of the preferences data.
+ These functions view the data as a collection of dictionaries
+ of key-value pairs and an associated path name.
+ The root path ("/") identifies the top-level dictionary.
+ Additional path components specify the keys for subdictionaries.
+
+ For example, the following dictionary can be accessed via
+ two paths. The root ("/") path would return a dictionary
+ with all keys and values. The path "/path1" would only
+ return the dictionary with the "key3" and "key4" properties.
+
+ <pre>
+ @textblock
+ <dict>
+ <key>key1</key>
+ <string>val1</string>
+ <key>key2</key>
+ <string>val2</string>
+ <key>path1</key>
+ <dict>
+ <key>key3</key>
+ <string>val3</string>
+ <key>key4</key>
+ <string>val4</string>
+ </dict>
+ </dict>
+ @/textblock
+ </pre>
+
+ Each dictionary can also include the kSCResvLink ("__LINK__") key.
+ The value associated with this key is interpreted as a link to
another path. If this key is present, a call to the
- SCPreferencesPathGetValue() API will return the dictionary
+ SCPreferencesPathGetValue function returns the dictionary
specified by the link.
*/
@function SCPreferencesPathCreateUniqueChild
@discussion Creates a new path component within the dictionary
hierarchy.
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ @param prefs The preferences session.
@param prefix A string that represents the parent path.
- @result A string representing the new (unique) child path; NULL
+ @result Returns a string representing the new (unique) child path; NULL
if the specified path does not exist.
*/
CFStringRef
SCPreferencesPathCreateUniqueChild (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef prefix
);
@function SCPreferencesPathGetValue
@discussion Returns the dictionary associated with the specified
path.
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ @param prefs The preferences session.
@param path A string that represents the path to be returned.
- @result The dictionary associated with the specified path; NULL
+ @result Returns the dictionary associated with the specified path; NULL
if the path does not exist.
*/
CFDictionaryRef
SCPreferencesPathGetValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef path
);
@function SCPreferencesPathGetLink
@discussion Returns the link (if one exists) associated with the
specified path.
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ @param prefs The preferences session.
@param path A string that represents the path to be returned.
- @result The dictionary associated with the specified path; NULL
+ @result Returns the dictionary associated with the specified path; NULL
if the path is not a link or does not exist.
*/
CFStringRef
SCPreferencesPathGetLink (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef path
);
/*!
@function SCPreferencesPathSetValue
@discussion Associates a dictionary with the specified path.
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ @param prefs The preferences session.
@param path A string that represents the path to be updated.
@param value A dictionary that represents the data to be
stored at the specified path.
- @result A boolean indicating the success (or failure) of the call.
+ @result Returns TRUE if successful; FALSE otherwise.
*/
Boolean
SCPreferencesPathSetValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef path,
CFDictionaryRef value
);
@function SCPreferencesPathSetLink
@discussion Associates a link to a second dictionary at the
specified path.
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ @param prefs The preferences session.
@param path A string that represents the path to be updated.
@param link A string that represents the link to be stored
at the specified path.
- @result A boolean indicating the success (or failure) of the call.
+ @result Returns TRUE if successful; FALSE otherwise.
*/
Boolean
SCPreferencesPathSetLink (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef path,
CFStringRef link
);
/*!
@function SCPreferencesPathRemoveValue
@discussion Removes the data associated with the specified path.
- @param session The SCPreferencesRef handle that should be used to
- communicate with the APIs.
+ @param prefs The preferences session.
@param path A string that represents the path to be returned.
- @result A boolean indicating the success (or failure) of the call.
+ @result Returns TRUE if successful; FALSE otherwise.
*/
Boolean
SCPreferencesPathRemoveValue (
- SCPreferencesRef session,
+ SCPreferencesRef prefs,
CFStringRef path
);
--- /dev/null
+/*
+ * Copyright (c) 2001-2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * October 29, 2001 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <SystemConfiguration/SystemConfiguration.h>
+
+#include <stdarg.h>
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreate(CFAllocatorRef allocator,
+ CFStringRef fmt,
+ ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ return (CFStringCreateWithFormatAndArguments(allocator,
+ NULL,
+ fmt,
+ args));
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateNetworkServices(CFAllocatorRef allocator)
+{
+ /*
+ * create "/NetworkServices"
+ */
+ return CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@"),
+ kSCPrefNetworkServices);
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateNetworkServiceEntity(CFAllocatorRef allocator,
+ CFStringRef service,
+ CFStringRef entity)
+{
+ CFStringRef path;
+
+ if (entity == NULL) {
+ /*
+ * create "/NetworkServices/service-id"
+ */
+ path = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@"),
+ kSCPrefNetworkServices,
+ service);
+ } else {
+ /*
+ * create "/NetworkServices/service-id/entity"
+ */
+ path = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@"),
+ kSCPrefNetworkServices,
+ service,
+ entity);
+ }
+
+ return path;
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSets(CFAllocatorRef allocator)
+{
+ /*
+ * create "/Sets"
+ */
+ return (CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@"),
+ kSCPrefSets));
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSet(CFAllocatorRef allocator,
+ CFStringRef set)
+{
+ /*
+ * create "/Sets/set-id"
+ */
+ return (CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@"),
+ kSCPrefSets,
+ set));
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkGlobalEntity(CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef entity)
+{
+ /*
+ * create "/Sets/set-id/Network/Global/entity"
+ */
+ return CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@/%@/%@"),
+ kSCPrefSets,
+ set,
+ kSCCompNetwork,
+ kSCCompGlobal,
+ entity);
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef ifname,
+ CFStringRef entity)
+{
+ /*
+ * create "/Sets/set-id/Network/Interface/interface-name/entity"
+ */
+ return CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@/%@/%@/%@"),
+ kSCPrefSets,
+ set,
+ kSCCompNetwork,
+ kSCCompInterface,
+ ifname,
+ entity);
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkService(CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef service)
+{
+ CFStringRef path;
+
+ if (service == NULL) {
+ /*
+ * create "/Sets/set-id/Network/Service"
+ */
+ path = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@/%@"),
+ kSCPrefSets,
+ set,
+ kSCCompNetwork,
+ kSCCompService);
+ } else {
+ /*
+ * create "/Sets/set-id/Network/Service/service-id"
+ */
+ path = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@/%@/%@"),
+ kSCPrefSets,
+ set,
+ kSCCompNetwork,
+ kSCCompService,
+ service);
+ }
+
+ return path;
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkServiceEntity(CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef service,
+ CFStringRef entity)
+{
+ CFStringRef path;
+
+ if (entity == NULL) {
+ /*
+ * create "/Sets/set-id/Network/Service/service-id"
+ */
+ path = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@/%@/%@"),
+ kSCPrefSets,
+ set,
+ kSCCompNetwork,
+ kSCCompService,
+ service);
+ } else {
+ /*
+ * create "/Sets/set-id/Network/Service/service-id/entity"
+ */
+ path = CFStringCreateWithFormat(allocator,
+ NULL,
+ CFSTR("/%@/%@/%@/%@/%@/%@"),
+ kSCPrefSets,
+ set,
+ kSCCompNetwork,
+ kSCCompService,
+ service,
+ entity);
+ }
+
+ return path;
+}
--- /dev/null
+/*
+ * Copyright (c) 2001-2004 Apple Computer, 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@
+ */
+
+#ifndef _SCPREFERENCESPATHKEY_H
+#define _SCPREFERENCESPATHKEY_H
+
+#include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+
+/*!
+ @header SCPreferencesPathKey
+ */
+
+
+__BEGIN_DECLS
+
+/*
+ * SCPreferencesPathKeyCreate*
+ * - convenience routines that create a CFString key for an item in the store
+ */
+
+/*!
+ @function SCPreferencesPathKeyCreate
+ @discussion Creates a preferences path key using the given format.
+ */
+CFStringRef
+SCPreferencesPathKeyCreate (
+ CFAllocatorRef allocator,
+ CFStringRef fmt,
+ ...
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateNetworkServices
+ */
+CFStringRef
+SCPreferencesPathKeyCreateNetworkServices (
+ CFAllocatorRef allocator
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateNetworkServiceEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateNetworkServiceEntity (
+ CFAllocatorRef allocator,
+ CFStringRef service,
+ CFStringRef entity
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateSets
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSets (
+ CFAllocatorRef allocator
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateSet
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSet (
+ CFAllocatorRef allocator,
+ CFStringRef set
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateSetNetworkInterfaceEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(
+ CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef ifname,
+ CFStringRef entity
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateSetNetworkGlobalEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkGlobalEntity(
+ CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef entity
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateSetNetworkService
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkService (
+ CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef service
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+ @function SCPreferencesPathKeyCreateSetNetworkServiceEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkServiceEntity(
+ CFAllocatorRef allocator,
+ CFStringRef set,
+ CFStringRef service,
+ CFStringRef entity
+ ) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+__END_DECLS
+
+#endif /* _SCPREFERENCESPATHKEY_H */
#ifndef _SCPREFERENCESPRIVATE_H
#define _SCPREFERENCESPRIVATE_H
+
+#include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCPreferences.h>
+/*!
+ @header SCPreferencesPrivate
+ */
+
/*!
@enum SCPreferencesKeyType
@discussion Used with the SCDynamicStoreKeyCreatePreferences() function
};
typedef int32_t SCPreferencesKeyType;
+
__BEGIN_DECLS
/*!
CFAllocatorRef allocator,
CFStringRef prefsID,
SCPreferencesKeyType keyType
- );
+ ) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
SCPreferencesRef
SCUserPreferencesCreate (
/*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*!
@header SCPreferencesSetSpecific
- The following APIs allow an application to set specific
- configuration information about the current system (e.g. the
- computer/sharing name).
+ @discussion The functions in the SCPreferencesSetSpecific API allow
+ an application to set specific configuration information
+ about the current system (for example, the computer or
+ sharing name).
+
+ To access configuration preferences, you must first establish
+ a preferences session using the SCPreferencesCreate function.
*/
/*!
@function SCPreferencesSetComputerName
- @discussion Updates the computer/host name in the system preferences.
+ @discussion Updates the computer name preference.
- Note: In order to commit these changes to permanent storage a call
- must be made to SCPreferencesCommitChanges().
- A call to SCPreferencesApplyChanges() is also required for the new
- name to become active.
- @param prefs An SCPreferencesRef that should be used for all API calls.
- @param name The computer/host name to be set.
- @param nameEncoding The encoding associated with the computer/host name.
- @result A boolean indicating the success (or failure) of the call.
+ Note: To commit these changes to permanent storage you must
+ call the SCPreferencesCommitChanges function.
+ In addition, you must call the SCPreferencesApplyChanges
+ function for the new name to become active.
+ @param prefs The preferences session.
+ @param name The computer name to be set.
+ @param nameEncoding The encoding associated with the computer name.
+ @result Returns TRUE if successful; FALSE otherwise.
*/
Boolean
SCPreferencesSetComputerName (
/*!
@function SCPreferencesSetLocalHostName
- @discussion Updates the local host name in the system preferences.
+ @discussion Updates the local host name.
- Note: In order to commit these changes to permanent storage a call
- must be made to SCPreferencesCommitChanges().
- A call to SCPreferencesApplyChanges() is also required for the new
- name to become active.
- @param prefs An SCPreferencesRef that should be used for all API calls.
+ Note: To commit these changes to permanent storage you must
+ call the SCPreferencesCommitChanges function.
+ In addition, you must call theSCPreferencesApplyChanges
+ function for the new name to become active.
+ @param prefs The preferences session.
@param name The local host name to be set.
- Note: the string must conform to the naming conventions of a DNS host
+ Note: this string must conform to the naming conventions of a DNS host
name as specified in RFC 1034 (section 3.5).
- @result A boolean indicating the success (or failure) of the call.
+ @result Returns TRUE if successful; FALSE otherwise.
*/
Boolean
SCPreferencesSetLocalHostName (
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, 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@
+ */
+
+#ifndef _SCPREFERENCESSETSPECIFICPRIVATE_H
+#define _SCPREFERENCESSETSPECIFICPRIVATE_H
+
+#include <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPreferences.h>
+
+
+/*!
+ @header SCPreferencesSetSpecificPrivate
+ @discussion The functions in the SCPreferencesSetSpecificPrivate API allow
+ an application to set specific configuration information
+ about the current system (for example, the computer or
+ sharing name).
+
+ To access configuration preferences, you must first establish
+ a preferences session using the SCPreferencesCreate function.
+ */
+
+
+__BEGIN_DECLS
+
+/*!
+ @function SCPreferencesSetHostName
+ @discussion Updates the host name preference.
+
+ Note: To commit these changes to permanent storage you must
+ call the SCPreferencesCommitChanges function.
+ In addition, you must call the SCPreferencesApplyChanges
+ function for the new name to become active.
+ @param prefs The preferences session.
+ @param name The host name to be set.
+ @result Returns TRUE if successful; FALSE otherwise.
+ */
+Boolean
+SCPreferencesSetHostName (
+ SCPreferencesRef prefs,
+ CFStringRef name
+ );
+
+__END_DECLS
+
+#endif /* _SCPREFERENCESSETSPECIFICPRIVATE_H */
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#define _SCPRIVATE_H
#include <sys/cdefs.h>
+#include <sys/syslog.h>
+#include <mach/message.h>
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SCDynamicStoreSetSpecificPrivate.h>
#include <SystemConfiguration/SCPreferencesPrivate.h>
+#include <SystemConfiguration/SCPreferencesGetSpecificPrivate.h>
+#include <SystemConfiguration/SCPreferencesSetSpecificPrivate.h>
+
+/*!
+ @header SCPrivate
+ */
/* framework variables */
extern Boolean _sc_debug; /* TRUE if debugging enabled */
/*!
@function _SCErrorSet
- @discussion Returns a last SystemConfiguration.framework API error code.
- @result The last error encountered.
+ @discussion Sets the last SystemConfiguration.framework API error code.
+ @param error The error encountered.
*/
void _SCErrorSet (int error);
-/*
+/*!
@function _SCSerialize
@discussion Serialize a CFPropertyList object for passing
to/from configd.
@param obj CFPropertyList object to serialize
@param xml A pointer to a CFDataRef, NULL if data should be
vm_allocated.
- @param data A pointer to the newly allocated/serialized data
+ @param dataRef A pointer to the newly allocated/serialized data
@param dataLen A pointer to the length in bytes of the newly
allocated/serialized data
*/
void **dataRef,
CFIndex *dataLen);
-/*
+/*!
@function _SCUnserialize
@discussion Unserialize a stream of bytes passed from/to configd
into a CFPropertyList object.
@param obj A pointer to memory that will be filled with the CFPropertyList
associated with the stream of bytes.
@param xml CFDataRef with the serialized data
- @param data A pointer to the serialized data
+ @param dataRef A pointer to the serialized data
@param dataLen A pointer to the length of the serialized data
Specify either "xml" or "data/dataLen".
void *dataRef,
CFIndex dataLen);
-/*
+/*!
@function _SCSerializeString
@discussion Serialize a CFString object for passing
to/from configd.
@param str CFString key to serialize
@param data A pointer to a CFDataRef, NULL if storage should be
vm_allocated.
- @param data A pointer to the newly allocated/serialized data
+ @param dataRef A pointer to the newly allocated/serialized data
@param dataLen A pointer to the length in bytes of the newly
allocated/serialized data
*/
void **dataRef,
CFIndex *dataLen);
-/*
+/*!
@function _SCUnserializeString
@discussion Unserialize a stream of bytes passed from/to configd
into a CFString object.
@param str A pointer to memory that will be filled with the CFPropertyList
associated with the stream of bytes.
@param utf8 CFDataRef with the serialized data
- @param data A pointer to the serialized data
+ @param dataRef A pointer to the serialized data
@param dataLen A pointer to the length of the serialized data
Specify either "utf8" or "data/dataLen".
void *dataRef,
CFIndex dataLen);
-/*
+/*!
@function _SCSerializeData
@discussion Serialize a CFData object for passing
to/from configd.
@param data CFData key to serialize
- @param data A pointer to the newly allocated/serialized data
+ @param dataRef A pointer to the newly allocated/serialized data
@param dataLen A pointer to the length in bytes of the newly
allocated/serialized data
*/
void **dataRef,
CFIndex *dataLen);
-/*
+/*!
@function _SCUnserializeData
@discussion Unserialize a stream of bytes passed from/to configd
into a CFData object.
@param data A pointer to memory that will be filled with the CFPropertyList
associated with the stream of bytes.
- @param data A pointer to the serialized data
+ @param dataRef A pointer to the serialized data
@param dataLen A pointer to the length of the serialized data
*/
Boolean _SCUnserializeData (CFDataRef *data,
void *dataRef,
CFIndex dataLen);
-/*
+/*!
@function _SCSerializeMultiple
@discussion Convert a CFDictionary containing a set of CFPropertlyList
values into a CFDictionary containing a set of serialized CFData
*/
CFDictionaryRef _SCSerializeMultiple (CFDictionaryRef dict);
-/*
+/*!
@function _SCUnserializeMultiple
@discussion Convert a CFDictionary containing a set of CFData
values into a CFDictionary containing a set of serialized
*/
CFDictionaryRef _SCUnserializeMultiple (CFDictionaryRef dict);
-/*
+/*!
@function _SC_cfstring_to_cstring
@discussion Extracts a C-string from a CFString.
@param cfstr The CFString to extract the data from.
- @param buf A user provided buffer of the specefied length. If NULL,
+ @param buf A user provided buffer of the specified length. If NULL,
a new buffer will be allocated to contain the C-string. It
is the responsiblity of the caller to free an allocated
buffer.
int bufLen,
CFStringEncoding encoding);
-/*
+/*!
+ * @function _SC_sockaddr_to_string
+ * @discussion Formats a "struct sockaddr" for reporting
+ * @param address The address to format
+ * @param buf A user provided buffer of the specified length.
+ * @param bufLen The size of the user provided buffer.
+ */
+void _SC_sockaddr_to_string (const struct sockaddr *address,
+ char *buf,
+ size_t bufLen);
+
+/*!
@function SCLog
@discussion Conditionally issue a log message.
@param condition A boolean value indicating if the message should be logged
CFStringRef formatString,
...);
-/*
+/*!
@function SCPrint
@discussion Conditionally issue a debug message.
@param condition A boolean value indicating if the message should be written
CFStringRef formatString,
...);
-/*
+/*!
@function SCTrace
@discussion Conditionally issue a debug message with a time stamp.
@param condition A boolean value indicating if the message should be written
CFStringRef formatString,
...);
+/*
+ * object / CFRunLoop management
+ */
+void
+_SC_signalRunLoop (CFTypeRef obj,
+ CFRunLoopSourceRef rls,
+ CFArrayRef rlList);
+
+Boolean
+_SC_isScheduled (CFTypeRef obj,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode,
+ CFMutableArrayRef rlList);
+
+void
+_SC_schedule (CFTypeRef obj,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode,
+ CFMutableArrayRef rlList);
+
+Boolean
+_SC_unschedule (CFTypeRef obj,
+ CFRunLoopRef runLoop,
+ CFStringRef runLoopMode,
+ CFMutableArrayRef rlList,
+ Boolean all);
+
__END_DECLS
#endif /* _SCPRIVATE_H */
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCPrivate.h>
+#include <netdb.h>
+
+
CFStringRef
SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator)
{
}
+static void
+validate_proxy_content(CFMutableDictionaryRef proxies,
+ CFStringRef proxy_enable,
+ CFStringRef proxy_host,
+ CFStringRef proxy_port,
+ const char * proxy_service,
+ int proxy_defaultport)
+{
+ int enabled = 0;
+ CFNumberRef num;
+ CFStringRef host;
+ CFNumberRef port = NULL;
+
+ num = CFDictionaryGetValue(proxies, proxy_enable);
+ if (num != NULL) {
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
+ // if we don't like the enabled key/value
+ goto disable;
+ }
+ }
+
+ host = CFDictionaryGetValue(proxies, proxy_host);
+ if (((enabled == 0) && (host != NULL)) ||
+ ((enabled != 0) && !isA_CFString(host))) {
+ // pass only valid proxy hosts and only when enabled
+ goto disable;
+ }
+
+ if (proxy_port != NULL) {
+ port = CFDictionaryGetValue(proxies, proxy_port);
+ if (((enabled == 0) && (port != NULL)) ||
+ ((enabled != 0) && (port != NULL) && !isA_CFNumber(port))) {
+ // pass only provided/valid proxy ports and only when enabled
+ goto disable;
+ }
+
+ if ((enabled != 0) && (port == NULL)) {
+ struct servent *service;
+
+ service = getservbyname(proxy_service, "tcp");
+ num = CFNumberCreate(NULL,
+ kCFNumberIntType,
+ (service != NULL) ? &service->s_port : &proxy_defaultport);
+ CFDictionarySetValue(proxies, proxy_port, num);
+ CFRelease(num);
+ }
+ }
+
+ return;
+
+ disable :
+
+ enabled = 0;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
+ CFDictionarySetValue(proxies, proxy_enable, num);
+ CFRelease(num);
+ CFDictionaryRemoveValue(proxies, proxy_host);
+ if (proxy_port != NULL) {
+ CFDictionaryRemoveValue(proxies, proxy_port);
+ }
+
+ return;
+}
+
+
CFDictionaryRef
SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
{
- CFDictionaryRef dict = NULL;
+ CFArrayRef array;
CFStringRef key;
- CFDictionaryRef proxies = NULL;
+ CFMutableDictionaryRef newProxies = NULL;
+ CFNumberRef num;
+ CFDictionaryRef proxies;
Boolean tempSession = FALSE;
- if (!store) {
+
+
+ /* copy proxy information from dynamic store */
+
+ if (store == NULL) {
store = SCDynamicStoreCreate(NULL,
CFSTR("SCDynamicStoreCopyProxies"),
NULL,
NULL);
- if (!store) {
- SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+ if (store == NULL) {
return NULL;
}
tempSession = TRUE;
}
- key = SCDynamicStoreKeyCreateProxies(NULL);
- dict = SCDynamicStoreCopyValue(store, key);
+ key = SCDynamicStoreKeyCreateProxies(NULL);
+ proxies = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
- if (!isA_CFDictionary(dict)) {
- _SCErrorSet(kSCStatusNoKey);
- goto done;
+
+ validate :
+
+ if (proxies != NULL) {
+ if (isA_CFDictionary(proxies)) {
+ newProxies = CFDictionaryCreateMutableCopy(NULL, 0, proxies);
+ }
+ CFRelease(proxies);
+ }
+
+ if (newProxies == NULL) {
+ newProxies = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
}
- proxies = CFRetain(dict);
+ /* validate [and augment] proxy content */
+
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesFTPEnable,
+ kSCPropNetProxiesFTPProxy,
+ kSCPropNetProxiesFTPPort,
+ "ftp",
+ 21);
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesGopherEnable,
+ kSCPropNetProxiesGopherProxy,
+ kSCPropNetProxiesGopherPort,
+ "gopher",
+ 70);
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesHTTPEnable,
+ kSCPropNetProxiesHTTPProxy,
+ kSCPropNetProxiesHTTPPort,
+ "http",
+ 80);
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesHTTPSEnable,
+ kSCPropNetProxiesHTTPSProxy,
+ kSCPropNetProxiesHTTPSPort,
+ "https",
+ 443);
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesRTSPEnable,
+ kSCPropNetProxiesRTSPProxy,
+ kSCPropNetProxiesRTSPPort,
+ "rtsp",
+ 554);
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesSOCKSEnable,
+ kSCPropNetProxiesSOCKSProxy,
+ kSCPropNetProxiesSOCKSPort,
+ "socks",
+ 1080);
+ validate_proxy_content(newProxies,
+ kSCPropNetProxiesProxyAutoConfigEnable,
+ kSCPropNetProxiesProxyAutoConfigURLString,
+ NULL,
+ NULL,
+ 0);
+
+ // validate WPAD setting
+ num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesProxyAutoDiscoveryEnable);
+ if (num != NULL) {
+ int enabled;
+
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
+ // if we don't like the enabled key/value
+ enabled = 0;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
+ CFDictionarySetValue(newProxies,
+ kSCPropNetProxiesProxyAutoDiscoveryEnable,
+ num);
+ CFRelease(num);
+ }
+ }
+
+ // validate proxy exception list
+ array = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExceptionsList);
+ if (array != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ n = isA_CFArray(array) ? CFArrayGetCount(array) : 0;
+ for (i = 0; i < n; i++) {
+ CFStringRef str;
+
+ str = CFArrayGetValueAtIndex(array, i);
+ if (!isA_CFString(str)) {
+ // if we don't like the array contents
+ n = 0;
+ break;
+ }
+ }
+
+ if (n == 0) {
+ CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesExceptionsList);
+ }
+ }
+
+ // validate exclude simple hostnames setting
+ num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExcludeSimpleHostnames);
+ if (num != NULL) {
+ int enabled;
+
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
+ // if we don't like the enabled key/value
+ enabled = 0;
+ num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
+ CFDictionarySetValue(newProxies,
+ kSCPropNetProxiesExcludeSimpleHostnames,
+ num);
+ CFRelease(num);
+ }
+ }
- done :
+ proxies = CFDictionaryCreateCopy(NULL, newProxies);
+ CFRelease(newProxies);
if (tempSession) CFRelease(store);
- if (dict) CFRelease(dict);
return proxies;
}
--- /dev/null
+/*
+ * This file is automatically generated
+ * DO NOT EDIT!
+ */
+
+#include <CoreFoundation/CFString.h>
+
+const CFStringRef kSCResvLink = CFSTR("__LINK__");
+const CFStringRef kSCResvInactive = CFSTR("__INACTIVE__");
+const CFStringRef kSCPropInterfaceName = CFSTR("InterfaceName");
+const CFStringRef kSCPropMACAddress = CFSTR("MACAddress");
+const CFStringRef kSCPropUserDefinedName = CFSTR("UserDefinedName");
+const CFStringRef kSCPropVersion = CFSTR("Version");
+const CFStringRef kSCPrefCurrentSet = CFSTR("CurrentSet");
+const CFStringRef kSCPrefNetworkServices = CFSTR("NetworkServices");
+const CFStringRef kSCPrefSets = CFSTR("Sets");
+const CFStringRef kSCPrefSystem = CFSTR("System");
+const CFStringRef kSCCompNetwork = CFSTR("Network");
+const CFStringRef kSCCompService = CFSTR("Service");
+const CFStringRef kSCCompGlobal = CFSTR("Global");
+const CFStringRef kSCCompHostNames = CFSTR("HostNames");
+const CFStringRef kSCCompInterface = CFSTR("Interface");
+const CFStringRef kSCCompSystem = CFSTR("System");
+const CFStringRef kSCCompUsers = CFSTR("Users");
+const CFStringRef kSCCompAnyRegex = CFSTR("[^/]+");
+const CFStringRef kSCEntNetAirPort = CFSTR("AirPort");
+const CFStringRef kSCEntNetAppleTalk = CFSTR("AppleTalk");
+const CFStringRef kSCEntNetDHCP = CFSTR("DHCP");
+const CFStringRef kSCEntNetDNS = CFSTR("DNS");
+const CFStringRef kSCEntNetEthernet = CFSTR("Ethernet");
+const CFStringRef kSCEntNetFireWire = CFSTR("FireWire");
+const CFStringRef kSCEntNetInterface = CFSTR("Interface");
+const CFStringRef kSCEntNetIPv4 = CFSTR("IPv4");
+const CFStringRef kSCEntNetIPv6 = CFSTR("IPv6");
+const CFStringRef kSCEntNetL2TP = CFSTR("L2TP");
+const CFStringRef kSCEntNetLink = CFSTR("Link");
+const CFStringRef kSCEntNetModem = CFSTR("Modem");
+const CFStringRef kSCEntNetNetInfo = CFSTR("NetInfo");
+const CFStringRef kSCEntNetPPP = CFSTR("PPP");
+const CFStringRef kSCEntNetPPPoE = CFSTR("PPPoE");
+const CFStringRef kSCEntNetPPPSerial = CFSTR("PPPSerial");
+const CFStringRef kSCEntNetPPTP = CFSTR("PPTP");
+const CFStringRef kSCEntNetProxies = CFSTR("Proxies");
+const CFStringRef kSCEntNet6to4 = CFSTR("6to4");
+const CFStringRef kSCPropNetOverridePrimary = CFSTR("OverridePrimary");
+const CFStringRef kSCPropNetServiceOrder = CFSTR("ServiceOrder");
+const CFStringRef kSCPropNetPPPOverridePrimary = CFSTR("PPPOverridePrimary");
+const CFStringRef kSCPropNetInterfaces = CFSTR("Interfaces");
+const CFStringRef kSCPropNetLocalHostName = CFSTR("LocalHostName");
+const CFStringRef kSCPropNetAirPortAllowNetCreation = CFSTR("AllowNetCreation");
+const CFStringRef kSCPropNetAirPortAuthPassword = CFSTR("AuthPassword");
+const CFStringRef kSCPropNetAirPortAuthPasswordEncryption = CFSTR("AuthPasswordEncryption");
+const CFStringRef kSCPropNetAirPortJoinMode = CFSTR("JoinMode");
+const CFStringRef kSCPropNetAirPortPowerEnabled = CFSTR("PowerEnabled");
+const CFStringRef kSCPropNetAirPortPreferredNetwork = CFSTR("PreferredNetwork");
+const CFStringRef kSCPropNetAirPortSavePasswords = CFSTR("SavePasswords");
+const CFStringRef kSCValNetAirPortJoinModeAutomatic = CFSTR("Automatic");
+const CFStringRef kSCValNetAirPortJoinModePreferred = CFSTR("Preferred");
+const CFStringRef kSCValNetAirPortJoinModeRecent = CFSTR("Recent");
+const CFStringRef kSCValNetAirPortJoinModeStrongest = CFSTR("Strongest");
+const CFStringRef kSCValNetAirPortAuthPasswordEncryptionKeychain = CFSTR("Keychain");
+const CFStringRef kSCPropNetAppleTalkComputerName = CFSTR("ComputerName");
+const CFStringRef kSCPropNetAppleTalkComputerNameEncoding = CFSTR("ComputerNameEncoding");
+const CFStringRef kSCPropNetAppleTalkConfigMethod = CFSTR("ConfigMethod");
+const CFStringRef kSCPropNetAppleTalkDefaultZone = CFSTR("DefaultZone");
+const CFStringRef kSCPropNetAppleTalkNetworkID = CFSTR("NetworkID");
+const CFStringRef kSCPropNetAppleTalkNetworkRange = CFSTR("NetworkRange");
+const CFStringRef kSCPropNetAppleTalkNodeID = CFSTR("NodeID");
+const CFStringRef kSCPropNetAppleTalkSeedNetworkRange = CFSTR("SeedNetworkRange");
+const CFStringRef kSCPropNetAppleTalkSeedZones = CFSTR("SeedZones");
+const CFStringRef kSCValNetAppleTalkConfigMethodNode = CFSTR("Node");
+const CFStringRef kSCValNetAppleTalkConfigMethodRouter = CFSTR("Router");
+const CFStringRef kSCValNetAppleTalkConfigMethodSeedRouter = CFSTR("SeedRouter");
+const CFStringRef kSCPropNetDNSDomainName = CFSTR("DomainName");
+const CFStringRef kSCPropNetDNSOptions = CFSTR("Options");
+const CFStringRef kSCPropNetDNSSearchDomains = CFSTR("SearchDomains");
+const CFStringRef kSCPropNetDNSSearchOrder = CFSTR("SearchOrder");
+const CFStringRef kSCPropNetDNSServerAddresses = CFSTR("ServerAddresses");
+const CFStringRef kSCPropNetDNSServerPort = CFSTR("ServerPort");
+const CFStringRef kSCPropNetDNSServerTimeout = CFSTR("ServerTimeout");
+const CFStringRef kSCPropNetDNSSortList = CFSTR("SortList");
+const CFStringRef kSCPropNetDNSSupplementalMatchDomains = CFSTR("SupplementalMatchDomains");
+const CFStringRef kSCPropNetDNSSupplementalMatchOrders = CFSTR("SupplementalMatchOrders");
+const CFStringRef kSCPropNetEthernetMediaSubType = CFSTR("MediaSubType");
+const CFStringRef kSCPropNetEthernetMediaOptions = CFSTR("MediaOptions");
+const CFStringRef kSCPropNetEthernetMTU = CFSTR("MTU");
+const CFStringRef kSCPropNetInterfaceDeviceName = CFSTR("DeviceName");
+const CFStringRef kSCPropNetInterfaceHardware = CFSTR("Hardware");
+const CFStringRef kSCPropNetInterfaceType = CFSTR("Type");
+const CFStringRef kSCPropNetInterfaceSubType = CFSTR("SubType");
+const CFStringRef kSCPropNetInterfaceSupportsModemOnHold = CFSTR("SupportsModemOnHold");
+const CFStringRef kSCValNetInterfaceTypeEthernet = CFSTR("Ethernet");
+const CFStringRef kSCValNetInterfaceTypeFireWire = CFSTR("FireWire");
+const CFStringRef kSCValNetInterfaceTypePPP = CFSTR("PPP");
+const CFStringRef kSCValNetInterfaceType6to4 = CFSTR("6to4");
+const CFStringRef kSCValNetInterfaceSubTypePPPoE = CFSTR("PPPoE");
+const CFStringRef kSCValNetInterfaceSubTypePPPSerial = CFSTR("PPPSerial");
+const CFStringRef kSCValNetInterfaceSubTypePPTP = CFSTR("PPTP");
+const CFStringRef kSCValNetInterfaceSubTypeL2TP = CFSTR("L2TP");
+const CFStringRef kSCPropNetIPv4Addresses = CFSTR("Addresses");
+const CFStringRef kSCPropNetIPv4ConfigMethod = CFSTR("ConfigMethod");
+const CFStringRef kSCPropNetIPv4DHCPClientID = CFSTR("DHCPClientID");
+const CFStringRef kSCPropNetIPv4Router = CFSTR("Router");
+const CFStringRef kSCPropNetIPv4SubnetMasks = CFSTR("SubnetMasks");
+const CFStringRef kSCPropNetIPv4DestAddresses = CFSTR("DestAddresses");
+const CFStringRef kSCPropNetIPv4BroadcastAddresses = CFSTR("BroadcastAddresses");
+const CFStringRef kSCValNetIPv4ConfigMethodBOOTP = CFSTR("BOOTP");
+const CFStringRef kSCValNetIPv4ConfigMethodDHCP = CFSTR("DHCP");
+const CFStringRef kSCValNetIPv4ConfigMethodINFORM = CFSTR("INFORM");
+const CFStringRef kSCValNetIPv4ConfigMethodLinkLocal = CFSTR("LinkLocal");
+const CFStringRef kSCValNetIPv4ConfigMethodManual = CFSTR("Manual");
+const CFStringRef kSCValNetIPv4ConfigMethodPPP = CFSTR("PPP");
+const CFStringRef kSCPropNetIPv6Addresses = CFSTR("Addresses");
+const CFStringRef kSCPropNetIPv6ConfigMethod = CFSTR("ConfigMethod");
+const CFStringRef kSCPropNetIPv6DestAddresses = CFSTR("DestAddresses");
+const CFStringRef kSCPropNetIPv6Flags = CFSTR("Flags");
+const CFStringRef kSCPropNetIPv6PrefixLength = CFSTR("PrefixLength");
+const CFStringRef kSCPropNetIPv6Router = CFSTR("Router");
+const CFStringRef kSCValNetIPv6ConfigMethodAutomatic = CFSTR("Automatic");
+const CFStringRef kSCValNetIPv6ConfigMethodManual = CFSTR("Manual");
+const CFStringRef kSCValNetIPv6ConfigMethodRouterAdvertisement = CFSTR("RouterAdvertisement");
+const CFStringRef kSCValNetIPv6ConfigMethod6to4 = CFSTR("6to4");
+const CFStringRef kSCPropNet6to4Relay = CFSTR("Relay");
+const CFStringRef kSCPropNetLinkActive = CFSTR("Active");
+const CFStringRef kSCPropNetLinkDetaching = CFSTR("Detaching");
+const CFStringRef kSCPropNetModemConnectionScript = CFSTR("ConnectionScript");
+const CFStringRef kSCPropNetModemConnectSpeed = CFSTR("ConnectSpeed");
+const CFStringRef kSCPropNetModemDataCompression = CFSTR("DataCompression");
+const CFStringRef kSCPropNetModemDialMode = CFSTR("DialMode");
+const CFStringRef kSCPropNetModemErrorCorrection = CFSTR("ErrorCorrection");
+const CFStringRef kSCPropNetModemHoldCallWaitingAudibleAlert = CFSTR("HoldCallWaitingAudibleAlert");
+const CFStringRef kSCPropNetModemHoldDisconnectOnAnswer = CFSTR("HoldDisconnectOnAnswer");
+const CFStringRef kSCPropNetModemHoldEnabled = CFSTR("HoldEnabled");
+const CFStringRef kSCPropNetModemHoldReminder = CFSTR("HoldReminder");
+const CFStringRef kSCPropNetModemHoldReminderTime = CFSTR("HoldReminderTime");
+const CFStringRef kSCPropNetModemNote = CFSTR("Note");
+const CFStringRef kSCPropNetModemPulseDial = CFSTR("PulseDial");
+const CFStringRef kSCPropNetModemSpeaker = CFSTR("Speaker");
+const CFStringRef kSCPropNetModemSpeed = CFSTR("Speed");
+const CFStringRef kSCValNetModemDialModeIgnoreDialTone = CFSTR("IgnoreDialTone");
+const CFStringRef kSCValNetModemDialModeManual = CFSTR("Manual");
+const CFStringRef kSCValNetModemDialModeWaitForDialTone = CFSTR("WaitForDialTone");
+const CFStringRef kSCPropNetNetInfoBindingMethods = CFSTR("BindingMethods");
+const CFStringRef kSCPropNetNetInfoServerAddresses = CFSTR("ServerAddresses");
+const CFStringRef kSCPropNetNetInfoServerTags = CFSTR("ServerTags");
+const CFStringRef kSCPropNetNetInfoBroadcastServerTag = CFSTR("BroadcastServerTag");
+const CFStringRef kSCValNetNetInfoBindingMethodsBroadcast = CFSTR("Broadcast");
+const CFStringRef kSCValNetNetInfoBindingMethodsDHCP = CFSTR("DHCP");
+const CFStringRef kSCValNetNetInfoBindingMethodsManual = CFSTR("Manual");
+const CFStringRef kSCValNetNetInfoDefaultServerTag = CFSTR("network");
+const CFStringRef kSCPropNetPPPACSPEnabled = CFSTR("ACSPEnabled");
+const CFStringRef kSCPropNetPPPConnectTime = CFSTR("ConnectTime");
+const CFStringRef kSCPropNetPPPDeviceLastCause = CFSTR("DeviceLastCause");
+const CFStringRef kSCPropNetPPPDialOnDemand = CFSTR("DialOnDemand");
+const CFStringRef kSCPropNetPPPDisconnectOnFastUserSwitch = CFSTR("DisconnectOnFastUserSwitch");
+const CFStringRef kSCPropNetPPPDisconnectOnIdle = CFSTR("DisconnectOnIdle");
+const CFStringRef kSCPropNetPPPDisconnectOnIdleTimer = CFSTR("DisconnectOnIdleTimer");
+const CFStringRef kSCPropNetPPPDisconnectOnLogout = CFSTR("DisconnectOnLogout");
+const CFStringRef kSCPropNetPPPDisconnectOnSleep = CFSTR("DisconnectOnSleep");
+const CFStringRef kSCPropNetPPPDisconnectTime = CFSTR("DisconnectTime");
+const CFStringRef kSCPropNetPPPIdleReminderTimer = CFSTR("IdleReminderTimer");
+const CFStringRef kSCPropNetPPPIdleReminder = CFSTR("IdleReminder");
+const CFStringRef kSCPropNetPPPLastCause = CFSTR("LastCause");
+const CFStringRef kSCPropNetPPPLogfile = CFSTR("Logfile");
+const CFStringRef kSCPropNetPPPPlugins = CFSTR("Plugins");
+const CFStringRef kSCPropNetPPPRetryConnectTime = CFSTR("RetryConnectTime");
+const CFStringRef kSCPropNetPPPSessionTimer = CFSTR("SessionTimer");
+const CFStringRef kSCPropNetPPPStatus = CFSTR("Status");
+const CFStringRef kSCPropNetPPPUseSessionTimer = CFSTR("UseSessionTimer");
+const CFStringRef kSCPropNetPPPVerboseLogging = CFSTR("VerboseLogging");
+const CFStringRef kSCPropNetPPPAuthEAPPlugins = CFSTR("AuthEAPPlugins");
+const CFStringRef kSCPropNetPPPAuthName = CFSTR("AuthName");
+const CFStringRef kSCPropNetPPPAuthPassword = CFSTR("AuthPassword");
+const CFStringRef kSCPropNetPPPAuthPasswordEncryption = CFSTR("AuthPasswordEncryption");
+const CFStringRef kSCPropNetPPPAuthPrompt = CFSTR("AuthPrompt");
+const CFStringRef kSCPropNetPPPAuthProtocol = CFSTR("AuthProtocol");
+const CFStringRef kSCValNetPPPAuthPasswordEncryptionKeychain = CFSTR("Keychain");
+const CFStringRef kSCValNetPPPAuthPromptBefore = CFSTR("Before");
+const CFStringRef kSCValNetPPPAuthPromptAfter = CFSTR("After");
+const CFStringRef kSCValNetPPPAuthProtocolCHAP = CFSTR("CHAP");
+const CFStringRef kSCValNetPPPAuthProtocolEAP = CFSTR("EAP");
+const CFStringRef kSCValNetPPPAuthProtocolMSCHAP1 = CFSTR("MSCHAP1");
+const CFStringRef kSCValNetPPPAuthProtocolMSCHAP2 = CFSTR("MSCHAP2");
+const CFStringRef kSCValNetPPPAuthProtocolPAP = CFSTR("PAP");
+const CFStringRef kSCPropNetPPPCommAlternateRemoteAddress = CFSTR("CommAlternateRemoteAddress");
+const CFStringRef kSCPropNetPPPCommConnectDelay = CFSTR("CommConnectDelay");
+const CFStringRef kSCPropNetPPPCommDisplayTerminalWindow = CFSTR("CommDisplayTerminalWindow");
+const CFStringRef kSCPropNetPPPCommRedialCount = CFSTR("CommRedialCount");
+const CFStringRef kSCPropNetPPPCommRedialEnabled = CFSTR("CommRedialEnabled");
+const CFStringRef kSCPropNetPPPCommRedialInterval = CFSTR("CommRedialInterval");
+const CFStringRef kSCPropNetPPPCommRemoteAddress = CFSTR("CommRemoteAddress");
+const CFStringRef kSCPropNetPPPCommTerminalScript = CFSTR("CommTerminalScript");
+const CFStringRef kSCPropNetPPPCommUseTerminalScript = CFSTR("CommUseTerminalScript");
+const CFStringRef kSCPropNetPPPCCPEnabled = CFSTR("CCPEnabled");
+const CFStringRef kSCPropNetPPPCCPMPPE40Enabled = CFSTR("CCPMPPE40Enabled");
+const CFStringRef kSCPropNetPPPCCPMPPE128Enabled = CFSTR("CCPMPPE128Enabled");
+const CFStringRef kSCPropNetPPPIPCPCompressionVJ = CFSTR("IPCPCompressionVJ");
+const CFStringRef kSCPropNetPPPIPCPUsePeerDNS = CFSTR("IPCPUsePeerDNS");
+const CFStringRef kSCPropNetPPPLCPEchoEnabled = CFSTR("LCPEchoEnabled");
+const CFStringRef kSCPropNetPPPLCPEchoFailure = CFSTR("LCPEchoFailure");
+const CFStringRef kSCPropNetPPPLCPEchoInterval = CFSTR("LCPEchoInterval");
+const CFStringRef kSCPropNetPPPLCPCompressionACField = CFSTR("LCPCompressionACField");
+const CFStringRef kSCPropNetPPPLCPCompressionPField = CFSTR("LCPCompressionPField");
+const CFStringRef kSCPropNetPPPLCPMRU = CFSTR("LCPMRU");
+const CFStringRef kSCPropNetPPPLCPMTU = CFSTR("LCPMTU");
+const CFStringRef kSCPropNetPPPLCPReceiveACCM = CFSTR("LCPReceiveACCM");
+const CFStringRef kSCPropNetPPPLCPTransmitACCM = CFSTR("LCPTransmitACCM");
+const CFStringRef kSCPropNetL2TPIPSecSharedSecret = CFSTR("IPSecSharedSecret");
+const CFStringRef kSCPropNetL2TPIPSecSharedSecretEncryption = CFSTR("IPSecSharedSecretEncryption");
+const CFStringRef kSCPropNetL2TPTransport = CFSTR("Transport");
+const CFStringRef kSCValNetL2TPIPSecSharedSecretEncryptionKeychain = CFSTR("Keychain");
+const CFStringRef kSCValNetL2TPTransportIP = CFSTR("IP");
+const CFStringRef kSCValNetL2TPTransportIPSec = CFSTR("IPSec");
+const CFStringRef kSCPropNetProxiesExceptionsList = CFSTR("ExceptionsList");
+const CFStringRef kSCPropNetProxiesExcludeSimpleHostnames = CFSTR("ExcludeSimpleHostnames");
+const CFStringRef kSCPropNetProxiesFTPEnable = CFSTR("FTPEnable");
+const CFStringRef kSCPropNetProxiesFTPPassive = CFSTR("FTPPassive");
+const CFStringRef kSCPropNetProxiesFTPPort = CFSTR("FTPPort");
+const CFStringRef kSCPropNetProxiesFTPProxy = CFSTR("FTPProxy");
+const CFStringRef kSCPropNetProxiesGopherEnable = CFSTR("GopherEnable");
+const CFStringRef kSCPropNetProxiesGopherPort = CFSTR("GopherPort");
+const CFStringRef kSCPropNetProxiesGopherProxy = CFSTR("GopherProxy");
+const CFStringRef kSCPropNetProxiesHTTPEnable = CFSTR("HTTPEnable");
+const CFStringRef kSCPropNetProxiesHTTPPort = CFSTR("HTTPPort");
+const CFStringRef kSCPropNetProxiesHTTPProxy = CFSTR("HTTPProxy");
+const CFStringRef kSCPropNetProxiesHTTPSEnable = CFSTR("HTTPSEnable");
+const CFStringRef kSCPropNetProxiesHTTPSPort = CFSTR("HTTPSPort");
+const CFStringRef kSCPropNetProxiesHTTPSProxy = CFSTR("HTTPSProxy");
+const CFStringRef kSCPropNetProxiesRTSPEnable = CFSTR("RTSPEnable");
+const CFStringRef kSCPropNetProxiesRTSPPort = CFSTR("RTSPPort");
+const CFStringRef kSCPropNetProxiesRTSPProxy = CFSTR("RTSPProxy");
+const CFStringRef kSCPropNetProxiesSOCKSEnable = CFSTR("SOCKSEnable");
+const CFStringRef kSCPropNetProxiesSOCKSPort = CFSTR("SOCKSPort");
+const CFStringRef kSCPropNetProxiesSOCKSProxy = CFSTR("SOCKSProxy");
+const CFStringRef kSCPropNetProxiesProxyAutoConfigEnable = CFSTR("ProxyAutoConfigEnable");
+const CFStringRef kSCPropNetProxiesProxyAutoConfigURLString = CFSTR("ProxyAutoConfigURLString");
+const CFStringRef kSCPropNetProxiesProxyAutoDiscoveryEnable = CFSTR("ProxyAutoDiscoveryEnable");
+const CFStringRef kSCEntUsersConsoleUser = CFSTR("ConsoleUser");
+const CFStringRef kSCPropSystemComputerName = CFSTR("ComputerName");
+const CFStringRef kSCPropSystemComputerNameEncoding = CFSTR("ComputerNameEncoding");
+const CFStringRef kSCDynamicStoreDomainFile = CFSTR("File:");
+const CFStringRef kSCDynamicStoreDomainPlugin = CFSTR("Plugin:");
+const CFStringRef kSCDynamicStoreDomainSetup = CFSTR("Setup:");
+const CFStringRef kSCDynamicStoreDomainState = CFSTR("State:");
+const CFStringRef kSCDynamicStoreDomainPrefs = CFSTR("Prefs:");
+const CFStringRef kSCDynamicStorePropSetupCurrentSet = CFSTR("CurrentSet");
+const CFStringRef kSCDynamicStorePropSetupLastUpdated = CFSTR("LastUpdated");
+const CFStringRef kSCDynamicStorePropNetInterfaces = CFSTR("Interfaces");
+const CFStringRef kSCDynamicStorePropNetPrimaryInterface = CFSTR("PrimaryInterface");
+const CFStringRef kSCDynamicStorePropNetPrimaryService = CFSTR("PrimaryService");
+const CFStringRef kSCDynamicStorePropNetServiceIDs = CFSTR("ServiceIDs");
+const CFStringRef kSCPropUsersConsoleUserName = CFSTR("Name");
+const CFStringRef kSCPropUsersConsoleUserUID = CFSTR("UID");
+const CFStringRef kSCPropUsersConsoleUserGID = CFSTR("GID");
--- /dev/null
+/*
+ * Copyright (c) 2000-2004 Apple Computer, 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@
+ */
+
+/*
+ * This file is automatically generated
+ * DO NOT EDIT!
+ */
+
+/*
+ * Reserved Keys
+ *
+ * kSCResvLink "__LINK__" CFString
+ * kSCResvInactive "__INACTIVE__"
+ *
+ * Generic Keys
+ *
+ * kSCPropInterfaceName "InterfaceName" CFString
+ * kSCPropMACAddress "MACAddress" CFString
+ * kSCPropUserDefinedName "UserDefinedName" CFString
+ * kSCPropVersion "Version" CFString
+ *
+ * Preference Keys
+ *
+ * kSCPrefCurrentSet "CurrentSet" CFString
+ * kSCPrefNetworkServices "NetworkServices" CFDictionary
+ * kSCPrefSets "Sets" CFDictionary
+ * kSCPrefSystem "System" CFDictionary
+ *
+ * Component Keys
+ *
+ * kSCCompNetwork "Network"
+ * kSCCompService "Service"
+ * kSCCompGlobal "Global"
+ * kSCCompHostNames "HostNames"
+ * kSCCompInterface "Interface"
+ * kSCCompSystem "System"
+ * kSCCompUsers "Users"
+ *
+ * --- Regex pattern which matches any component ---
+ * kSCCompAnyRegex "[^/]+"
+ *
+ * Network Entity Keys
+ *
+ * kSCEntNetAirPort "AirPort" CFDictionary
+ * kSCEntNetAppleTalk "AppleTalk" CFDictionary
+ * kSCEntNetDHCP "DHCP" CFDictionary
+ * kSCEntNetDNS "DNS" CFDictionary
+ * kSCEntNetEthernet "Ethernet" CFDictionary
+ * kSCEntNetFireWire "FireWire" CFDictionary
+ * kSCEntNetInterface "Interface" CFDictionary
+ * kSCEntNetIPv4 "IPv4" CFDictionary
+ * kSCEntNetIPv6 "IPv6" CFDictionary
+ * kSCEntNetL2TP "L2TP" CFDictionary
+ * kSCEntNetLink "Link" CFDictionary
+ * kSCEntNetModem "Modem" CFDictionary
+ * kSCEntNetNetInfo "NetInfo" CFDictionary
+ * kSCEntNetPPP "PPP" CFDictionary
+ * kSCEntNetPPPoE "PPPoE" CFDictionary
+ * kSCEntNetPPPSerial "PPPSerial" CFDictionary
+ * kSCEntNetPPTP "PPTP" CFDictionary
+ * kSCEntNetProxies "Proxies" CFDictionary
+ * kSCEntNet6to4 "6to4" CFDictionary
+ *
+ * kSCCompNetwork Properties
+ *
+ * kSCPropNetOverridePrimary "OverridePrimary" CFNumber (0 or 1)
+ * kSCPropNetServiceOrder "ServiceOrder" CFArray[CFString]
+ * kSCPropNetPPPOverridePrimary "PPPOverridePrimary" CFNumber (0 or 1)
+ *
+ * kSCCompNetworkInterface Properties
+ *
+ * kSCPropNetInterfaces "Interfaces" CFArray[CFString]
+ *
+ * kSCCompNetworkHostNames Properties
+ *
+ * kSCPropNetLocalHostName "LocalHostName" CFString
+ *
+ * kSCEntNetAirPort (Hardware) Entity Keys
+ *
+ * kSCPropNetAirPortAllowNetCreation "AllowNetCreation" CFNumber (0 or 1)
+ * kSCPropNetAirPortAuthPassword "AuthPassword" CFData
+ * kSCPropNetAirPortAuthPasswordEncryption "AuthPasswordEncryption" CFString
+ * kSCPropNetAirPortJoinMode "JoinMode" CFString
+ * kSCPropNetAirPortPowerEnabled "PowerEnabled" CFNumber (0 or 1)
+ * kSCPropNetAirPortPreferredNetwork "PreferredNetwork" CFString
+ * kSCPropNetAirPortSavePasswords "SavePasswords" CFNumber (0 or 1)
+ *
+ * --- kSCPropNetAirPortJoinMode values ---
+ * kSCValNetAirPortJoinModeAutomatic "Automatic"
+ * kSCValNetAirPortJoinModePreferred "Preferred"
+ * kSCValNetAirPortJoinModeRecent "Recent"
+ * kSCValNetAirPortJoinModeStrongest "Strongest"
+ *
+ * --- kSCPropNetAirPortPasswordEncryption values ---
+ * kSCValNetAirPortAuthPasswordEncryptionKeychain "Keychain"
+ *
+ * kSCEntNetAppleTalk Entity Keys
+ *
+ * kSCPropNetAppleTalkComputerName "ComputerName" CFString
+ * kSCPropNetAppleTalkComputerNameEncoding "ComputerNameEncoding" CFNumber
+ * kSCPropNetAppleTalkConfigMethod "ConfigMethod" CFString
+ * kSCPropNetAppleTalkDefaultZone "DefaultZone" CFString
+ * kSCPropNetAppleTalkNetworkID "NetworkID" CFNumber
+ * kSCPropNetAppleTalkNetworkRange "NetworkRange" CFArray[CFNumber]
+ * kSCPropNetAppleTalkNodeID "NodeID" CFNumber
+ * kSCPropNetAppleTalkSeedNetworkRange "SeedNetworkRange" CFArray[CFNumber]
+ * kSCPropNetAppleTalkSeedZones "SeedZones" CFArray[CFString]
+ *
+ * --- kSCPropNetAppleTalkConfigMethod values ---
+ * kSCValNetAppleTalkConfigMethodNode "Node"
+ * kSCValNetAppleTalkConfigMethodRouter "Router"
+ * kSCValNetAppleTalkConfigMethodSeedRouter "SeedRouter"
+ *
+ * kSCEntNetDNS Entity Keys
+ *
+ * kSCPropNetDNSDomainName "DomainName" CFString
+ * kSCPropNetDNSOptions "Options" CFString
+ * kSCPropNetDNSSearchDomains "SearchDomains" CFArray[CFString]
+ * kSCPropNetDNSSearchOrder "SearchOrder" CFNumber
+ * kSCPropNetDNSServerAddresses "ServerAddresses" CFArray[CFString]
+ * kSCPropNetDNSServerPort "ServerPort" CFNumber
+ * kSCPropNetDNSServerTimeout "ServerTimeout" CFNumber
+ * kSCPropNetDNSSortList "SortList" CFArray[CFString]
+ * kSCPropNetDNSSupplementalMatchDomains "SupplementalMatchDomains" CFArray[CFString]
+ * kSCPropNetDNSSupplementalMatchOrders "SupplementalMatchOrders" CFArray[CFNumber]
+ *
+ * kSCEntNetEthernet (Hardware) Entity Keys
+ *
+ * kSCPropNetEthernetMediaSubType "MediaSubType" CFString
+ * kSCPropNetEthernetMediaOptions "MediaOptions" CFArray[CFString]
+ * kSCPropNetEthernetMTU "MTU" CFNumber
+ *
+ * kSCEntNetFireWire (Hardware) Entity Keys
+ *
+ * * RESERVED FOR FUTURE USE *
+ *
+ * kSCEntNetInterface Entity Keys
+ *
+ * kSCPropNetInterfaceDeviceName "DeviceName" CFString
+ * kSCPropNetInterfaceHardware "Hardware" CFString
+ * kSCPropNetInterfaceType "Type" CFString
+ * kSCPropNetInterfaceSubType "SubType" CFString
+ * kSCPropNetInterfaceSupportsModemOnHold "SupportsModemOnHold" CFNumber (0 or 1)
+ *
+ * --- kSCPropNetInterfaceType values ---
+ * kSCValNetInterfaceTypeEthernet "Ethernet"
+ * kSCValNetInterfaceTypeFireWire "FireWire"
+ * kSCValNetInterfaceTypePPP "PPP"
+ * kSCValNetInterfaceType6to4 "6to4"
+ *
+ * --- kSCPropNetServiceSubType values (for PPP) ---
+ * kSCValNetInterfaceSubTypePPPoE "PPPoE"
+ * kSCValNetInterfaceSubTypePPPSerial "PPPSerial"
+ * kSCValNetInterfaceSubTypePPTP "PPTP"
+ * kSCValNetInterfaceSubTypeL2TP "L2TP"
+ *
+ * kSCEntNetIPv4 Entity Keys
+ *
+ * kSCPropNetIPv4Addresses "Addresses" CFArray[CFString]
+ * kSCPropNetIPv4ConfigMethod "ConfigMethod" CFString
+ * kSCPropNetIPv4DHCPClientID "DHCPClientID" CFString
+ * kSCPropNetIPv4Router "Router" CFString
+ * kSCPropNetIPv4SubnetMasks "SubnetMasks" CFArray[CFString]
+ * kSCPropNetIPv4DestAddresses "DestAddresses" CFArray[CFString]
+ * kSCPropNetIPv4BroadcastAddresses "BroadcastAddresses" CFArray[CFString]
+ *
+ * --- kSCPropNetIPv4ConfigMethod values ---
+ * kSCValNetIPv4ConfigMethodBOOTP "BOOTP"
+ * kSCValNetIPv4ConfigMethodDHCP "DHCP"
+ * kSCValNetIPv4ConfigMethodINFORM "INFORM"
+ * kSCValNetIPv4ConfigMethodLinkLocal "LinkLocal"
+ * kSCValNetIPv4ConfigMethodManual "Manual"
+ * kSCValNetIPv4ConfigMethodPPP "PPP"
+ *
+ * kSCEntNetIPv6 Entity Keys
+ *
+ * kSCPropNetIPv6Addresses "Addresses" CFArray[CFString]
+ * kSCPropNetIPv6ConfigMethod "ConfigMethod" CFString
+ * kSCPropNetIPv6DestAddresses "DestAddresses" CFArray[CFString]
+ * kSCPropNetIPv6Flags "Flags" CFNumber
+ * kSCPropNetIPv6PrefixLength "PrefixLength" CFArray[CFNumber]
+ * kSCPropNetIPv6Router "Router" CFString
+ *
+ * --- kSCPropNetIPv6ConfigMethod values ---
+ * kSCValNetIPv6ConfigMethodAutomatic "Automatic"
+ * kSCValNetIPv6ConfigMethodManual "Manual"
+ * kSCValNetIPv6ConfigMethodRouterAdvertisement "RouterAdvertisement"
+ * kSCValNetIPv6ConfigMethod6to4 "6to4"
+ *
+ * kSCEntNet6to4 Entity Keys
+ *
+ * kSCPropNet6to4Relay "Relay" CFString
+ *
+ * kSCEntNetLink Entity Keys
+ *
+ * kSCPropNetLinkActive "Active" CFBoolean
+ * kSCPropNetLinkDetaching "Detaching" CFBoolean
+ *
+ * kSCEntNetModem (Hardware) Entity Keys
+ *
+ * kSCPropNetModemConnectionScript "ConnectionScript" CFString
+ * kSCPropNetModemConnectSpeed "ConnectSpeed" CFNumber
+ * kSCPropNetModemDataCompression "DataCompression" CFNumber (0 or 1)
+ * kSCPropNetModemDialMode "DialMode" CFString
+ * kSCPropNetModemErrorCorrection "ErrorCorrection" CFNumber (0 or 1)
+ * kSCPropNetModemHoldCallWaitingAudibleAlert "HoldCallWaitingAudibleAlert" CFNumber (0 or 1)
+ * kSCPropNetModemHoldDisconnectOnAnswer "HoldDisconnectOnAnswer" CFNumber (0 or 1)
+ * kSCPropNetModemHoldEnabled "HoldEnabled" CFNumber (0 or 1)
+ * kSCPropNetModemHoldReminder "HoldReminder" CFNumber (0 or 1)
+ * kSCPropNetModemHoldReminderTime "HoldReminderTime" CFNumber
+ * kSCPropNetModemNote "Note" CFString
+ * kSCPropNetModemPulseDial "PulseDial" CFNumber (0 or 1)
+ * kSCPropNetModemSpeaker "Speaker" CFNumber (0 or 1)
+ * kSCPropNetModemSpeed "Speed" CFNumber
+ *
+ * --- kSCPropNetModemDialMode values ---
+ * kSCValNetModemDialModeIgnoreDialTone "IgnoreDialTone"
+ * kSCValNetModemDialModeManual "Manual"
+ * kSCValNetModemDialModeWaitForDialTone "WaitForDialTone"
+ *
+ * kSCEntNetNetInfo Entity Keys
+ *
+ * kSCPropNetNetInfoBindingMethods "BindingMethods" CFString
+ * kSCPropNetNetInfoServerAddresses "ServerAddresses" CFArray[CFString]
+ * kSCPropNetNetInfoServerTags "ServerTags" CFArray[CFString]
+ * kSCPropNetNetInfoBroadcastServerTag "BroadcastServerTag" CFString
+ *
+ * --- kSCPropNetNetInfoBindingMethods values ---
+ * kSCValNetNetInfoBindingMethodsBroadcast "Broadcast"
+ * kSCValNetNetInfoBindingMethodsDHCP "DHCP"
+ * kSCValNetNetInfoBindingMethodsManual "Manual"
+ *
+ * --- kSCPropNetNetInfoBroadcastServerTag default value ---
+ * kSCValNetNetInfoDefaultServerTag "network"
+ *
+ * kSCEntNetPPP Entity Keys
+ *
+ * kSCPropNetPPPACSPEnabled "ACSPEnabled" CFNumber (0 or 1)
+ * kSCPropNetPPPConnectTime "ConnectTime" CFNumber
+ * kSCPropNetPPPDeviceLastCause "DeviceLastCause" CFNumber
+ * kSCPropNetPPPDialOnDemand "DialOnDemand" CFNumber (0 or 1)
+ * kSCPropNetPPPDisconnectOnFastUserSwitch "DisconnectOnFastUserSwitch" CFNumber (0 or 1)
+ * kSCPropNetPPPDisconnectOnIdle "DisconnectOnIdle" CFNumber (0 or 1)
+ * kSCPropNetPPPDisconnectOnIdleTimer "DisconnectOnIdleTimer" CFNumber
+ * kSCPropNetPPPDisconnectOnLogout "DisconnectOnLogout" CFNumber (0 or 1)
+ * kSCPropNetPPPDisconnectOnSleep "DisconnectOnSleep" CFNumber (0 or 1)
+ * kSCPropNetPPPDisconnectTime "DisconnectTime" CFNumber
+ * kSCPropNetPPPIdleReminderTimer "IdleReminderTimer" CFNumber
+ * kSCPropNetPPPIdleReminder "IdleReminder" CFNumber (0 or 1)
+ * kSCPropNetPPPLastCause "LastCause" CFNumber
+ * kSCPropNetPPPLogfile "Logfile" CFString
+ * kSCPropNetPPPPlugins "Plugins" CFArray[CFString]
+ * kSCPropNetPPPRetryConnectTime "RetryConnectTime" CFNumber
+ * kSCPropNetPPPSessionTimer "SessionTimer" CFNumber
+ * kSCPropNetPPPStatus "Status" CFNumber
+ * kSCPropNetPPPUseSessionTimer "UseSessionTimer" CFNumber (0 or 1)
+ * kSCPropNetPPPVerboseLogging "VerboseLogging" CFNumber (0 or 1)
+ *
+ * --- Auth: ---
+ * kSCPropNetPPPAuthEAPPlugins "AuthEAPPlugins" CFArray[CFString]
+ * kSCPropNetPPPAuthName "AuthName" CFString
+ * kSCPropNetPPPAuthPassword "AuthPassword" CFString
+ * kSCPropNetPPPAuthPasswordEncryption "AuthPasswordEncryption" CFString
+ * kSCPropNetPPPAuthPrompt "AuthPrompt" CFString
+ * kSCPropNetPPPAuthProtocol "AuthProtocol" CFArray[CFString]
+ *
+ * --- kSCPropNetPPPAuthPasswordEncryption values ---
+ * kSCValNetPPPAuthPasswordEncryptionKeychain "Keychain"
+ *
+ * --- kSCPropNetPPPAuthPrompt values ---
+ * kSCValNetPPPAuthPromptBefore "Before" CFString
+ * kSCValNetPPPAuthPromptAfter "After" CFString
+ *
+ * --- kSCPropNetPPPAuthProtocol values ---
+ * kSCValNetPPPAuthProtocolCHAP "CHAP" CFString
+ * kSCValNetPPPAuthProtocolEAP "EAP" CFString
+ * kSCValNetPPPAuthProtocolMSCHAP1 "MSCHAP1" CFString
+ * kSCValNetPPPAuthProtocolMSCHAP2 "MSCHAP2" CFString
+ * kSCValNetPPPAuthProtocolPAP "PAP" CFString
+ *
+ * --- Comm: ---
+ * kSCPropNetPPPCommAlternateRemoteAddress "CommAlternateRemoteAddress" CFString
+ * kSCPropNetPPPCommConnectDelay "CommConnectDelay" CFNumber
+ * kSCPropNetPPPCommDisplayTerminalWindow "CommDisplayTerminalWindow" CFNumber (0 or 1)
+ * kSCPropNetPPPCommRedialCount "CommRedialCount" CFNumber
+ * kSCPropNetPPPCommRedialEnabled "CommRedialEnabled" CFNumber (0 or 1)
+ * kSCPropNetPPPCommRedialInterval "CommRedialInterval" CFNumber
+ * kSCPropNetPPPCommRemoteAddress "CommRemoteAddress" CFString
+ * kSCPropNetPPPCommTerminalScript "CommTerminalScript" CFString
+ * kSCPropNetPPPCommUseTerminalScript "CommUseTerminalScript" CFNumber (0 or 1)
+ *
+ * --- CCP: ---
+ * kSCPropNetPPPCCPEnabled "CCPEnabled" CFNumber (0 or 1)
+ * kSCPropNetPPPCCPMPPE40Enabled "CCPMPPE40Enabled" CFNumber (0 or 1)
+ * kSCPropNetPPPCCPMPPE128Enabled "CCPMPPE128Enabled" CFNumber (0 or 1)
+ *
+ * --- IPCP: ---
+ * kSCPropNetPPPIPCPCompressionVJ "IPCPCompressionVJ" CFNumber (0 or 1)
+ * kSCPropNetPPPIPCPUsePeerDNS "IPCPUsePeerDNS" CFNumber (0 or 1)
+ *
+ * --- LCP: ---
+ * kSCPropNetPPPLCPEchoEnabled "LCPEchoEnabled" CFNumber (0 or 1)
+ * kSCPropNetPPPLCPEchoFailure "LCPEchoFailure" CFNumber
+ * kSCPropNetPPPLCPEchoInterval "LCPEchoInterval" CFNumber
+ * kSCPropNetPPPLCPCompressionACField "LCPCompressionACField" CFNumber (0 or 1)
+ * kSCPropNetPPPLCPCompressionPField "LCPCompressionPField" CFNumber (0 or 1)
+ * kSCPropNetPPPLCPMRU "LCPMRU" CFNumber
+ * kSCPropNetPPPLCPMTU "LCPMTU" CFNumber
+ * kSCPropNetPPPLCPReceiveACCM "LCPReceiveACCM" CFNumber
+ * kSCPropNetPPPLCPTransmitACCM "LCPTransmitACCM" CFNumber
+ *
+ * kSCEntNetPPPoE Entity Keys
+ *
+ * * RESERVED FOR FUTURE USE *
+ *
+ * kSCEntNetPPPSerial Entity Keys
+ *
+ * * RESERVED FOR FUTURE USE *
+ *
+ * kSCEntNetPPTP Entity Keys
+ *
+ * * RESERVED FOR FUTURE USE *
+ *
+ * kSCEntNetL2TP Entity Keys
+ *
+ * kSCPropNetL2TPIPSecSharedSecret "IPSecSharedSecret" CFString
+ * kSCPropNetL2TPIPSecSharedSecretEncryption "IPSecSharedSecretEncryption" CFString
+ * kSCPropNetL2TPTransport "Transport" CFString
+ *
+ * --- kSCPropNetL2TPIPSecSharedSecretEncryption values ---
+ * kSCValNetL2TPIPSecSharedSecretEncryptionKeychain "Keychain"
+ *
+ * --- kSCPropNetL2TPTransport values ---
+ * kSCValNetL2TPTransportIP "IP"
+ * kSCValNetL2TPTransportIPSec "IPSec"
+ *
+ * kSCEntNetProxies Entity Keys
+ *
+ * kSCPropNetProxiesExceptionsList "ExceptionsList" CFArray[CFString]
+ * kSCPropNetProxiesExcludeSimpleHostnames "ExcludeSimpleHostnames" CFNumber (0 or 1)
+ * kSCPropNetProxiesFTPEnable "FTPEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesFTPPassive "FTPPassive" CFNumber (0 or 1)
+ * kSCPropNetProxiesFTPPort "FTPPort" CFNumber
+ * kSCPropNetProxiesFTPProxy "FTPProxy" CFString
+ * kSCPropNetProxiesGopherEnable "GopherEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesGopherPort "GopherPort" CFNumber
+ * kSCPropNetProxiesGopherProxy "GopherProxy" CFString
+ * kSCPropNetProxiesHTTPEnable "HTTPEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesHTTPPort "HTTPPort" CFNumber
+ * kSCPropNetProxiesHTTPProxy "HTTPProxy" CFString
+ * kSCPropNetProxiesHTTPSEnable "HTTPSEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesHTTPSPort "HTTPSPort" CFNumber
+ * kSCPropNetProxiesHTTPSProxy "HTTPSProxy" CFString
+ * kSCPropNetProxiesRTSPEnable "RTSPEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesRTSPPort "RTSPPort" CFNumber
+ * kSCPropNetProxiesRTSPProxy "RTSPProxy" CFString
+ * kSCPropNetProxiesSOCKSEnable "SOCKSEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesSOCKSPort "SOCKSPort" CFNumber
+ * kSCPropNetProxiesSOCKSProxy "SOCKSProxy" CFString
+ * kSCPropNetProxiesProxyAutoConfigEnable "ProxyAutoConfigEnable" CFNumber (0 or 1)
+ * kSCPropNetProxiesProxyAutoConfigURLString "ProxyAutoConfigURLString" CFString
+ * kSCPropNetProxiesProxyAutoDiscoveryEnable "ProxyAutoDiscoveryEnable" CFNumber (0 or 1)
+ *
+ * kSCCompUsers Entity Keys
+ *
+ * kSCEntUsersConsoleUser "ConsoleUser"
+ *
+ * kSCCompSystem Properties
+ *
+ * kSCPropSystemComputerName "ComputerName" CFString
+ * kSCPropSystemComputerNameEncoding "ComputerNameEncoding" CFNumber
+ *
+ * SCDynamicStore "domain" prefixes
+ *
+ * kSCDynamicStoreDomainFile "File:"
+ * kSCDynamicStoreDomainPlugin "Plugin:"
+ * kSCDynamicStoreDomainSetup "Setup:"
+ * kSCDynamicStoreDomainState "State:"
+ * kSCDynamicStoreDomainPrefs "Prefs:"
+ *
+ * Preference ("location") Keys
+ *
+ * kSCDynamicStorePropSetupCurrentSet "CurrentSet" CFString
+ * kSCDynamicStorePropSetupLastUpdated "LastUpdated"
+ *
+ * Common/shared Keys
+ *
+ * kSCDynamicStorePropNetInterfaces "Interfaces" CFArray[CFString]
+ * kSCDynamicStorePropNetPrimaryInterface "PrimaryInterface" CFString
+ * kSCDynamicStorePropNetPrimaryService "PrimaryService" CFString
+ * kSCDynamicStorePropNetServiceIDs "ServiceIDs" CFArray[CFString]
+ */
+
+
+/*
+ * Note: The MACOSX_DEPLOYMENT_TARGET environment variable should be used
+ * when building an application targeted for an earlier version of
+ * Mac OS X. Please reference Technical Note TN2064 for more details.
+ */
+
+/*
+ * Note: For Cocoa/Obj-C/Foundation applications accessing these preference
+ * keys you may want to consider the following :
+ *
+ * #define SC_SCHEMA_DECLARATION(k,q) extern NSString * k
+ * #import <SystemConfiguration/SystemConfiguration.h>
+ */
+
+/*
+ * Note: For CFM applications using these schema keys you may want to
+ * consider the following :
+ *
+ * #define SC_SCHEMA_KV(k,v,t) lookup_SC_key( CFSTR( #k ) )
+ * #define SC_SCHEMA_DECLARATION(k,q)
+ * #include <SystemConfiguration/SystemConfiguration.h>
+ *
+ * CFStringRef lookup_SC_key(CFStringRef key)
+ * {
+ * // this function should [dynamically, on-demand] load the
+ * // SystemConfiguration.framework, look up the provided key,
+ * // and return the associated value.
+ * }
+ */
+
+/*
+ * Note: Earlier versions of this header file defined a "SCSTR" macro
+ * which helped to facilitate Obj-C development. Use of this macro
+ * has been deprecated (in Mac OS X 10.4) in favor of the newer
+ * "SC_SCHEMA_KV" and "SC_SCHEMA_DECLARATION" macros
+ */
+
+
+#ifndef _SCSCHEMADEFINITIONS_H
+#define _SCSCHEMADEFINITIONS_H
+
+/* -------------------- Macro declarations -------------------- */
+
+#include <AvailabilityMacros.h>
+
+/*
+ * let's "do the right thing" for those wishing to build for
+ * Mac OS X 10.1 and 10.2
+ */
+#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED
+ #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED
+ #ifndef SCSTR
+ #include <CoreFoundation/CFString.h>
+ #define SCSTR(s) CFSTR(s)
+ #endif
+ #ifndef SC_SCHEMA_KV
+ #define SC_SCHEMA_KV(k,v,t) SCSTR( v )
+ #endif
+ #ifndef SC_SCHEMA_DECLARATION
+ #define SC_SCHEMA_DECLARATION(k,q)
+ #endif
+ #endif
+#endif
+
+/*
+ * Define a schema key/value/type tuple
+ */
+#ifndef SC_SCHEMA_KV
+ #define SC_SCHEMA_KV(k,v,t) k
+#endif
+
+/*
+ * Provide an "extern" for the key/value
+ */
+#ifndef SC_SCHEMA_DECLARATION
+ #ifndef SCSTR
+ #include <CoreFoundation/CFString.h>
+ #define SC_SCHEMA_DECLARATION(k,q) extern const CFStringRef k q
+ #else
+ #import <Foundation/NSString.h>
+ #define SC_SCHEMA_DECLARATION(k,q) extern NSString * k q
+ #endif
+#endif
+#if MAC_OS_X_VERSION_10_4 >= MAC_OS_X_VERSION_MIN_REQUIRED
+ #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED
+ #ifndef SCSTR
+ #include <CoreFoundation/CFString.h>
+ #define SCSTR(s) CFSTR(s)
+ #endif
+ #endif
+#endif
+
+
+/* -------------------- HeaderDoc comments -------------------- */
+
+
+#if 0
+/*!
+ * @header SCSchemaDefinitions
+ */
+
+/*!
+ @const kSCResvLink
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCResvLink;
+
+/*!
+ @const kSCResvInactive
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCResvInactive;
+
+/*!
+ @const kSCPropInterfaceName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropInterfaceName;
+
+/*!
+ @const kSCPropMACAddress
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropMACAddress;
+
+/*!
+ @const kSCPropUserDefinedName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropUserDefinedName;
+
+/*!
+ @const kSCPropVersion
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropVersion;
+
+/*!
+ @group Preference Keys
+ */
+
+/*!
+ @const kSCPrefCurrentSet
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefCurrentSet;
+
+/*!
+ @const kSCPrefNetworkServices
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefNetworkServices;
+
+/*!
+ @const kSCPrefSets
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefSets;
+
+/*!
+ @const kSCPrefSystem
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefSystem;
+
+/*!
+ @group Component Keys
+ */
+
+/*!
+ @const kSCCompNetwork
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompNetwork;
+
+/*!
+ @const kSCCompService
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompService;
+
+/*!
+ @const kSCCompGlobal
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompGlobal;
+
+/*!
+ @const kSCCompHostNames
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCCompHostNames;
+
+/*!
+ @const kSCCompInterface
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompInterface;
+
+/*!
+ @const kSCCompSystem
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompSystem;
+
+/*!
+ @const kSCCompUsers
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompUsers;
+
+/*!
+ @const kSCCompAnyRegex
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompAnyRegex;
+
+/*!
+ @group Network Entity Keys
+ */
+
+/*!
+ @const kSCEntNetAirPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetAirPort;
+
+/*!
+ @const kSCEntNetAppleTalk
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetAppleTalk;
+
+/*!
+ @const kSCEntNetDHCP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetDHCP;
+
+/*!
+ @const kSCEntNetDNS
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetDNS;
+
+/*!
+ @const kSCEntNetEthernet
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetEthernet;
+
+/*!
+ @const kSCEntNetFireWire
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetFireWire;
+
+/*!
+ @const kSCEntNetInterface
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetInterface;
+
+/*!
+ @const kSCEntNetIPv4
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetIPv4;
+
+/*!
+ @const kSCEntNetIPv6
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetIPv6;
+
+/*!
+ @const kSCEntNetL2TP
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetL2TP;
+
+/*!
+ @const kSCEntNetLink
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetLink;
+
+/*!
+ @const kSCEntNetModem
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetModem;
+
+/*!
+ @const kSCEntNetNetInfo
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetNetInfo;
+
+/*!
+ @const kSCEntNetPPP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetPPP;
+
+/*!
+ @const kSCEntNetPPPoE
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetPPPoE;
+
+/*!
+ @const kSCEntNetPPPSerial
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetPPPSerial;
+
+/*!
+ @const kSCEntNetPPTP
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetPPTP;
+
+/*!
+ @const kSCEntNetProxies
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetProxies;
+
+/*!
+ @const kSCEntNet6to4
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNet6to4;
+
+/*!
+ @group kSCCompNetwork Properties
+ */
+
+/*!
+ @const kSCPropNetOverridePrimary
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetOverridePrimary;
+
+/*!
+ @const kSCPropNetServiceOrder
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetServiceOrder;
+
+/*!
+ @const kSCPropNetPPPOverridePrimary
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPOverridePrimary;
+
+/*!
+ @group kSCCompNetworkInterface Properties
+ */
+
+/*!
+ @const kSCPropNetInterfaces
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetInterfaces;
+
+/*!
+ @group kSCCompNetworkHostNames Properties
+ */
+
+/*!
+ @const kSCPropNetLocalHostName
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetLocalHostName;
+
+/*!
+ @group kSCEntNetAirPort (Hardware) Entity Keys
+ */
+
+/*!
+ @const kSCPropNetAirPortAllowNetCreation
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAirPortAllowNetCreation;
+
+/*!
+ @const kSCPropNetAirPortAuthPassword
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortAuthPassword;
+
+/*!
+ @const kSCPropNetAirPortAuthPasswordEncryption
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortAuthPasswordEncryption;
+
+/*!
+ @const kSCPropNetAirPortJoinMode
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAirPortJoinMode;
+
+/*!
+ @const kSCPropNetAirPortPowerEnabled
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortPowerEnabled;
+
+/*!
+ @const kSCPropNetAirPortPreferredNetwork
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortPreferredNetwork;
+
+/*!
+ @const kSCPropNetAirPortSavePasswords
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAirPortSavePasswords;
+
+/*!
+ @const kSCValNetAirPortJoinModeAutomatic
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModeAutomatic;
+
+/*!
+ @const kSCValNetAirPortJoinModePreferred
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModePreferred;
+
+/*!
+ @const kSCValNetAirPortJoinModeRecent
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModeRecent;
+
+/*!
+ @const kSCValNetAirPortJoinModeStrongest
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModeStrongest;
+
+/*!
+ @const kSCValNetAirPortAuthPasswordEncryptionKeychain
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetAirPortAuthPasswordEncryptionKeychain;
+
+/*!
+ @group kSCEntNetAppleTalk Entity Keys
+ */
+
+/*!
+ @const kSCPropNetAppleTalkComputerName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkComputerName;
+
+/*!
+ @const kSCPropNetAppleTalkComputerNameEncoding
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkComputerNameEncoding;
+
+/*!
+ @const kSCPropNetAppleTalkConfigMethod
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkConfigMethod;
+
+/*!
+ @const kSCPropNetAppleTalkDefaultZone
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkDefaultZone;
+
+/*!
+ @const kSCPropNetAppleTalkNetworkID
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkNetworkID;
+
+/*!
+ @const kSCPropNetAppleTalkNetworkRange
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAppleTalkNetworkRange;
+
+/*!
+ @const kSCPropNetAppleTalkNodeID
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkNodeID;
+
+/*!
+ @const kSCPropNetAppleTalkSeedNetworkRange
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkSeedNetworkRange;
+
+/*!
+ @const kSCPropNetAppleTalkSeedZones
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkSeedZones;
+
+/*!
+ @const kSCValNetAppleTalkConfigMethodNode
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetAppleTalkConfigMethodNode;
+
+/*!
+ @const kSCValNetAppleTalkConfigMethodRouter
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetAppleTalkConfigMethodRouter;
+
+/*!
+ @const kSCValNetAppleTalkConfigMethodSeedRouter
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetAppleTalkConfigMethodSeedRouter;
+
+/*!
+ @group kSCEntNetDNS Entity Keys
+ */
+
+/*!
+ @const kSCPropNetDNSDomainName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSDomainName;
+
+/*!
+ @const kSCPropNetDNSOptions
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSOptions;
+
+/*!
+ @const kSCPropNetDNSSearchDomains
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSSearchDomains;
+
+/*!
+ @const kSCPropNetDNSSearchOrder
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSSearchOrder;
+
+/*!
+ @const kSCPropNetDNSServerAddresses
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSServerAddresses;
+
+/*!
+ @const kSCPropNetDNSServerPort
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSServerPort;
+
+/*!
+ @const kSCPropNetDNSServerTimeout
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSServerTimeout;
+
+/*!
+ @const kSCPropNetDNSSortList
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSSortList;
+
+/*!
+ @const kSCPropNetDNSSupplementalMatchDomains
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSSupplementalMatchDomains;
+
+/*!
+ @const kSCPropNetDNSSupplementalMatchOrders
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSSupplementalMatchOrders;
+
+/*!
+ @group kSCEntNetEthernet (Hardware) Entity Keys
+ */
+
+/*!
+ @const kSCPropNetEthernetMediaSubType
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetEthernetMediaSubType;
+
+/*!
+ @const kSCPropNetEthernetMediaOptions
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetEthernetMediaOptions;
+
+/*!
+ @const kSCPropNetEthernetMTU
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetEthernetMTU;
+
+/*!
+ @group kSCEntNetFireWire (Hardware) Entity Keys
+ */
+
+/*!
+ @group kSCEntNetInterface Entity Keys
+ */
+
+/*!
+ @const kSCPropNetInterfaceDeviceName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceDeviceName;
+
+/*!
+ @const kSCPropNetInterfaceHardware
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceHardware;
+
+/*!
+ @const kSCPropNetInterfaceType
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceType;
+
+/*!
+ @const kSCPropNetInterfaceSubType
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceSubType;
+
+/*!
+ @const kSCPropNetInterfaceSupportsModemOnHold
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetInterfaceSupportsModemOnHold;
+
+/*!
+ @const kSCValNetInterfaceTypeEthernet
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceTypeEthernet;
+
+/*!
+ @const kSCValNetInterfaceTypeFireWire
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetInterfaceTypeFireWire;
+
+/*!
+ @const kSCValNetInterfaceTypePPP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceTypePPP;
+
+/*!
+ @const kSCValNetInterfaceType6to4
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetInterfaceType6to4;
+
+/*!
+ @const kSCValNetInterfaceSubTypePPPoE
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypePPPoE;
+
+/*!
+ @const kSCValNetInterfaceSubTypePPPSerial
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypePPPSerial;
+
+/*!
+ @const kSCValNetInterfaceSubTypePPTP
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypePPTP;
+
+/*!
+ @const kSCValNetInterfaceSubTypeL2TP
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypeL2TP;
+
+/*!
+ @group kSCEntNetIPv4 Entity Keys
+ */
+
+/*!
+ @const kSCPropNetIPv4Addresses
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4Addresses;
+
+/*!
+ @const kSCPropNetIPv4ConfigMethod
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4ConfigMethod;
+
+/*!
+ @const kSCPropNetIPv4DHCPClientID
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4DHCPClientID;
+
+/*!
+ @const kSCPropNetIPv4Router
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4Router;
+
+/*!
+ @const kSCPropNetIPv4SubnetMasks
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4SubnetMasks;
+
+/*!
+ @const kSCPropNetIPv4DestAddresses
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4DestAddresses;
+
+/*!
+ @const kSCPropNetIPv4BroadcastAddresses
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4BroadcastAddresses;
+
+/*!
+ @const kSCValNetIPv4ConfigMethodBOOTP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodBOOTP;
+
+/*!
+ @const kSCValNetIPv4ConfigMethodDHCP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodDHCP;
+
+/*!
+ @const kSCValNetIPv4ConfigMethodINFORM
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodINFORM;
+
+/*!
+ @const kSCValNetIPv4ConfigMethodLinkLocal
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodLinkLocal;
+
+/*!
+ @const kSCValNetIPv4ConfigMethodManual
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodManual;
+
+/*!
+ @const kSCValNetIPv4ConfigMethodPPP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodPPP;
+
+/*!
+ @group kSCEntNetIPv6 Entity Keys
+ */
+
+/*!
+ @const kSCPropNetIPv6Addresses
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv6Addresses;
+
+/*!
+ @const kSCPropNetIPv6ConfigMethod
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv6ConfigMethod;
+
+/*!
+ @const kSCPropNetIPv6DestAddresses
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6DestAddresses;
+
+/*!
+ @const kSCPropNetIPv6Flags
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6Flags;
+
+/*!
+ @const kSCPropNetIPv6PrefixLength
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6PrefixLength;
+
+/*!
+ @const kSCPropNetIPv6Router
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6Router;
+
+/*!
+ @const kSCValNetIPv6ConfigMethodAutomatic
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethodAutomatic;
+
+/*!
+ @const kSCValNetIPv6ConfigMethodManual
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethodManual;
+
+/*!
+ @const kSCValNetIPv6ConfigMethodRouterAdvertisement
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethodRouterAdvertisement;
+
+/*!
+ @const kSCValNetIPv6ConfigMethod6to4
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethod6to4;
+
+/*!
+ @group kSCEntNet6to4 Entity Keys
+ */
+
+/*!
+ @const kSCPropNet6to4Relay
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNet6to4Relay;
+
+/*!
+ @group kSCEntNetLink Entity Keys
+ */
+
+/*!
+ @const kSCPropNetLinkActive
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetLinkActive;
+
+/*!
+ @const kSCPropNetLinkDetaching
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetLinkDetaching;
+
+/*!
+ @group kSCEntNetModem (Hardware) Entity Keys
+ */
+
+/*!
+ @const kSCPropNetModemConnectionScript
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemConnectionScript;
+
+/*!
+ @const kSCPropNetModemConnectSpeed
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemConnectSpeed;
+
+/*!
+ @const kSCPropNetModemDataCompression
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemDataCompression;
+
+/*!
+ @const kSCPropNetModemDialMode
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemDialMode;
+
+/*!
+ @const kSCPropNetModemErrorCorrection
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemErrorCorrection;
+
+/*!
+ @const kSCPropNetModemHoldCallWaitingAudibleAlert
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldCallWaitingAudibleAlert;
+
+/*!
+ @const kSCPropNetModemHoldDisconnectOnAnswer
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldDisconnectOnAnswer;
+
+/*!
+ @const kSCPropNetModemHoldEnabled
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldEnabled;
+
+/*!
+ @const kSCPropNetModemHoldReminder
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldReminder;
+
+/*!
+ @const kSCPropNetModemHoldReminderTime
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldReminderTime;
+
+/*!
+ @const kSCPropNetModemNote
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemNote;
+
+/*!
+ @const kSCPropNetModemPulseDial
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemPulseDial;
+
+/*!
+ @const kSCPropNetModemSpeaker
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemSpeaker;
+
+/*!
+ @const kSCPropNetModemSpeed
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemSpeed;
+
+/*!
+ @const kSCValNetModemDialModeIgnoreDialTone
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetModemDialModeIgnoreDialTone;
+
+/*!
+ @const kSCValNetModemDialModeManual
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetModemDialModeManual;
+
+/*!
+ @const kSCValNetModemDialModeWaitForDialTone
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetModemDialModeWaitForDialTone;
+
+/*!
+ @group kSCEntNetNetInfo Entity Keys
+ */
+
+/*!
+ @const kSCPropNetNetInfoBindingMethods
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoBindingMethods;
+
+/*!
+ @const kSCPropNetNetInfoServerAddresses
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoServerAddresses;
+
+/*!
+ @const kSCPropNetNetInfoServerTags
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoServerTags;
+
+/*!
+ @const kSCPropNetNetInfoBroadcastServerTag
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoBroadcastServerTag;
+
+/*!
+ @const kSCValNetNetInfoBindingMethodsBroadcast
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoBindingMethodsBroadcast;
+
+/*!
+ @const kSCValNetNetInfoBindingMethodsDHCP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoBindingMethodsDHCP;
+
+/*!
+ @const kSCValNetNetInfoBindingMethodsManual
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoBindingMethodsManual;
+
+/*!
+ @const kSCValNetNetInfoDefaultServerTag
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoDefaultServerTag;
+
+/*!
+ @group kSCEntNetPPP Entity Keys
+ */
+
+/*!
+ @const kSCPropNetPPPACSPEnabled
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPACSPEnabled;
+
+/*!
+ @const kSCPropNetPPPConnectTime
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPConnectTime;
+
+/*!
+ @const kSCPropNetPPPDeviceLastCause
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPDeviceLastCause;
+
+/*!
+ @const kSCPropNetPPPDialOnDemand
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDialOnDemand;
+
+/*!
+ @const kSCPropNetPPPDisconnectOnFastUserSwitch
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnFastUserSwitch;
+
+/*!
+ @const kSCPropNetPPPDisconnectOnIdle
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnIdle;
+
+/*!
+ @const kSCPropNetPPPDisconnectOnIdleTimer
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnIdleTimer;
+
+/*!
+ @const kSCPropNetPPPDisconnectOnLogout
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnLogout;
+
+/*!
+ @const kSCPropNetPPPDisconnectOnSleep
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnSleep;
+
+/*!
+ @const kSCPropNetPPPDisconnectTime
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectTime;
+
+/*!
+ @const kSCPropNetPPPIdleReminderTimer
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPIdleReminderTimer;
+
+/*!
+ @const kSCPropNetPPPIdleReminder
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPIdleReminder;
+
+/*!
+ @const kSCPropNetPPPLastCause
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPLastCause;
+
+/*!
+ @const kSCPropNetPPPLogfile
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLogfile;
+
+/*!
+ @const kSCPropNetPPPPlugins
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPPlugins;
+
+/*!
+ @const kSCPropNetPPPRetryConnectTime
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPRetryConnectTime;
+
+/*!
+ @const kSCPropNetPPPSessionTimer
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPSessionTimer;
+
+/*!
+ @const kSCPropNetPPPStatus
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPStatus;
+
+/*!
+ @const kSCPropNetPPPUseSessionTimer
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPUseSessionTimer;
+
+/*!
+ @const kSCPropNetPPPVerboseLogging
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPVerboseLogging;
+
+/*!
+ @const kSCPropNetPPPAuthEAPPlugins
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPAuthEAPPlugins;
+
+/*!
+ @const kSCPropNetPPPAuthName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthName;
+
+/*!
+ @const kSCPropNetPPPAuthPassword
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthPassword;
+
+/*!
+ @const kSCPropNetPPPAuthPasswordEncryption
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthPasswordEncryption;
+
+/*!
+ @const kSCPropNetPPPAuthPrompt
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPAuthPrompt;
+
+/*!
+ @const kSCPropNetPPPAuthProtocol
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthProtocol;
+
+/*!
+ @const kSCValNetPPPAuthPasswordEncryptionKeychain
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthPasswordEncryptionKeychain;
+
+/*!
+ @const kSCValNetPPPAuthPromptBefore
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthPromptBefore;
+
+/*!
+ @const kSCValNetPPPAuthPromptAfter
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthPromptAfter;
+
+/*!
+ @const kSCValNetPPPAuthProtocolCHAP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolCHAP;
+
+/*!
+ @const kSCValNetPPPAuthProtocolEAP
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolEAP;
+
+/*!
+ @const kSCValNetPPPAuthProtocolMSCHAP1
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolMSCHAP1;
+
+/*!
+ @const kSCValNetPPPAuthProtocolMSCHAP2
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolMSCHAP2;
+
+/*!
+ @const kSCValNetPPPAuthProtocolPAP
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolPAP;
+
+/*!
+ @const kSCPropNetPPPCommAlternateRemoteAddress
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommAlternateRemoteAddress;
+
+/*!
+ @const kSCPropNetPPPCommConnectDelay
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommConnectDelay;
+
+/*!
+ @const kSCPropNetPPPCommDisplayTerminalWindow
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommDisplayTerminalWindow;
+
+/*!
+ @const kSCPropNetPPPCommRedialCount
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRedialCount;
+
+/*!
+ @const kSCPropNetPPPCommRedialEnabled
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRedialEnabled;
+
+/*!
+ @const kSCPropNetPPPCommRedialInterval
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRedialInterval;
+
+/*!
+ @const kSCPropNetPPPCommRemoteAddress
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRemoteAddress;
+
+/*!
+ @const kSCPropNetPPPCommTerminalScript
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommTerminalScript;
+
+/*!
+ @const kSCPropNetPPPCommUseTerminalScript
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPCommUseTerminalScript;
+
+/*!
+ @const kSCPropNetPPPCCPEnabled
+ @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPCCPEnabled;
+
+/*!
+ @const kSCPropNetPPPCCPMPPE40Enabled
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPCCPMPPE40Enabled;
+
+/*!
+ @const kSCPropNetPPPCCPMPPE128Enabled
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPCCPMPPE128Enabled;
+
+/*!
+ @const kSCPropNetPPPIPCPCompressionVJ
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPIPCPCompressionVJ;
+
+/*!
+ @const kSCPropNetPPPIPCPUsePeerDNS
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPIPCPUsePeerDNS;
+
+/*!
+ @const kSCPropNetPPPLCPEchoEnabled
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPEchoEnabled;
+
+/*!
+ @const kSCPropNetPPPLCPEchoFailure
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPEchoFailure;
+
+/*!
+ @const kSCPropNetPPPLCPEchoInterval
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPEchoInterval;
+
+/*!
+ @const kSCPropNetPPPLCPCompressionACField
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPCompressionACField;
+
+/*!
+ @const kSCPropNetPPPLCPCompressionPField
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPCompressionPField;
+
+/*!
+ @const kSCPropNetPPPLCPMRU
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPMRU;
+
+/*!
+ @const kSCPropNetPPPLCPMTU
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPMTU;
+
+/*!
+ @const kSCPropNetPPPLCPReceiveACCM
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPReceiveACCM;
+
+/*!
+ @const kSCPropNetPPPLCPTransmitACCM
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPTransmitACCM;
+
+/*!
+ @group kSCEntNetPPPoE Entity Keys
+ */
+
+/*!
+ @group kSCEntNetPPPSerial Entity Keys
+ */
+
+/*!
+ @group kSCEntNetPPTP Entity Keys
+ */
+
+/*!
+ @group kSCEntNetL2TP Entity Keys
+ */
+
+/*!
+ @const kSCPropNetL2TPIPSecSharedSecret
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetL2TPIPSecSharedSecret;
+
+/*!
+ @const kSCPropNetL2TPIPSecSharedSecretEncryption
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetL2TPIPSecSharedSecretEncryption;
+
+/*!
+ @const kSCPropNetL2TPTransport
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetL2TPTransport;
+
+/*!
+ @const kSCValNetL2TPIPSecSharedSecretEncryptionKeychain
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetL2TPIPSecSharedSecretEncryptionKeychain;
+
+/*!
+ @const kSCValNetL2TPTransportIP
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetL2TPTransportIP;
+
+/*!
+ @const kSCValNetL2TPTransportIPSec
+ @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetL2TPTransportIPSec;
+
+/*!
+ @group kSCEntNetProxies Entity Keys
+ */
+
+/*!
+ @const kSCPropNetProxiesExceptionsList
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesExceptionsList;
+
+/*!
+ @const kSCPropNetProxiesExcludeSimpleHostnames
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesExcludeSimpleHostnames;
+
+/*!
+ @const kSCPropNetProxiesFTPEnable
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPEnable;
+
+/*!
+ @const kSCPropNetProxiesFTPPassive
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPPassive;
+
+/*!
+ @const kSCPropNetProxiesFTPPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPPort;
+
+/*!
+ @const kSCPropNetProxiesFTPProxy
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPProxy;
+
+/*!
+ @const kSCPropNetProxiesGopherEnable
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesGopherEnable;
+
+/*!
+ @const kSCPropNetProxiesGopherPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesGopherPort;
+
+/*!
+ @const kSCPropNetProxiesGopherProxy
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesGopherProxy;
+
+/*!
+ @const kSCPropNetProxiesHTTPEnable
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPEnable;
+
+/*!
+ @const kSCPropNetProxiesHTTPPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPPort;
+
+/*!
+ @const kSCPropNetProxiesHTTPProxy
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPProxy;
+
+/*!
+ @const kSCPropNetProxiesHTTPSEnable
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPSEnable;
+
+/*!
+ @const kSCPropNetProxiesHTTPSPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPSPort;
+
+/*!
+ @const kSCPropNetProxiesHTTPSProxy
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPSProxy;
+
+/*!
+ @const kSCPropNetProxiesRTSPEnable
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesRTSPEnable;
+
+/*!
+ @const kSCPropNetProxiesRTSPPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesRTSPPort;
+
+/*!
+ @const kSCPropNetProxiesRTSPProxy
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesRTSPProxy;
+
+/*!
+ @const kSCPropNetProxiesSOCKSEnable
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesSOCKSEnable;
+
+/*!
+ @const kSCPropNetProxiesSOCKSPort
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesSOCKSPort;
+
+/*!
+ @const kSCPropNetProxiesSOCKSProxy
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesSOCKSProxy;
+
+/*!
+ @const kSCPropNetProxiesProxyAutoConfigEnable
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesProxyAutoConfigEnable;
+
+/*!
+ @const kSCPropNetProxiesProxyAutoConfigURLString
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesProxyAutoConfigURLString;
+
+/*!
+ @const kSCPropNetProxiesProxyAutoDiscoveryEnable
+ @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesProxyAutoDiscoveryEnable;
+
+/*!
+ @group kSCCompUsers Entity Keys
+ */
+
+/*!
+ @const kSCEntUsersConsoleUser
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntUsersConsoleUser;
+
+/*!
+ @group kSCCompSystem Properties
+ */
+
+/*!
+ @const kSCPropSystemComputerName
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropSystemComputerName;
+
+/*!
+ @const kSCPropSystemComputerNameEncoding
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropSystemComputerNameEncoding;
+
+/*!
+ @group SCDynamicStore "domain" prefixes
+ */
+
+/*!
+ @const kSCDynamicStoreDomainFile
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainFile;
+
+/*!
+ @const kSCDynamicStoreDomainPlugin
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainPlugin;
+
+/*!
+ @const kSCDynamicStoreDomainSetup
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainSetup;
+
+/*!
+ @const kSCDynamicStoreDomainState
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainState;
+
+/*!
+ @const kSCDynamicStoreDomainPrefs
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainPrefs;
+
+/*!
+ @group Preference ("location") Keys
+ */
+
+/*!
+ @const kSCDynamicStorePropSetupCurrentSet
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropSetupCurrentSet;
+
+/*!
+ @const kSCDynamicStorePropSetupLastUpdated
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropSetupLastUpdated;
+
+/*!
+ @group Common/shared Keys
+ */
+
+/*!
+ @const kSCDynamicStorePropNetInterfaces
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetInterfaces;
+
+/*!
+ @const kSCDynamicStorePropNetPrimaryInterface
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetPrimaryInterface;
+
+/*!
+ @const kSCDynamicStorePropNetPrimaryService
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetPrimaryService;
+
+/*!
+ @const kSCDynamicStorePropNetServiceIDs
+ @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetServiceIDs;
+
+/*!
+ @const kSCPropUsersConsoleUserName
+ @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropUsersConsoleUserName;
+
+/*!
+ @const kSCPropUsersConsoleUserUID
+ @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropUsersConsoleUserUID;
+
+/*!
+ @const kSCPropUsersConsoleUserGID
+ @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropUsersConsoleUserGID;
+
+#endif /* 0 */
+
+
+/* -------------------- Schema declarations -------------------- */
+
+
+#define kSCResvLink \
+ SC_SCHEMA_KV(kSCResvLink \
+ ,"__LINK__" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCResvLink,);
+
+#define kSCResvInactive \
+ SC_SCHEMA_KV(kSCResvInactive \
+ ,"__INACTIVE__" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCResvInactive,);
+
+#define kSCPropInterfaceName \
+ SC_SCHEMA_KV(kSCPropInterfaceName \
+ ,"InterfaceName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropInterfaceName,);
+
+#define kSCPropMACAddress \
+ SC_SCHEMA_KV(kSCPropMACAddress \
+ ,"MACAddress" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropMACAddress,);
+
+#define kSCPropUserDefinedName \
+ SC_SCHEMA_KV(kSCPropUserDefinedName \
+ ,"UserDefinedName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropUserDefinedName,);
+
+#define kSCPropVersion \
+ SC_SCHEMA_KV(kSCPropVersion \
+ ,"Version" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropVersion,);
+
+#define kSCPrefCurrentSet \
+ SC_SCHEMA_KV(kSCPrefCurrentSet \
+ ,"CurrentSet" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPrefCurrentSet,);
+
+#define kSCPrefNetworkServices \
+ SC_SCHEMA_KV(kSCPrefNetworkServices \
+ ,"NetworkServices" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCPrefNetworkServices,);
+
+#define kSCPrefSets \
+ SC_SCHEMA_KV(kSCPrefSets \
+ ,"Sets" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCPrefSets,);
+
+#define kSCPrefSystem \
+ SC_SCHEMA_KV(kSCPrefSystem \
+ ,"System" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCPrefSystem,);
+
+#define kSCCompNetwork \
+ SC_SCHEMA_KV(kSCCompNetwork \
+ ,"Network" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompNetwork,);
+
+#define kSCCompService \
+ SC_SCHEMA_KV(kSCCompService \
+ ,"Service" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompService,);
+
+#define kSCCompGlobal \
+ SC_SCHEMA_KV(kSCCompGlobal \
+ ,"Global" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompGlobal,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCCompHostNames \
+ SC_SCHEMA_KV(kSCCompHostNames \
+ ,"HostNames" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCCompHostNames, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCCompInterface \
+ SC_SCHEMA_KV(kSCCompInterface \
+ ,"Interface" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompInterface,);
+
+#define kSCCompSystem \
+ SC_SCHEMA_KV(kSCCompSystem \
+ ,"System" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompSystem,);
+
+#define kSCCompUsers \
+ SC_SCHEMA_KV(kSCCompUsers \
+ ,"Users" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompUsers,);
+
+#define kSCCompAnyRegex \
+ SC_SCHEMA_KV(kSCCompAnyRegex \
+ ,"[^/]+" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCCompAnyRegex,);
+
+#define kSCEntNetAirPort \
+ SC_SCHEMA_KV(kSCEntNetAirPort \
+ ,"AirPort" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetAirPort,);
+
+#define kSCEntNetAppleTalk \
+ SC_SCHEMA_KV(kSCEntNetAppleTalk \
+ ,"AppleTalk" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetAppleTalk,);
+
+#define kSCEntNetDHCP \
+ SC_SCHEMA_KV(kSCEntNetDHCP \
+ ,"DHCP" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetDHCP,);
+
+#define kSCEntNetDNS \
+ SC_SCHEMA_KV(kSCEntNetDNS \
+ ,"DNS" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetDNS,);
+
+#define kSCEntNetEthernet \
+ SC_SCHEMA_KV(kSCEntNetEthernet \
+ ,"Ethernet" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetEthernet,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetFireWire \
+ SC_SCHEMA_KV(kSCEntNetFireWire \
+ ,"FireWire" \
+ ,CFDictionary )
+#endif
+ SC_SCHEMA_DECLARATION(kSCEntNetFireWire, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCEntNetInterface \
+ SC_SCHEMA_KV(kSCEntNetInterface \
+ ,"Interface" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetInterface,);
+
+#define kSCEntNetIPv4 \
+ SC_SCHEMA_KV(kSCEntNetIPv4 \
+ ,"IPv4" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetIPv4,);
+
+#define kSCEntNetIPv6 \
+ SC_SCHEMA_KV(kSCEntNetIPv6 \
+ ,"IPv6" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetIPv6,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetL2TP \
+ SC_SCHEMA_KV(kSCEntNetL2TP \
+ ,"L2TP" \
+ ,CFDictionary )
+#endif
+ SC_SCHEMA_DECLARATION(kSCEntNetL2TP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCEntNetLink \
+ SC_SCHEMA_KV(kSCEntNetLink \
+ ,"Link" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetLink,);
+
+#define kSCEntNetModem \
+ SC_SCHEMA_KV(kSCEntNetModem \
+ ,"Modem" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetModem,);
+
+#define kSCEntNetNetInfo \
+ SC_SCHEMA_KV(kSCEntNetNetInfo \
+ ,"NetInfo" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetNetInfo,);
+
+#define kSCEntNetPPP \
+ SC_SCHEMA_KV(kSCEntNetPPP \
+ ,"PPP" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetPPP,);
+
+#define kSCEntNetPPPoE \
+ SC_SCHEMA_KV(kSCEntNetPPPoE \
+ ,"PPPoE" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetPPPoE,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetPPPSerial \
+ SC_SCHEMA_KV(kSCEntNetPPPSerial \
+ ,"PPPSerial" \
+ ,CFDictionary )
+#endif
+ SC_SCHEMA_DECLARATION(kSCEntNetPPPSerial, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetPPTP \
+ SC_SCHEMA_KV(kSCEntNetPPTP \
+ ,"PPTP" \
+ ,CFDictionary )
+#endif
+ SC_SCHEMA_DECLARATION(kSCEntNetPPTP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCEntNetProxies \
+ SC_SCHEMA_KV(kSCEntNetProxies \
+ ,"Proxies" \
+ ,CFDictionary )
+ SC_SCHEMA_DECLARATION(kSCEntNetProxies,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNet6to4 \
+ SC_SCHEMA_KV(kSCEntNet6to4 \
+ ,"6to4" \
+ ,CFDictionary )
+#endif
+ SC_SCHEMA_DECLARATION(kSCEntNet6to4, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetOverridePrimary \
+ SC_SCHEMA_KV(kSCPropNetOverridePrimary \
+ ,"OverridePrimary" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetOverridePrimary, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetServiceOrder \
+ SC_SCHEMA_KV(kSCPropNetServiceOrder \
+ ,"ServiceOrder" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetServiceOrder,);
+
+#define kSCPropNetPPPOverridePrimary \
+ SC_SCHEMA_KV(kSCPropNetPPPOverridePrimary \
+ ,"PPPOverridePrimary" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPOverridePrimary,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetInterfaces \
+ SC_SCHEMA_KV(kSCPropNetInterfaces \
+ ,"Interfaces" \
+ ,CFArray[CFString] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetInterfaces, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetLocalHostName \
+ SC_SCHEMA_KV(kSCPropNetLocalHostName \
+ ,"LocalHostName" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetLocalHostName, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAirPortAllowNetCreation \
+ SC_SCHEMA_KV(kSCPropNetAirPortAllowNetCreation \
+ ,"AllowNetCreation" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortAllowNetCreation, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetAirPortAuthPassword \
+ SC_SCHEMA_KV(kSCPropNetAirPortAuthPassword \
+ ,"AuthPassword" \
+ ,CFData )
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPassword,);
+
+#define kSCPropNetAirPortAuthPasswordEncryption \
+ SC_SCHEMA_KV(kSCPropNetAirPortAuthPasswordEncryption \
+ ,"AuthPasswordEncryption" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPasswordEncryption,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAirPortJoinMode \
+ SC_SCHEMA_KV(kSCPropNetAirPortJoinMode \
+ ,"JoinMode" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortJoinMode, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetAirPortPowerEnabled \
+ SC_SCHEMA_KV(kSCPropNetAirPortPowerEnabled \
+ ,"PowerEnabled" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortPowerEnabled,);
+
+#define kSCPropNetAirPortPreferredNetwork \
+ SC_SCHEMA_KV(kSCPropNetAirPortPreferredNetwork \
+ ,"PreferredNetwork" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortPreferredNetwork,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAirPortSavePasswords \
+ SC_SCHEMA_KV(kSCPropNetAirPortSavePasswords \
+ ,"SavePasswords" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetAirPortSavePasswords, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetAirPortJoinModeAutomatic \
+ SC_SCHEMA_KV(kSCValNetAirPortJoinModeAutomatic \
+ ,"Automatic" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeAutomatic, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetAirPortJoinModePreferred \
+ SC_SCHEMA_KV(kSCValNetAirPortJoinModePreferred \
+ ,"Preferred" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModePreferred, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetAirPortJoinModeRecent \
+ SC_SCHEMA_KV(kSCValNetAirPortJoinModeRecent \
+ ,"Recent" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeRecent, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetAirPortJoinModeStrongest \
+ SC_SCHEMA_KV(kSCValNetAirPortJoinModeStrongest \
+ ,"Strongest" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeStrongest, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetAirPortAuthPasswordEncryptionKeychain \
+ SC_SCHEMA_KV(kSCValNetAirPortAuthPasswordEncryptionKeychain \
+ ,"Keychain" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetAirPortAuthPasswordEncryptionKeychain, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetAppleTalkComputerName \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkComputerName \
+ ,"ComputerName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkComputerName,);
+
+#define kSCPropNetAppleTalkComputerNameEncoding \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkComputerNameEncoding \
+ ,"ComputerNameEncoding" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkComputerNameEncoding,);
+
+#define kSCPropNetAppleTalkConfigMethod \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkConfigMethod \
+ ,"ConfigMethod" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkConfigMethod,);
+
+#define kSCPropNetAppleTalkDefaultZone \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkDefaultZone \
+ ,"DefaultZone" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkDefaultZone,);
+
+#define kSCPropNetAppleTalkNetworkID \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkNetworkID \
+ ,"NetworkID" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkNetworkID,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAppleTalkNetworkRange \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkNetworkRange \
+ ,"NetworkRange" \
+ ,CFArray[CFNumber] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkNetworkRange, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetAppleTalkNodeID \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkNodeID \
+ ,"NodeID" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkNodeID,);
+
+#define kSCPropNetAppleTalkSeedNetworkRange \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkSeedNetworkRange \
+ ,"SeedNetworkRange" \
+ ,CFArray[CFNumber] )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkSeedNetworkRange,);
+
+#define kSCPropNetAppleTalkSeedZones \
+ SC_SCHEMA_KV(kSCPropNetAppleTalkSeedZones \
+ ,"SeedZones" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkSeedZones,);
+
+#define kSCValNetAppleTalkConfigMethodNode \
+ SC_SCHEMA_KV(kSCValNetAppleTalkConfigMethodNode \
+ ,"Node" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetAppleTalkConfigMethodNode,);
+
+#define kSCValNetAppleTalkConfigMethodRouter \
+ SC_SCHEMA_KV(kSCValNetAppleTalkConfigMethodRouter \
+ ,"Router" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetAppleTalkConfigMethodRouter,);
+
+#define kSCValNetAppleTalkConfigMethodSeedRouter \
+ SC_SCHEMA_KV(kSCValNetAppleTalkConfigMethodSeedRouter \
+ ,"SeedRouter" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetAppleTalkConfigMethodSeedRouter,);
+
+#define kSCPropNetDNSDomainName \
+ SC_SCHEMA_KV(kSCPropNetDNSDomainName \
+ ,"DomainName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSDomainName,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSOptions \
+ SC_SCHEMA_KV(kSCPropNetDNSOptions \
+ ,"Options" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSOptions, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetDNSSearchDomains \
+ SC_SCHEMA_KV(kSCPropNetDNSSearchDomains \
+ ,"SearchDomains" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSSearchDomains,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSSearchOrder \
+ SC_SCHEMA_KV(kSCPropNetDNSSearchOrder \
+ ,"SearchOrder" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSSearchOrder, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetDNSServerAddresses \
+ SC_SCHEMA_KV(kSCPropNetDNSServerAddresses \
+ ,"ServerAddresses" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSServerAddresses,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSServerPort \
+ SC_SCHEMA_KV(kSCPropNetDNSServerPort \
+ ,"ServerPort" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSServerPort, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSServerTimeout \
+ SC_SCHEMA_KV(kSCPropNetDNSServerTimeout \
+ ,"ServerTimeout" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSServerTimeout, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetDNSSortList \
+ SC_SCHEMA_KV(kSCPropNetDNSSortList \
+ ,"SortList" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSSortList,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSSupplementalMatchDomains \
+ SC_SCHEMA_KV(kSCPropNetDNSSupplementalMatchDomains \
+ ,"SupplementalMatchDomains" \
+ ,CFArray[CFString] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSSupplementalMatchDomains, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSSupplementalMatchOrders \
+ SC_SCHEMA_KV(kSCPropNetDNSSupplementalMatchOrders \
+ ,"SupplementalMatchOrders" \
+ ,CFArray[CFNumber] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetDNSSupplementalMatchOrders, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetEthernetMediaSubType \
+ SC_SCHEMA_KV(kSCPropNetEthernetMediaSubType \
+ ,"MediaSubType" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetEthernetMediaSubType, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetEthernetMediaOptions \
+ SC_SCHEMA_KV(kSCPropNetEthernetMediaOptions \
+ ,"MediaOptions" \
+ ,CFArray[CFString] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetEthernetMediaOptions, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetEthernetMTU \
+ SC_SCHEMA_KV(kSCPropNetEthernetMTU \
+ ,"MTU" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetEthernetMTU, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetInterfaceDeviceName \
+ SC_SCHEMA_KV(kSCPropNetInterfaceDeviceName \
+ ,"DeviceName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetInterfaceDeviceName,);
+
+#define kSCPropNetInterfaceHardware \
+ SC_SCHEMA_KV(kSCPropNetInterfaceHardware \
+ ,"Hardware" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetInterfaceHardware,);
+
+#define kSCPropNetInterfaceType \
+ SC_SCHEMA_KV(kSCPropNetInterfaceType \
+ ,"Type" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetInterfaceType,);
+
+#define kSCPropNetInterfaceSubType \
+ SC_SCHEMA_KV(kSCPropNetInterfaceSubType \
+ ,"SubType" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetInterfaceSubType,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetInterfaceSupportsModemOnHold \
+ SC_SCHEMA_KV(kSCPropNetInterfaceSupportsModemOnHold \
+ ,"SupportsModemOnHold" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetInterfaceSupportsModemOnHold, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCValNetInterfaceTypeEthernet \
+ SC_SCHEMA_KV(kSCValNetInterfaceTypeEthernet \
+ ,"Ethernet" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceTypeEthernet,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetInterfaceTypeFireWire \
+ SC_SCHEMA_KV(kSCValNetInterfaceTypeFireWire \
+ ,"FireWire" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceTypeFireWire, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetInterfaceTypePPP \
+ SC_SCHEMA_KV(kSCValNetInterfaceTypePPP \
+ ,"PPP" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceTypePPP,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetInterfaceType6to4 \
+ SC_SCHEMA_KV(kSCValNetInterfaceType6to4 \
+ ,"6to4" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceType6to4, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetInterfaceSubTypePPPoE \
+ SC_SCHEMA_KV(kSCValNetInterfaceSubTypePPPoE \
+ ,"PPPoE" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypePPPoE,);
+
+#define kSCValNetInterfaceSubTypePPPSerial \
+ SC_SCHEMA_KV(kSCValNetInterfaceSubTypePPPSerial \
+ ,"PPPSerial" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypePPPSerial,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetInterfaceSubTypePPTP \
+ SC_SCHEMA_KV(kSCValNetInterfaceSubTypePPTP \
+ ,"PPTP" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypePPTP, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetInterfaceSubTypeL2TP \
+ SC_SCHEMA_KV(kSCValNetInterfaceSubTypeL2TP \
+ ,"L2TP" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypeL2TP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetIPv4Addresses \
+ SC_SCHEMA_KV(kSCPropNetIPv4Addresses \
+ ,"Addresses" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4Addresses,);
+
+#define kSCPropNetIPv4ConfigMethod \
+ SC_SCHEMA_KV(kSCPropNetIPv4ConfigMethod \
+ ,"ConfigMethod" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4ConfigMethod,);
+
+#define kSCPropNetIPv4DHCPClientID \
+ SC_SCHEMA_KV(kSCPropNetIPv4DHCPClientID \
+ ,"DHCPClientID" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4DHCPClientID,);
+
+#define kSCPropNetIPv4Router \
+ SC_SCHEMA_KV(kSCPropNetIPv4Router \
+ ,"Router" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4Router,);
+
+#define kSCPropNetIPv4SubnetMasks \
+ SC_SCHEMA_KV(kSCPropNetIPv4SubnetMasks \
+ ,"SubnetMasks" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4SubnetMasks,);
+
+#define kSCPropNetIPv4DestAddresses \
+ SC_SCHEMA_KV(kSCPropNetIPv4DestAddresses \
+ ,"DestAddresses" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4DestAddresses,);
+
+#define kSCPropNetIPv4BroadcastAddresses \
+ SC_SCHEMA_KV(kSCPropNetIPv4BroadcastAddresses \
+ ,"BroadcastAddresses" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv4BroadcastAddresses,);
+
+#define kSCValNetIPv4ConfigMethodBOOTP \
+ SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodBOOTP \
+ ,"BOOTP" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodBOOTP,);
+
+#define kSCValNetIPv4ConfigMethodDHCP \
+ SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodDHCP \
+ ,"DHCP" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodDHCP,);
+
+#define kSCValNetIPv4ConfigMethodINFORM \
+ SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodINFORM \
+ ,"INFORM" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodINFORM,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetIPv4ConfigMethodLinkLocal \
+ SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodLinkLocal \
+ ,"LinkLocal" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodLinkLocal, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCValNetIPv4ConfigMethodManual \
+ SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodManual \
+ ,"Manual" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodManual,);
+
+#define kSCValNetIPv4ConfigMethodPPP \
+ SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodPPP \
+ ,"PPP" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodPPP,);
+
+#define kSCPropNetIPv6Addresses \
+ SC_SCHEMA_KV(kSCPropNetIPv6Addresses \
+ ,"Addresses" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv6Addresses,);
+
+#define kSCPropNetIPv6ConfigMethod \
+ SC_SCHEMA_KV(kSCPropNetIPv6ConfigMethod \
+ ,"ConfigMethod" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv6ConfigMethod,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6DestAddresses \
+ SC_SCHEMA_KV(kSCPropNetIPv6DestAddresses \
+ ,"DestAddresses" \
+ ,CFArray[CFString] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv6DestAddresses, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6Flags \
+ SC_SCHEMA_KV(kSCPropNetIPv6Flags \
+ ,"Flags" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv6Flags, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6PrefixLength \
+ SC_SCHEMA_KV(kSCPropNetIPv6PrefixLength \
+ ,"PrefixLength" \
+ ,CFArray[CFNumber] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv6PrefixLength, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6Router \
+ SC_SCHEMA_KV(kSCPropNetIPv6Router \
+ ,"Router" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetIPv6Router, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethodAutomatic \
+ SC_SCHEMA_KV(kSCValNetIPv6ConfigMethodAutomatic \
+ ,"Automatic" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethodAutomatic, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethodManual \
+ SC_SCHEMA_KV(kSCValNetIPv6ConfigMethodManual \
+ ,"Manual" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethodManual, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethodRouterAdvertisement \
+ SC_SCHEMA_KV(kSCValNetIPv6ConfigMethodRouterAdvertisement \
+ ,"RouterAdvertisement" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethodRouterAdvertisement, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethod6to4 \
+ SC_SCHEMA_KV(kSCValNetIPv6ConfigMethod6to4 \
+ ,"6to4" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethod6to4, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNet6to4Relay \
+ SC_SCHEMA_KV(kSCPropNet6to4Relay \
+ ,"Relay" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNet6to4Relay, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetLinkActive \
+ SC_SCHEMA_KV(kSCPropNetLinkActive \
+ ,"Active" \
+ ,CFBoolean )
+ SC_SCHEMA_DECLARATION(kSCPropNetLinkActive,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetLinkDetaching \
+ SC_SCHEMA_KV(kSCPropNetLinkDetaching \
+ ,"Detaching" \
+ ,CFBoolean )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetLinkDetaching, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetModemConnectionScript \
+ SC_SCHEMA_KV(kSCPropNetModemConnectionScript \
+ ,"ConnectionScript" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemConnectionScript,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemConnectSpeed \
+ SC_SCHEMA_KV(kSCPropNetModemConnectSpeed \
+ ,"ConnectSpeed" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemConnectSpeed, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetModemDataCompression \
+ SC_SCHEMA_KV(kSCPropNetModemDataCompression \
+ ,"DataCompression" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemDataCompression,);
+
+#define kSCPropNetModemDialMode \
+ SC_SCHEMA_KV(kSCPropNetModemDialMode \
+ ,"DialMode" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemDialMode,);
+
+#define kSCPropNetModemErrorCorrection \
+ SC_SCHEMA_KV(kSCPropNetModemErrorCorrection \
+ ,"ErrorCorrection" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemErrorCorrection,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldCallWaitingAudibleAlert \
+ SC_SCHEMA_KV(kSCPropNetModemHoldCallWaitingAudibleAlert \
+ ,"HoldCallWaitingAudibleAlert" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemHoldCallWaitingAudibleAlert, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldDisconnectOnAnswer \
+ SC_SCHEMA_KV(kSCPropNetModemHoldDisconnectOnAnswer \
+ ,"HoldDisconnectOnAnswer" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemHoldDisconnectOnAnswer, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldEnabled \
+ SC_SCHEMA_KV(kSCPropNetModemHoldEnabled \
+ ,"HoldEnabled" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemHoldEnabled, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldReminder \
+ SC_SCHEMA_KV(kSCPropNetModemHoldReminder \
+ ,"HoldReminder" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemHoldReminder, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldReminderTime \
+ SC_SCHEMA_KV(kSCPropNetModemHoldReminderTime \
+ ,"HoldReminderTime" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemHoldReminderTime, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemNote \
+ SC_SCHEMA_KV(kSCPropNetModemNote \
+ ,"Note" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetModemNote, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetModemPulseDial \
+ SC_SCHEMA_KV(kSCPropNetModemPulseDial \
+ ,"PulseDial" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemPulseDial,);
+
+#define kSCPropNetModemSpeaker \
+ SC_SCHEMA_KV(kSCPropNetModemSpeaker \
+ ,"Speaker" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemSpeaker,);
+
+#define kSCPropNetModemSpeed \
+ SC_SCHEMA_KV(kSCPropNetModemSpeed \
+ ,"Speed" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetModemSpeed,);
+
+#define kSCValNetModemDialModeIgnoreDialTone \
+ SC_SCHEMA_KV(kSCValNetModemDialModeIgnoreDialTone \
+ ,"IgnoreDialTone" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetModemDialModeIgnoreDialTone,);
+
+#define kSCValNetModemDialModeManual \
+ SC_SCHEMA_KV(kSCValNetModemDialModeManual \
+ ,"Manual" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetModemDialModeManual,);
+
+#define kSCValNetModemDialModeWaitForDialTone \
+ SC_SCHEMA_KV(kSCValNetModemDialModeWaitForDialTone \
+ ,"WaitForDialTone" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetModemDialModeWaitForDialTone,);
+
+#define kSCPropNetNetInfoBindingMethods \
+ SC_SCHEMA_KV(kSCPropNetNetInfoBindingMethods \
+ ,"BindingMethods" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetNetInfoBindingMethods,);
+
+#define kSCPropNetNetInfoServerAddresses \
+ SC_SCHEMA_KV(kSCPropNetNetInfoServerAddresses \
+ ,"ServerAddresses" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetNetInfoServerAddresses,);
+
+#define kSCPropNetNetInfoServerTags \
+ SC_SCHEMA_KV(kSCPropNetNetInfoServerTags \
+ ,"ServerTags" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetNetInfoServerTags,);
+
+#define kSCPropNetNetInfoBroadcastServerTag \
+ SC_SCHEMA_KV(kSCPropNetNetInfoBroadcastServerTag \
+ ,"BroadcastServerTag" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetNetInfoBroadcastServerTag,);
+
+#define kSCValNetNetInfoBindingMethodsBroadcast \
+ SC_SCHEMA_KV(kSCValNetNetInfoBindingMethodsBroadcast \
+ ,"Broadcast" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetNetInfoBindingMethodsBroadcast,);
+
+#define kSCValNetNetInfoBindingMethodsDHCP \
+ SC_SCHEMA_KV(kSCValNetNetInfoBindingMethodsDHCP \
+ ,"DHCP" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetNetInfoBindingMethodsDHCP,);
+
+#define kSCValNetNetInfoBindingMethodsManual \
+ SC_SCHEMA_KV(kSCValNetNetInfoBindingMethodsManual \
+ ,"Manual" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetNetInfoBindingMethodsManual,);
+
+#define kSCValNetNetInfoDefaultServerTag \
+ SC_SCHEMA_KV(kSCValNetNetInfoDefaultServerTag \
+ ,"network" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCValNetNetInfoDefaultServerTag,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPACSPEnabled \
+ SC_SCHEMA_KV(kSCPropNetPPPACSPEnabled \
+ ,"ACSPEnabled" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPACSPEnabled, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPConnectTime \
+ SC_SCHEMA_KV(kSCPropNetPPPConnectTime \
+ ,"ConnectTime" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPConnectTime, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPDeviceLastCause \
+ SC_SCHEMA_KV(kSCPropNetPPPDeviceLastCause \
+ ,"DeviceLastCause" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDeviceLastCause, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetPPPDialOnDemand \
+ SC_SCHEMA_KV(kSCPropNetPPPDialOnDemand \
+ ,"DialOnDemand" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDialOnDemand,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPDisconnectOnFastUserSwitch \
+ SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnFastUserSwitch \
+ ,"DisconnectOnFastUserSwitch" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnFastUserSwitch, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetPPPDisconnectOnIdle \
+ SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnIdle \
+ ,"DisconnectOnIdle" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnIdle,);
+
+#define kSCPropNetPPPDisconnectOnIdleTimer \
+ SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnIdleTimer \
+ ,"DisconnectOnIdleTimer" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnIdleTimer,);
+
+#define kSCPropNetPPPDisconnectOnLogout \
+ SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnLogout \
+ ,"DisconnectOnLogout" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnLogout,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPDisconnectOnSleep \
+ SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnSleep \
+ ,"DisconnectOnSleep" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnSleep, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPDisconnectTime \
+ SC_SCHEMA_KV(kSCPropNetPPPDisconnectTime \
+ ,"DisconnectTime" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectTime, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPIdleReminderTimer \
+ SC_SCHEMA_KV(kSCPropNetPPPIdleReminderTimer \
+ ,"IdleReminderTimer" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPIdleReminderTimer,);
+
+#define kSCPropNetPPPIdleReminder \
+ SC_SCHEMA_KV(kSCPropNetPPPIdleReminder \
+ ,"IdleReminder" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPIdleReminder,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPLastCause \
+ SC_SCHEMA_KV(kSCPropNetPPPLastCause \
+ ,"LastCause" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLastCause, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetPPPLogfile \
+ SC_SCHEMA_KV(kSCPropNetPPPLogfile \
+ ,"Logfile" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLogfile,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPPlugins \
+ SC_SCHEMA_KV(kSCPropNetPPPPlugins \
+ ,"Plugins" \
+ ,CFArray[CFString] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPPlugins, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPRetryConnectTime \
+ SC_SCHEMA_KV(kSCPropNetPPPRetryConnectTime \
+ ,"RetryConnectTime" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPRetryConnectTime, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPSessionTimer \
+ SC_SCHEMA_KV(kSCPropNetPPPSessionTimer \
+ ,"SessionTimer" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPSessionTimer,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPStatus \
+ SC_SCHEMA_KV(kSCPropNetPPPStatus \
+ ,"Status" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPStatus, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPUseSessionTimer \
+ SC_SCHEMA_KV(kSCPropNetPPPUseSessionTimer \
+ ,"UseSessionTimer" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPUseSessionTimer, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetPPPVerboseLogging \
+ SC_SCHEMA_KV(kSCPropNetPPPVerboseLogging \
+ ,"VerboseLogging" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPVerboseLogging,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPAuthEAPPlugins \
+ SC_SCHEMA_KV(kSCPropNetPPPAuthEAPPlugins \
+ ,"AuthEAPPlugins" \
+ ,CFArray[CFString] )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthEAPPlugins, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPAuthName \
+ SC_SCHEMA_KV(kSCPropNetPPPAuthName \
+ ,"AuthName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthName,);
+
+#define kSCPropNetPPPAuthPassword \
+ SC_SCHEMA_KV(kSCPropNetPPPAuthPassword \
+ ,"AuthPassword" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthPassword,);
+
+#define kSCPropNetPPPAuthPasswordEncryption \
+ SC_SCHEMA_KV(kSCPropNetPPPAuthPasswordEncryption \
+ ,"AuthPasswordEncryption" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthPasswordEncryption,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPAuthPrompt \
+ SC_SCHEMA_KV(kSCPropNetPPPAuthPrompt \
+ ,"AuthPrompt" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthPrompt, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPAuthProtocol \
+ SC_SCHEMA_KV(kSCPropNetPPPAuthProtocol \
+ ,"AuthProtocol" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthProtocol,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthPasswordEncryptionKeychain \
+ SC_SCHEMA_KV(kSCValNetPPPAuthPasswordEncryptionKeychain \
+ ,"Keychain" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthPasswordEncryptionKeychain, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthPromptBefore \
+ SC_SCHEMA_KV(kSCValNetPPPAuthPromptBefore \
+ ,"Before" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthPromptBefore, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthPromptAfter \
+ SC_SCHEMA_KV(kSCValNetPPPAuthPromptAfter \
+ ,"After" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthPromptAfter, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetPPPAuthProtocolCHAP \
+ SC_SCHEMA_KV(kSCValNetPPPAuthProtocolCHAP \
+ ,"CHAP" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolCHAP,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthProtocolEAP \
+ SC_SCHEMA_KV(kSCValNetPPPAuthProtocolEAP \
+ ,"EAP" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolEAP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthProtocolMSCHAP1 \
+ SC_SCHEMA_KV(kSCValNetPPPAuthProtocolMSCHAP1 \
+ ,"MSCHAP1" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolMSCHAP1, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthProtocolMSCHAP2 \
+ SC_SCHEMA_KV(kSCValNetPPPAuthProtocolMSCHAP2 \
+ ,"MSCHAP2" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolMSCHAP2, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetPPPAuthProtocolPAP \
+ SC_SCHEMA_KV(kSCValNetPPPAuthProtocolPAP \
+ ,"PAP" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolPAP,);
+
+#define kSCPropNetPPPCommAlternateRemoteAddress \
+ SC_SCHEMA_KV(kSCPropNetPPPCommAlternateRemoteAddress \
+ ,"CommAlternateRemoteAddress" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommAlternateRemoteAddress,);
+
+#define kSCPropNetPPPCommConnectDelay \
+ SC_SCHEMA_KV(kSCPropNetPPPCommConnectDelay \
+ ,"CommConnectDelay" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommConnectDelay,);
+
+#define kSCPropNetPPPCommDisplayTerminalWindow \
+ SC_SCHEMA_KV(kSCPropNetPPPCommDisplayTerminalWindow \
+ ,"CommDisplayTerminalWindow" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommDisplayTerminalWindow,);
+
+#define kSCPropNetPPPCommRedialCount \
+ SC_SCHEMA_KV(kSCPropNetPPPCommRedialCount \
+ ,"CommRedialCount" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRedialCount,);
+
+#define kSCPropNetPPPCommRedialEnabled \
+ SC_SCHEMA_KV(kSCPropNetPPPCommRedialEnabled \
+ ,"CommRedialEnabled" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRedialEnabled,);
+
+#define kSCPropNetPPPCommRedialInterval \
+ SC_SCHEMA_KV(kSCPropNetPPPCommRedialInterval \
+ ,"CommRedialInterval" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRedialInterval,);
+
+#define kSCPropNetPPPCommRemoteAddress \
+ SC_SCHEMA_KV(kSCPropNetPPPCommRemoteAddress \
+ ,"CommRemoteAddress" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRemoteAddress,);
+
+#define kSCPropNetPPPCommTerminalScript \
+ SC_SCHEMA_KV(kSCPropNetPPPCommTerminalScript \
+ ,"CommTerminalScript" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommTerminalScript,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPCommUseTerminalScript \
+ SC_SCHEMA_KV(kSCPropNetPPPCommUseTerminalScript \
+ ,"CommUseTerminalScript" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCommUseTerminalScript, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPCCPEnabled \
+ SC_SCHEMA_KV(kSCPropNetPPPCCPEnabled \
+ ,"CCPEnabled" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCCPEnabled, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPCCPMPPE40Enabled \
+ SC_SCHEMA_KV(kSCPropNetPPPCCPMPPE40Enabled \
+ ,"CCPMPPE40Enabled" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCCPMPPE40Enabled, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPCCPMPPE128Enabled \
+ SC_SCHEMA_KV(kSCPropNetPPPCCPMPPE128Enabled \
+ ,"CCPMPPE128Enabled" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPCCPMPPE128Enabled, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetPPPIPCPCompressionVJ \
+ SC_SCHEMA_KV(kSCPropNetPPPIPCPCompressionVJ \
+ ,"IPCPCompressionVJ" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPIPCPCompressionVJ,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPIPCPUsePeerDNS \
+ SC_SCHEMA_KV(kSCPropNetPPPIPCPUsePeerDNS \
+ ,"IPCPUsePeerDNS" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPIPCPUsePeerDNS, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetPPPLCPEchoEnabled \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPEchoEnabled \
+ ,"LCPEchoEnabled" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPEchoEnabled,);
+
+#define kSCPropNetPPPLCPEchoFailure \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPEchoFailure \
+ ,"LCPEchoFailure" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPEchoFailure,);
+
+#define kSCPropNetPPPLCPEchoInterval \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPEchoInterval \
+ ,"LCPEchoInterval" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPEchoInterval,);
+
+#define kSCPropNetPPPLCPCompressionACField \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPCompressionACField \
+ ,"LCPCompressionACField" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPCompressionACField,);
+
+#define kSCPropNetPPPLCPCompressionPField \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPCompressionPField \
+ ,"LCPCompressionPField" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPCompressionPField,);
+
+#define kSCPropNetPPPLCPMRU \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPMRU \
+ ,"LCPMRU" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPMRU,);
+
+#define kSCPropNetPPPLCPMTU \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPMTU \
+ ,"LCPMTU" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPMTU,);
+
+#define kSCPropNetPPPLCPReceiveACCM \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPReceiveACCM \
+ ,"LCPReceiveACCM" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPReceiveACCM,);
+
+#define kSCPropNetPPPLCPTransmitACCM \
+ SC_SCHEMA_KV(kSCPropNetPPPLCPTransmitACCM \
+ ,"LCPTransmitACCM" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPTransmitACCM,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetL2TPIPSecSharedSecret \
+ SC_SCHEMA_KV(kSCPropNetL2TPIPSecSharedSecret \
+ ,"IPSecSharedSecret" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetL2TPIPSecSharedSecret, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetL2TPIPSecSharedSecretEncryption \
+ SC_SCHEMA_KV(kSCPropNetL2TPIPSecSharedSecretEncryption \
+ ,"IPSecSharedSecretEncryption" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetL2TPIPSecSharedSecretEncryption, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetL2TPTransport \
+ SC_SCHEMA_KV(kSCPropNetL2TPTransport \
+ ,"Transport" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetL2TPTransport, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetL2TPIPSecSharedSecretEncryptionKeychain \
+ SC_SCHEMA_KV(kSCValNetL2TPIPSecSharedSecretEncryptionKeychain \
+ ,"Keychain" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetL2TPIPSecSharedSecretEncryptionKeychain, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetL2TPTransportIP \
+ SC_SCHEMA_KV(kSCValNetL2TPTransportIP \
+ ,"IP" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetL2TPTransportIP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetL2TPTransportIPSec \
+ SC_SCHEMA_KV(kSCValNetL2TPTransportIPSec \
+ ,"IPSec" \
+ , )
+#endif
+ SC_SCHEMA_DECLARATION(kSCValNetL2TPTransportIPSec, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetProxiesExceptionsList \
+ SC_SCHEMA_KV(kSCPropNetProxiesExceptionsList \
+ ,"ExceptionsList" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesExceptionsList,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesExcludeSimpleHostnames \
+ SC_SCHEMA_KV(kSCPropNetProxiesExcludeSimpleHostnames \
+ ,"ExcludeSimpleHostnames" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesExcludeSimpleHostnames, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetProxiesFTPEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesFTPEnable \
+ ,"FTPEnable" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPEnable,);
+
+#define kSCPropNetProxiesFTPPassive \
+ SC_SCHEMA_KV(kSCPropNetProxiesFTPPassive \
+ ,"FTPPassive" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPPassive,);
+
+#define kSCPropNetProxiesFTPPort \
+ SC_SCHEMA_KV(kSCPropNetProxiesFTPPort \
+ ,"FTPPort" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPPort,);
+
+#define kSCPropNetProxiesFTPProxy \
+ SC_SCHEMA_KV(kSCPropNetProxiesFTPProxy \
+ ,"FTPProxy" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPProxy,);
+
+#define kSCPropNetProxiesGopherEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesGopherEnable \
+ ,"GopherEnable" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesGopherEnable,);
+
+#define kSCPropNetProxiesGopherPort \
+ SC_SCHEMA_KV(kSCPropNetProxiesGopherPort \
+ ,"GopherPort" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesGopherPort,);
+
+#define kSCPropNetProxiesGopherProxy \
+ SC_SCHEMA_KV(kSCPropNetProxiesGopherProxy \
+ ,"GopherProxy" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesGopherProxy,);
+
+#define kSCPropNetProxiesHTTPEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesHTTPEnable \
+ ,"HTTPEnable" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPEnable,);
+
+#define kSCPropNetProxiesHTTPPort \
+ SC_SCHEMA_KV(kSCPropNetProxiesHTTPPort \
+ ,"HTTPPort" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPPort,);
+
+#define kSCPropNetProxiesHTTPProxy \
+ SC_SCHEMA_KV(kSCPropNetProxiesHTTPProxy \
+ ,"HTTPProxy" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPProxy,);
+
+#define kSCPropNetProxiesHTTPSEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesHTTPSEnable \
+ ,"HTTPSEnable" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPSEnable,);
+
+#define kSCPropNetProxiesHTTPSPort \
+ SC_SCHEMA_KV(kSCPropNetProxiesHTTPSPort \
+ ,"HTTPSPort" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPSPort,);
+
+#define kSCPropNetProxiesHTTPSProxy \
+ SC_SCHEMA_KV(kSCPropNetProxiesHTTPSProxy \
+ ,"HTTPSProxy" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPSProxy,);
+
+#define kSCPropNetProxiesRTSPEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesRTSPEnable \
+ ,"RTSPEnable" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesRTSPEnable,);
+
+#define kSCPropNetProxiesRTSPPort \
+ SC_SCHEMA_KV(kSCPropNetProxiesRTSPPort \
+ ,"RTSPPort" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesRTSPPort,);
+
+#define kSCPropNetProxiesRTSPProxy \
+ SC_SCHEMA_KV(kSCPropNetProxiesRTSPProxy \
+ ,"RTSPProxy" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesRTSPProxy,);
+
+#define kSCPropNetProxiesSOCKSEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesSOCKSEnable \
+ ,"SOCKSEnable" \
+ ,CFNumber (0 or 1) )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesSOCKSEnable,);
+
+#define kSCPropNetProxiesSOCKSPort \
+ SC_SCHEMA_KV(kSCPropNetProxiesSOCKSPort \
+ ,"SOCKSPort" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesSOCKSPort,);
+
+#define kSCPropNetProxiesSOCKSProxy \
+ SC_SCHEMA_KV(kSCPropNetProxiesSOCKSProxy \
+ ,"SOCKSProxy" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesSOCKSProxy,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesProxyAutoConfigEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesProxyAutoConfigEnable \
+ ,"ProxyAutoConfigEnable" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesProxyAutoConfigEnable, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesProxyAutoConfigURLString \
+ SC_SCHEMA_KV(kSCPropNetProxiesProxyAutoConfigURLString \
+ ,"ProxyAutoConfigURLString" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesProxyAutoConfigURLString, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesProxyAutoDiscoveryEnable \
+ SC_SCHEMA_KV(kSCPropNetProxiesProxyAutoDiscoveryEnable \
+ ,"ProxyAutoDiscoveryEnable" \
+ ,CFNumber (0 or 1) )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropNetProxiesProxyAutoDiscoveryEnable, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCEntUsersConsoleUser \
+ SC_SCHEMA_KV(kSCEntUsersConsoleUser \
+ ,"ConsoleUser" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCEntUsersConsoleUser,);
+
+#define kSCPropSystemComputerName \
+ SC_SCHEMA_KV(kSCPropSystemComputerName \
+ ,"ComputerName" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCPropSystemComputerName,);
+
+#define kSCPropSystemComputerNameEncoding \
+ SC_SCHEMA_KV(kSCPropSystemComputerNameEncoding \
+ ,"ComputerNameEncoding" \
+ ,CFNumber )
+ SC_SCHEMA_DECLARATION(kSCPropSystemComputerNameEncoding,);
+
+#define kSCDynamicStoreDomainFile \
+ SC_SCHEMA_KV(kSCDynamicStoreDomainFile \
+ ,"File:" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainFile,);
+
+#define kSCDynamicStoreDomainPlugin \
+ SC_SCHEMA_KV(kSCDynamicStoreDomainPlugin \
+ ,"Plugin:" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainPlugin,);
+
+#define kSCDynamicStoreDomainSetup \
+ SC_SCHEMA_KV(kSCDynamicStoreDomainSetup \
+ ,"Setup:" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainSetup,);
+
+#define kSCDynamicStoreDomainState \
+ SC_SCHEMA_KV(kSCDynamicStoreDomainState \
+ ,"State:" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainState,);
+
+#define kSCDynamicStoreDomainPrefs \
+ SC_SCHEMA_KV(kSCDynamicStoreDomainPrefs \
+ ,"Prefs:" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainPrefs,);
+
+#define kSCDynamicStorePropSetupCurrentSet \
+ SC_SCHEMA_KV(kSCDynamicStorePropSetupCurrentSet \
+ ,"CurrentSet" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCDynamicStorePropSetupCurrentSet,);
+
+#define kSCDynamicStorePropSetupLastUpdated \
+ SC_SCHEMA_KV(kSCDynamicStorePropSetupLastUpdated \
+ ,"LastUpdated" \
+ , )
+ SC_SCHEMA_DECLARATION(kSCDynamicStorePropSetupLastUpdated,);
+
+#define kSCDynamicStorePropNetInterfaces \
+ SC_SCHEMA_KV(kSCDynamicStorePropNetInterfaces \
+ ,"Interfaces" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetInterfaces,);
+
+#define kSCDynamicStorePropNetPrimaryInterface \
+ SC_SCHEMA_KV(kSCDynamicStorePropNetPrimaryInterface \
+ ,"PrimaryInterface" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetPrimaryInterface,);
+
+#define kSCDynamicStorePropNetPrimaryService \
+ SC_SCHEMA_KV(kSCDynamicStorePropNetPrimaryService \
+ ,"PrimaryService" \
+ ,CFString )
+ SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetPrimaryService,);
+
+#define kSCDynamicStorePropNetServiceIDs \
+ SC_SCHEMA_KV(kSCDynamicStorePropNetServiceIDs \
+ ,"ServiceIDs" \
+ ,CFArray[CFString] )
+ SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetServiceIDs,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \
+ MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
+#define kSCPropUsersConsoleUserName \
+ SC_SCHEMA_KV(kSCPropUsersConsoleUserName \
+ ,"Name" \
+ ,CFString )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropUsersConsoleUserName, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \
+ MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
+#define kSCPropUsersConsoleUserUID \
+ SC_SCHEMA_KV(kSCPropUsersConsoleUserUID \
+ ,"UID" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropUsersConsoleUserUID, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \
+ MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
+#define kSCPropUsersConsoleUserGID \
+ SC_SCHEMA_KV(kSCPropUsersConsoleUserGID \
+ ,"GID" \
+ ,CFNumber )
+#endif
+ SC_SCHEMA_DECLARATION(kSCPropUsersConsoleUserGID, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);
+
+#endif /* _SCSCHEMADEFINITIONS_H */
/*!
- @header SystemConfiguration.h
- The SystemConfiguration framework provides access to the
- data used to configure a running system. The APIs provided
- by this framework communicate with the "configd" daemon.
-
- The "configd" daemon manages a "dynamic store" reflecting the
- desired configuration settings as well as the current state
- of the system. The daemon provides a notification mechanism
- for user-level processes which need to be aware of changes
- made to the data. Lastly, the daemon loads a number of
- bundles (or plug-ins) that monitor low-level kernel events
- and, via a set of policy modules, keep the state data up
- to date.
+ @header SystemConfiguration
+ @discussion The System Configuration framework provides access to the
+ data used to configure a running system. The APIs provided
+ by this framework communicate with the configd daemon.
+
+ The configd daemon manages a dynamic store reflecting the
+ desired configuration settings as well as the current state
+ of the system. The daemon provides a notification mechanism
+ for processes that need to be aware of changes made to the
+ data. Lastly, the daemon loads a number of bundles (or
+ plug-ins) that monitor low-level kernel events and, through
+ a set of policy modules, keep the state data up to date.
*/
/*!
- @enum
- @discussion Returned status codes.
-
+ @enum Error codes
+ @discussion Returned error codes.
@constant kSCStatusOK Success
@constant kSCStatusFailed Non-specific Failure
@constant kSCStatusInvalidArgument Invalid argument
@constant kSCStatusKeyExists Data associated with key already defined
@constant kSCStatusLocked Lock already held
@constant kSCStatusNeedLock Lock required for this operation
-
@constant kSCStatusNoStoreSession Configuration daemon session not active
- @constant kSCStatusNoStoreServer Configuration daemon not (no longer) available
+ @constant kSCStatusNoStoreServer Configuration daemon not (or no longer) available
@constant kSCStatusNotifierActive Notifier is currently active
-
- @constant kSCStatusNoPrefsSession Preference session not active
+ @constant kSCStatusNoPrefsSession Preferences session not active
@constant kSCStatusPrefsBusy Preferences update currently in progress
@constant kSCStatusNoConfigFile Configuration file not found
@constant kSCStatusNoLink No such link
@constant kSCStatusStale Write attempted on stale version of object
@constant kSCStatusMaxLink Maximum link count exceeded
-
@constant kSCStatusReachabilityUnknown
A determination could not be made regarding the reachability
- of the specified nodename/address.
+ of the specified nodename or address.
*/
enum {
/*
- * Generic status codes
+ * Generic error codes
*/
kSCStatusOK = 0, /* Success */
kSCStatusFailed = 1001, /* Non-specific failure */
kSCStatusLocked = 1006, /* Lock already held */
kSCStatusNeedLock = 1007, /* Lock required for this operation */
/*
- * SCDynamicStore status codes
+ * SCDynamicStore error codes
*/
kSCStatusNoStoreSession = 2001, /* Configuration daemon session not active */
kSCStatusNoStoreServer = 2002, /* Configuration daemon not (no longer) available */
kSCStatusNotifierActive = 2003, /* Notifier is currently active */
/*
- * SCPreferences status codes
+ * SCPreferences error codes
*/
kSCStatusNoPrefsSession = 3001, /* Preference session not active */
kSCStatusPrefsBusy = 3002, /* Preferences update currently in progress */
kSCStatusStale = 3005, /* Write attempted on stale version of object */
kSCStatusMaxLink = 3006, /* Maximum link count exceeded */
/*
- * SCNetwork status codes
+ * SCNetwork error codes
*/
kSCStatusReachabilityUnknown = 4001 /* Network reachability cannot be determined */
};
#include <SystemConfiguration/SCPreferences.h>
#include <SystemConfiguration/SCPreferencesPath.h>
+/* network configuration */
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+
/* store and preference scheme definitions */
#include <SystemConfiguration/SCSchemaDefinitions.h>
/*!
@function SCError
- @discussion Returns a last SystemConfiguration.framework API error code.
- @result The last error encountered.
+ @discussion Returns the most recent status or error code generated
+ as the result of calling a System Configuration framework API.
+ @result Returns the last error encountered.
*/
int SCError ();
/*!
@function SCErrorString
- @discussion Returns a pointer to the error message string associated
- with the specified status.
+ @discussion Returns a pointer to the message string
+ associated with the specified status or error.
@param status The SCDynamicStoreStatus to be returned.
- @result The error message string.
+ @result Returns a pointer to the error message string.
*/
const char * SCErrorString (int status);
#include <CoreFoundation/CFRuntime.h>
#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCPrivate.h>
#include <ifaddrs.h>
#include <pthread.h>
+#include <unistd.h>
#include <sys/types.h>
-#define KERNEL_PRIVATE
#include <sys/ioctl.h>
-#undef KERNEL_PRIVATE
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/ethernet.h>
-#define KERNEL_PRIVATE 1
+#define KERNEL_PRIVATE
#include <net/if.h>
#include <net/if_var.h>
#undef KERNEL_PRIVATE
}
-static Boolean
-_VLAN_create(int s, CFStringRef interface)
-{
-#ifdef SIOCIFCREATE
- struct ifreq ifr;
-
- bzero(&ifr, sizeof(ifr));
- (void) _SC_cfstring_to_cstring(interface,
- ifr.ifr_name,
- sizeof(ifr.ifr_name),
- kCFStringEncodingASCII);
-
- if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
- SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCIFCREATE) failed: %s"), strerror(errno));
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
- }
-
- return TRUE;
-#else /* SIOCIFCREATE */
- return FALSE;
-#endif /* SIOCIFCREATE */
-}
-
-
-static Boolean
-_VLAN_destroy(int s, CFStringRef interface)
-{
-#ifdef SIOCIFDESTROY
- struct ifreq ifr;
-
- bzero(&ifr, sizeof(ifr));
- (void) _SC_cfstring_to_cstring(interface,
- ifr.ifr_name,
- sizeof(ifr.ifr_name),
- kCFStringEncodingASCII);
-
- if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) {
- SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCIFDESTROY) failed: %s"), strerror(errno));
- _SCErrorSet(kSCStatusFailed);
- return FALSE;
- }
-
- return TRUE;
-#else /* SIOCIFDESTROY */
- return FALSE;
-#endif /* SIOCIFDESTROY */
-}
-
-
static Boolean
_VLANDevice_set(int s, CFStringRef interface, CFStringRef device, CFNumberRef tag)
{
-#ifdef SIOCSETVLAN
struct ifreq ifr;
int tag_val;
struct vlanreq vreq;
vreq.vlr_tag = tag_val;
// update parent device and tag
- if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) {
- SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSETVLAN) failed: %s"), strerror(errno));
+ if (ioctl(s, SIOCSIFVLAN, (caddr_t)&ifr) == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSIFVLAN) failed: %s"), strerror(errno));
+ _SCErrorSet(kSCStatusFailed);
+ return FALSE;
+ }
+
+ // mark the parent device "up"
+ if (!__markInterfaceUp(s, device)) {
_SCErrorSet(kSCStatusFailed);
return FALSE;
}
return TRUE;
-#else /* SIOCSETVLAN */
- return FALSE;
-#endif /* SIOCSETVLAN */
}
static Boolean
_VLANDevice_unset(int s, CFStringRef interface)
{
-#ifdef SIOCSETVLAN
struct ifreq ifr;
struct vlanreq vreq;
vreq.vlr_tag = 0;
// update parent device and tag
- if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) {
- SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSETVLAN) failed: %s"), strerror(errno));
+ if (ioctl(s, SIOCSIFVLAN, (caddr_t)&ifr) == -1) {
+ SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSIFVLAN) failed: %s"), strerror(errno));
_SCErrorSet(kSCStatusFailed);
return FALSE;
}
return TRUE;
-#else /* SIOCSETVLAN */
- return FALSE;
-#endif /* SIOCSETVLAN */
}
/* get the interface index */
- if_name = _SC_cfstring_to_cstring(device, NULL, NULL, kCFStringEncodingASCII);
+ if_name = _SC_cfstring_to_cstring(device, NULL, 0, kCFStringEncodingASCII);
if (if_name == NULL) {
return FALSE; // if conversion error
}
{
VLANInterfacePrivateRef vlanPrivate = (VLANInterfacePrivateRef)cf;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceDeallocate:"));
-
/* release resources */
CFRelease(vlanPrivate->ifname);
VLANInterfacePrivateRef vlanPrivate;
uint32_t size;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceCreatePrivate:"));
-
/* initialize runtime */
pthread_once(&vlanInterface_init, __VLANInterfaceInitialize);
{
VLANPreferencesPrivateRef prefsPrivate = (VLANPreferencesPrivateRef)cf;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesDeallocate:"));
-
/* release resources */
pthread_mutex_destroy(&prefsPrivate->lock);
strncpy(ifr.ifr_name, ifp->ifa_name, sizeof(ifr.ifr_name));
ifr.ifr_data = (caddr_t)&vreq;
- if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) {
+ if (ioctl(s, SIOCGIFVLAN, (caddr_t)&ifr) == -1) {
SCLog(TRUE, LOG_ERR, CFSTR("ioctl() failed: %s"), strerror(errno));
_SCErrorSet(kSCStatusFailed);
CFRelease(vlans);
VLANPreferencesPrivateRef prefsPrivate;
uint32_t size;
- SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesCreate:"));
-
/* initialize runtime */
pthread_once(&vlanPreferences_init, __VLANPreferencesInitialize);
__kVLANPreferencesTypeID,
size,
NULL);
- if (!prefsPrivate) {
+ if (prefsPrivate == NULL) {
return NULL;
}
newVlan = __VLANInterfaceCreatePrivate(allocator, vlan_if, device, tag, options);
+ /* yes, we're going to be changing the configuration */
+ setConfigurationChanged(prefs);
+
/* save in the prefs */
if (nConfig == 0) {
(void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
CFRelease(newVlans);
- /* yes, we've change the configuration */
- setConfigurationChanged(prefs);
-
next_if :
CFRelease(vlan_if);
}
CFDictionaryAddValue(newDict, __kVLANInterface_options, newOptions);
}
+ /* yes, we're going to be changing the configuration */
+ setConfigurationChanged(prefs);
+
/* update the prefs */
newVlans = CFArrayCreateMutableCopy(allocator, 0, vlans);
- CFArrayRemoveValueAtIndex(newVlans, cur_if);
- CFArrayAppendValue(newVlans, newDict);
+ CFArraySetValueAtIndex(newVlans, cur_if, newDict);
CFRelease(newDict);
(void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
CFRelease(newVlans);
- /* yes, we've change the configuration */
- setConfigurationChanged(prefs);
-
ok = TRUE;
done :
goto done;
}
+ /* yes, we're going to be changing the configuration */
+ setConfigurationChanged(prefs);
+
/* remove the vlan */
allocator = CFGetAllocator(prefs);
(void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
CFRelease(newVlans);
- /* yes, we've change the configuration */
- setConfigurationChanged(prefs);
-
ok = TRUE;
done :
s = inet_dgram_socket();
}
- ok = _VLAN_destroy(s, a_vlan_if);
+ ok = __destroyInterface(s, a_vlan_if);
if (!ok) {
+ _SCErrorSet(kSCStatusFailed);
goto done;
}
}
}
} else {
// if the new [parent] device does not support VLANs
- ok = _VLAN_destroy(s, c_vlan_if);
+ ok = __destroyInterface(s, c_vlan_if);
if (!ok) {
+ _SCErrorSet(kSCStatusFailed);
goto done;
}
}
s = inet_dgram_socket();
}
- ok = _VLAN_create(s, c_vlan_if);
+ ok = __createInterface(s, c_vlan_if);
if (!ok) {
+ _SCErrorSet(kSCStatusFailed);
goto done;
}
goto done;
}
- ok = TRUE;
-
done :
pthread_mutex_unlock(&prefsPrivate->lock);
#ifndef _VLANCONFIGURATION_H
#define _VLANCONFIGURATION_H
+/*!
+ @header VLANConfiguration
+*/
#include <sys/cdefs.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/VLANConfiguration.h>
+
+
+/*!
+ @header VLANConfigurationPrivate
+ */
+
+
#define VLAN_PREFERENCES_ID CFSTR("VirtualNetworkInterfaces.plist")
routine configopen ( server : mach_port_t;
name : xmlData;
+ options : xmlData;
out session : mach_port_move_send_t;
out status : int);
__private_extern__ CFMutableDictionaryRef
_IOBSDNameMatching(mach_port_t masterPort, unsigned int options, const char *bsdName)
{
- static CFMutableDictionaryRef (*dyfunc)(mach_port_t, unsigned int, const char *) = NULL;
+ #undef IOBSDNameMatching
+ static typeof (IOBSDNameMatching) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOBSDNameMatching", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ io_object_t
_IOIteratorNext(io_iterator_t iterator)
{
- static io_object_t (*dyfunc)(io_iterator_t) = NULL;
+ #undef IOIteratorNext
+ static typeof (IOIteratorNext) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOIteratorNext", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ kern_return_t
_IOMasterPort(mach_port_t bootstrapPort, mach_port_t *masterPort)
{
- static kern_return_t (*dyfunc)(mach_port_t, mach_port_t *) = NULL;
+ #undef IOMasterPort
+ static typeof (IOMasterPort) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOMasterPort", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
}
+__private_extern__ boolean_t
+_IOObjectConformsTo(io_object_t object, const io_name_t className)
+{
+ #undef IOObjectConformsTo
+ static typeof (IOObjectConformsTo) *dyfunc = NULL;
+ if (!dyfunc) {
+ void *image = __loadIOKit();
+ if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOObjectConformsTo", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+ }
+ return dyfunc ? dyfunc(object, className) : FALSE;
+}
+
+
+__private_extern__ boolean_t
+_IOObjectGetClass(io_object_t object, io_name_t className)
+{
+ #undef IOObjectGetClass
+ static typeof (IOObjectGetClass) *dyfunc = NULL;
+ if (!dyfunc) {
+ void *image = __loadIOKit();
+ if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOObjectGetClass", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+ }
+ return dyfunc ? dyfunc(object, className) : FALSE;
+}
+
+
__private_extern__ kern_return_t
_IOObjectRelease(io_object_t object)
{
- static kern_return_t (*dyfunc)(io_object_t) = NULL;
+ #undef IOObjectRelease
+ static typeof (IOObjectRelease) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOObjectRelease", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ CFTypeRef
_IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options)
{
- static CFTypeRef (*dyfunc)(io_registry_entry_t, CFStringRef, CFAllocatorRef, IOOptionBits) = NULL;
+ #undef IORegistryEntryCreateCFProperty
+ static typeof (IORegistryEntryCreateCFProperty) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryCreateCFProperty", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ kern_return_t
_IORegistryEntryCreateCFProperties(io_registry_entry_t entry, CFMutableDictionaryRef *properties, CFAllocatorRef allocator, IOOptionBits options)
{
- static kern_return_t (*dyfunc)(io_registry_entry_t, CFMutableDictionaryRef *, CFAllocatorRef, IOOptionBits) = NULL;
+ #undef IORegistryEntryCreateCFProperties
+ static typeof (IORegistryEntryCreateCFProperties) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryCreateCFProperties", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
}
+__private_extern__ kern_return_t
+_IORegistryEntryCreateIterator(mach_port_t masterPort, const io_name_t plane, IOOptionBits options, io_iterator_t *iterator)
+{
+ #undef IORegistryEntryCreateIterator
+ static typeof (IORegistryEntryCreateIterator) *dyfunc = NULL;
+ if (!dyfunc) {
+ void *image = __loadIOKit();
+ if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryCreateIterator", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+ }
+ return dyfunc ? dyfunc(masterPort, plane, options, iterator) : KERN_FAILURE;
+}
+
+
+__private_extern__ kern_return_t
+_IORegistryEntryGetName(io_registry_entry_t entry, io_name_t name)
+{
+ #undef IORegistryEntryGetName
+ static typeof (IORegistryEntryGetName) *dyfunc = NULL;
+ if (!dyfunc) {
+ void *image = __loadIOKit();
+ if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryGetName", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+ }
+ return dyfunc ? dyfunc(entry, name) : KERN_FAILURE;
+}
+
+
__private_extern__ kern_return_t
_IORegistryEntryGetParentEntry(io_registry_entry_t entry, const io_name_t plane, io_registry_entry_t *parent)
{
- static kern_return_t (*dyfunc)(io_registry_entry_t, const io_name_t, io_registry_entry_t *) = NULL;
+ #undef IORegistryEntryGetParentEntry
+ static typeof (IORegistryEntryGetParentEntry) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryGetParentEntry", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
}
- return dyfunc ? dyfunc(entry, plane, parent) : NULL;
+ return dyfunc ? dyfunc(entry, plane, parent) : KERN_FAILURE;
}
__private_extern__ kern_return_t
_IORegistryEntryGetPath(io_registry_entry_t entry, const io_name_t plane, io_string_t path)
{
- static kern_return_t (*dyfunc)(io_registry_entry_t, const io_name_t, io_string_t) = NULL;
+ #undef IORegistryEntryGetPath
+ static typeof (IORegistryEntryGetPath) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryGetPath", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
}
+__private_extern__ CFTypeRef
+_IORegistryEntrySearchCFProperty(io_registry_entry_t entry, const io_name_t plane, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options)
+{
+ #undef IORegistryEntrySearchCFProperty
+ static typeof (IORegistryEntrySearchCFProperty) *dyfunc = NULL;
+ if (!dyfunc) {
+ void *image = __loadIOKit();
+ if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntrySearchCFProperty", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+ }
+ return dyfunc ? dyfunc(entry, plane, key, allocator, options) : NULL;
+}
+
+
__private_extern__ kern_return_t
_IOServiceGetMatchingServices(mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t *existing)
{
- static kern_return_t (*dyfunc)(mach_port_t, CFDictionaryRef, io_iterator_t *) = NULL;
+ #undef IOServiceGetMatchingServices
+ static typeof (IOServiceGetMatchingServices) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOServiceGetMatchingServices", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ CFMutableDictionaryRef
_IOServiceMatching(const char *name)
{
- static CFMutableDictionaryRef (*dyfunc)(const char *) = NULL;
+ #undef IOServiceMatching
+ static typeof (IOServiceMatching) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadIOKit();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOServiceMatching", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ OSStatus
_SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData)
{
- static OSStatus (*dyfunc)(SecKeychainItemRef, SecItemClass *, SecKeychainAttributeList *, UInt32 *, void **) = NULL;
+ #undef SecKeychainItemCopyContent
+ static typeof (SecKeychainItemCopyContent) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadSecurity();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainItemCopyContent", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ OSStatus
_SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *itemRef)
{
- static OSStatus (*dyfunc)(SecKeychainSearchRef, SecKeychainItemRef *) = NULL;
+ #undef SecKeychainSearchCopyNext
+ static typeof (SecKeychainSearchCopyNext) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadSecurity();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCopyNext", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
__private_extern__ OSStatus
_SecKeychainSearchCreateFromAttributes(CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef)
{
- static OSStatus (*dyfunc)(CFTypeRef, SecItemClass, const SecKeychainAttributeList *, SecKeychainSearchRef *) = NULL;
+ #undef SecKeychainSearchCreateFromAttributes
+ static typeof (SecKeychainSearchCreateFromAttributes) *dyfunc = NULL;
if (!dyfunc) {
void *image = __loadSecurity();
if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCreateFromAttributes", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
);
#define IOMasterPort _IOMasterPort
+boolean_t
+_IOObjectConformsTo (
+ io_object_t object,
+ const io_name_t className
+ );
+#define IOObjectConformsTo _IOObjectConformsTo
+
+boolean_t
+_IOObjectGetClass (
+ io_object_t object,
+ io_name_t className
+ );
+#define IOObjectGetClass _IOObjectGetClass
+
kern_return_t
_IOObjectRelease (
io_object_t object
);
#define IORegistryEntryCreateCFProperties _IORegistryEntryCreateCFProperties
+kern_return_t
+_IORegistryEntryCreateIterator (
+ io_registry_entry_t entry,
+ const io_name_t plane,
+ IOOptionBits options,
+ io_iterator_t *iterator
+ );
+#define IORegistryEntryCreateIterator _IORegistryEntryCreateIterator
+
+kern_return_t
+_IORegistryEntryGetName (
+ io_registry_entry_t entry,
+ io_name_t name
+ );
+#define IORegistryEntryGetName _IORegistryEntryGetName
+
kern_return_t
_IORegistryEntryGetParentEntry (
io_registry_entry_t entry,
);
#define IORegistryEntryGetPath _IORegistryEntryGetPath
+CFTypeRef
+_IORegistryEntrySearchCFProperty (
+ io_registry_entry_t entry,
+ const io_name_t plane,
+ CFStringRef key,
+ CFAllocatorRef allocator,
+ IOOptionBits options
+ );
+#define IORegistryEntrySearchCFProperty _IORegistryEntrySearchCFProperty
+
kern_return_t
_IOServiceGetMatchingServices (
mach_port_t masterPort,
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * 4 March 2004 Allan Nathanson (ajn@apple.com)
+ * - an alternate scheme to help facilitate access to the schema
+ * definitions for cross-compilation to earlier releases AND
+ * access to CFM applications.
+ *
* 16 July 2003 Allan Nathanson (ajn@apple.com)
* - changes to facilitate cross-compilation to earlier releases
*
char copyright_string[] =
"/*\n"
-" * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.\n"
+" * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.\n"
" *\n"
" * @APPLE_LICENSE_HEADER_START@\n"
" * \n"
typedef enum {
COMMENT,
- OBSOLETE,
- REGULAR,
- DEFINE,
- FUTURE,
+ GROUP,
+ SC_10_1,
+ SC_10_2,
+ SC_10_1_10_3, // deprecated in 10.4
+ SC_10_3,
+ SC_10_4,
END
} controlType;
+#define SC_SCHEMA_KV "SC_SCHEMA_KV"
#define SC_SCHEMA_DECLARATION "SC_SCHEMA_DECLARATION"
#define KEY_PREFIX "kSC"
#define CFNUMBER_BOOL "CFNumber (0 or 1)"
#define CFSTRING "CFString"
-#define ACSPENABLED "ACSPEnabled" // Apple Client Server Protocol
+#define ACSP "ACSP" // Apple Client Server Protocol
#define ACTIVE "Active"
#define ADDRESSES "Addresses"
#define AFTER "After"
#define ANYREGEX "AnyRegex"
#define APPLETALK "AppleTalk"
#define AUTH "Auth"
+#define AUTOCONFIG "AutoConfig"
+#define AUTODISCOVERY "AutoDiscovery"
#define AUTOMATIC "Automatic"
#define BEFORE "Before"
#define BINDINGMETHODS "BindingMethods"
#define BOOTP "BOOTP"
#define BROADCAST "Broadcast"
-#define BROADCASTADDRESSES "BroadcastAddresses"
-#define BROADCASTSERVERTAG "BroadcastServerTag"
#define CALLWAITINGAUDIBLEALERT "CallWaitingAudibleAlert"
+#define CAUSE "Cause"
#define CCP "CCP"
#define CHAP "CHAP"
#define COMM "Comm"
#define CONSOLEUSER "ConsoleUser"
#define CURRENTSET "CurrentSet"
#define DATACOMPRESSION "DataCompression"
-#define DEFAULTSERVERTAG "DefaultServerTag"
+#define DEFAULT "Default"
#define DEFAULTZONE "DefaultZone"
-#define DESTADDRESSES "DestAddresses"
+#define DEST "Dest"
#define DETACHING "Detaching"
#define DEVICE "Device"
#define DEVICENAME "DeviceName"
#define DIALMODE "DialMode"
#define DIALONDEMAND "DialOnDemand"
#define DISCONNECTONANSWER "DisconnectOnAnswer"
+#define DISCONNECTONFASTUSERSWITCH "DisconnectOnFastUserSwitch"
#define DISCONNECTONIDLE "DisconnectOnIdle"
#define DISCONNECTONIDLETIMER "DisconnectOnIdleTimer"
#define DISCONNECTONLOGOUT "DisconnectOnLogout"
#define DISPLAYTERMINALWINDOW "DisplayTerminalWindow"
#define DNS "DNS"
#define DOMAIN "Domain"
-#define DOMAINNAME "DomainName"
-#define DOMAINSEPARATOR "DomainSeparator"
+#define DOMAINS "Domains"
#define EAP "EAP"
-#define ECHOENABLED "EchoEnabled"
+#define ECHO "Echo"
#define ECHOFAILURE "EchoFailure"
#define ECHOINTERVAL "EchoInterval"
+#define ENABLE "Enable"
#define ENABLED "Enabled"
#define ENCODING "Encoding"
#define ENCRYPTION "Encryption"
#define ERRORCORRECTION "ErrorCorrection"
#define ETHERNET "Ethernet"
#define EXCEPTIONSLIST "ExceptionsList"
+#define EXCLUDESIMPLEHOSTNAMES "ExcludeSimpleHostnames"
#define FILE "File"
#define FIREWIRE "FireWire"
+#define FIRST "First"
#define FLAGS "Flags"
-#define FTPENABLE "FTPEnable"
-#define FTPPASSIVE "FTPPassive"
-#define FTPPORT "FTPPort"
-#define FTPPROXY "FTPProxy"
+#define FTP "FTP"
#define GID "GID"
#define GLOBAL "Global"
-#define GOPHERENABLE "GopherEnable"
-#define GOPHERPORT "GopherPort"
-#define GOPHERPROXY "GopherProxy"
+#define GOPHER "Gopher"
#define HARDWARE "Hardware"
#define HOLD "Hold"
#define HOSTNAMES "HostNames"
-#define HTTPENABLE "HTTPEnable"
-#define HTTPPORT "HTTPPort"
-#define HTTPPROXY "HTTPProxy"
-#define HTTPSENABLE "HTTPSEnable"
-#define HTTPSPORT "HTTPSPort"
-#define HTTPSPROXY "HTTPSProxy"
+#define HTTP "HTTP"
+#define HTTPS "HTTPS"
#define IDLEREMINDER "IdleReminder"
#define IDLEREMINDERTIMER "IdleReminderTimer"
#define IGNOREDIALTONE "IgnoreDialTone"
#define JOINMODE "JoinMode"
#define KEYCHAIN "Keychain"
#define L2TP "L2TP"
-#define LASTCAUSE "LastCause"
-#define LASTUPDATED "LastUpdated"
+#define LAST "Last"
#define LCP "LCP"
#define LINK "Link"
#define LINKLOCAL "LinkLocal"
#define LOGFILE "Logfile"
#define MACADDRESS "MACAddress"
#define MANUAL "Manual"
+#define MATCH "Match"
#define MEDIA "Media"
#define OPTIONS "Options"
#define MODEM "Modem"
+#define MPPE40 "MPPE40"
+#define MPPE128 "MPPE128"
#define MRU "MRU"
#define MSCHAP1 "MSCHAP1"
#define MSCHAP2 "MSCHAP2"
#define NETWORKID "NetworkID"
#define NETWORKRANGE "NetworkRange"
#define NETWORKSERVICES "NetworkServices"
-#define NIS "NIS"
#define NODE "Node"
#define NODEID "NodeID"
#define NOTE "Note"
+#define ORDER "Order"
+#define ORDERS "Orders"
#define OVERRIDEPRIMARY "OverridePrimary"
#define PAP "PAP"
+#define PASSIVE "Passive"
#define PASSWORD "Password"
+#define PEERDNS "PeerDNS"
#define PLUGIN "Plugin"
#define PLUGINS "Plugins"
-#define POWERENABLED "PowerEnabled"
+#define POWER "Power"
+#define PORT "Port"
#define PPP "PPP"
#define PPPOE "PPPoE"
-#define PPPOVERRIDEPRIMARY "PPPOverridePrimary"
#define PPPSERIAL "PPPSerial"
#define PPTP "PPTP"
#define PREFERRED "Preferred"
-#define PREFERREDNETWORK "PreferredNetwork"
#define PREFIXLENGTH "PrefixLength"
#define PREFS "Prefs"
#define PRIMARYINTERFACE "PrimaryInterface"
#define PROMPT "Prompt"
#define PROTOCOL "Protocol"
#define PROXIES "Proxies"
-#define PROXYAUTOCONFIGENABLE "ProxyAutoConfigEnable"
-#define PROXYAUTOCONFIGURLSTRING "ProxyAutoConfigURLString"
+#define PROXY "Proxy"
#define PULSEDIAL "PulseDial"
#define RECEIVEACCM "ReceiveACCM"
#define RECENT "Recent"
#define REDIALCOUNT "RedialCount"
-#define REDIALENABLED "RedialEnabled"
+#define REDIAL "Redial"
#define REDIALINTERVAL "RedialInterval"
#define RELAY "Relay"
#define REMINDER "Reminder"
#define ROOTSEPARATOR "RootSeparator"
#define ROUTER "Router"
#define ROUTERADVERTISEMENT "RouterAdvertisement"
-#define RTSPENABLE "RTSPEnable"
-#define RTSPPORT "RTSPPort"
-#define RTSPPROXY "RTSPProxy"
+#define RTSP "RTSP"
#define SAVEPASSWORDS "SavePasswords"
-#define SEARCHDOMAINS "SearchDomains"
+#define SEARCH "Search"
#define SEEDNETWORKRANGE "SeedNetworkRange"
#define SEEDROUTER "SeedRouter"
#define SEEDZONES "SeedZones"
-#define SERVERADDRESSES "ServerAddresses"
-#define SERVERTAGS "ServerTags"
+#define SERVER "Server"
#define SERVICE "Service"
#define SERVICEIDS "ServiceIDs"
-#define SERVICEORDER "ServiceOrder"
#define SESSIONTIMER "SessionTimer"
#define SETS "Sets"
#define SETUP "Setup"
#define SHAREDSECRET "SharedSecret"
-#define SOCKSENABLE "SOCKSEnable"
-#define SOCKSPORT "SOCKSPort"
-#define SOCKSPROXY "SOCKSProxy"
+#define SOCKS "SOCKS"
#define SORTLIST "SortList"
#define SPEAKER "Speaker"
#define SPEED "Speed"
#define STRONGEST "Strongest"
#define SUBNETMASKS "SubnetMasks"
#define SUBTYPE "SubType"
+#define SUPPLEMENTAL "Supplemental"
#define SUPPORTSMODEMONHOLD "SupportsModemOnHold"
#define SYSTEM "System"
+#define TAG "Tag"
+#define TAGS "Tags"
#define TERMINALSCRIPT "TerminalScript"
+#define TIMEOUT "Timeout"
#define TRANSMITACCM "TransmitACCM"
#define TRANSPORT "Transport"
#define TYPE "Type"
#define UID "UID"
+#define UPDATED "Updated"
+#define URLSTRING "URLString"
#define USERDEFINEDNAME "UserDefinedName"
#define USE "Use"
#define USERS "Users"
const char * value;
const char * type;
} names[] = {
- { COMMENT, "/*\n * Reserved Keys\n */", NULL, NULL },
- { REGULAR, RESV, LINK, "__LINK__", CFSTRING },
- { REGULAR, RESV, INACTIVE, "__INACTIVE__", NULL },
+
+ { GROUP, NULL, "Reserved Keys", NULL, NULL },
+
+ { SC_10_1, RESV, LINK, "__LINK__", CFSTRING },
+ { SC_10_1, RESV, INACTIVE, "__INACTIVE__", NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Generic Keys\n */", NULL },
- { DEFINE , PROP, INTERFACENAME, NULL, CFSTRING },
- { REGULAR, PROP, MACADDRESS, NULL, CFSTRING },
- { REGULAR, PROP, USERDEFINEDNAME, NULL, CFSTRING },
- { DEFINE , PROP, VERSION, NULL, CFSTRING },
+ { GROUP, NULL, "Generic Keys", NULL, NULL },
+
+ { SC_10_1, PROP, INTERFACENAME, NULL, CFSTRING },
+ { SC_10_1, PROP, MACADDRESS, NULL, CFSTRING },
+ { SC_10_1, PROP, USERDEFINEDNAME, NULL, CFSTRING },
+ { SC_10_1, PROP, VERSION, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Preference Keys\n */", NULL },
- { REGULAR, PREF, CURRENTSET, NULL, CFSTRING },
- { REGULAR, PREF, NETWORKSERVICES, NULL, CFDICTIONARY },
- { REGULAR, PREF, SETS, NULL, CFDICTIONARY },
- { REGULAR, PREF, SYSTEM, NULL, CFDICTIONARY },
+ { GROUP, PREF, "Preference Keys", NULL, NULL },
+
+ { SC_10_1, PREF, CURRENTSET, NULL, CFSTRING },
+ { SC_10_1, PREF, NETWORKSERVICES, NULL, CFDICTIONARY },
+ { SC_10_1, PREF, SETS, NULL, CFDICTIONARY },
+ { SC_10_1, PREF, SYSTEM, NULL, CFDICTIONARY },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Component Keys\n */", NULL },
- { REGULAR, COMP, NETWORK, NULL, NULL },
- { REGULAR, COMP, SERVICE, NULL, NULL },
- { REGULAR, COMP, GLOBAL, NULL, NULL },
- { DEFINE , COMP, HOSTNAMES, NULL, NULL },
- { REGULAR, COMP, INTERFACE, NULL, NULL },
- { REGULAR, COMP, SYSTEM, NULL, NULL },
- { REGULAR, COMP, USERS, NULL, NULL },
+ { GROUP, COMP, "Component Keys", NULL, NULL },
+
+ { SC_10_1, COMP, NETWORK, NULL, NULL },
+ { SC_10_1, COMP, SERVICE, NULL, NULL },
+ { SC_10_1, COMP, GLOBAL, NULL, NULL },
+ { SC_10_2, COMP, HOSTNAMES, NULL, NULL },
+ { SC_10_1, COMP, INTERFACE, NULL, NULL },
+ { SC_10_1, COMP, SYSTEM, NULL, NULL },
+ { SC_10_1, COMP, USERS, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Regex key which matches any component\n */", NULL },
- { REGULAR, COMP, ANYREGEX, "[^/]+", NULL },
+ { COMMENT, "--- Regex pattern which matches any component ---", NULL },
+ { SC_10_1, COMP, ANYREGEX, "[^/]+", NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Network Entity Keys\n */", NULL },
- { REGULAR, NETENT, AIRPORT, NULL, CFDICTIONARY },
- { REGULAR, NETENT, APPLETALK, NULL, CFDICTIONARY },
- { DEFINE , NETENT, DHCP, NULL, CFDICTIONARY },
- { REGULAR, NETENT, DNS, NULL, CFDICTIONARY },
- { REGULAR, NETENT, ETHERNET, NULL, CFDICTIONARY },
- { DEFINE , NETENT, FIREWIRE, NULL, CFDICTIONARY },
- { REGULAR, NETENT, INTERFACE, NULL, CFDICTIONARY },
- { REGULAR, NETENT, IPV4, NULL, CFDICTIONARY },
- { REGULAR, NETENT, IPV6, NULL, CFDICTIONARY },
- { DEFINE , NETENT, L2TP, NULL, CFDICTIONARY },
- { REGULAR, NETENT, LINK, NULL, CFDICTIONARY },
- { REGULAR, NETENT, MODEM, NULL, CFDICTIONARY },
- { REGULAR, NETENT, NETINFO, NULL, CFDICTIONARY },
- { FUTURE , NETENT, NIS, NULL, CFDICTIONARY },
- { REGULAR, NETENT, PPP, NULL, CFDICTIONARY },
- { REGULAR, NETENT, PPPOE, NULL, CFDICTIONARY },
- { DEFINE , NETENT, PPPSERIAL, NULL, CFDICTIONARY },
- { DEFINE , NETENT, PPTP, NULL, CFDICTIONARY },
- { REGULAR, NETENT, PROXIES, NULL, CFDICTIONARY },
- { DEFINE , NETENT, STF, NULL, CFDICTIONARY },
+ { GROUP, NETENT, "Network Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETENT, AIRPORT, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, APPLETALK, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, DHCP, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, DNS, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, ETHERNET, NULL, CFDICTIONARY },
+ { SC_10_3, NETENT, FIREWIRE, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, INTERFACE, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, IPV4, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, IPV6, NULL, CFDICTIONARY },
+ { SC_10_3, NETENT, L2TP, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, LINK, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, MODEM, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, NETINFO, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, PPP, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, PPPOE, NULL, CFDICTIONARY },
+ { SC_10_3, NETENT, PPPSERIAL, NULL, CFDICTIONARY },
+ { SC_10_3, NETENT, PPTP, NULL, CFDICTIONARY },
+ { SC_10_1, NETENT, PROXIES, NULL, CFDICTIONARY },
+ { SC_10_3, NETENT, STF, NULL, CFDICTIONARY },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK " Properties\n */", NULL },
- { DEFINE , NETPROP, OVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP, SERVICEORDER, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP, PPPOVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
+ { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK " Properties", NULL, NULL },
+
+ { SC_10_2, NETPROP, OVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP, SERVICE ORDER, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP, PPP OVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK INTERFACE " Properties\n */", NULL },
- { DEFINE , NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
+ { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK INTERFACE " Properties", NULL, NULL },
+
+ { SC_10_2, NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK HOSTNAMES " Properties\n */", NULL },
- { DEFINE , NETPROP, LOCALHOSTNAME, NULL, CFSTRING },
+ { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK HOSTNAMES " Properties", NULL, NULL },
+
+ { SC_10_2, NETPROP, LOCALHOSTNAME, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
- { DEFINE , NETPROP AIRPORT, ALLOWNETCREATION, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFDATA },
- { REGULAR, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
- { DEFINE , NETPROP AIRPORT, JOINMODE, NULL, CFSTRING },
- { REGULAR, NETPROP AIRPORT, POWERENABLED, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP AIRPORT, PREFERREDNETWORK, NULL, CFSTRING },
- { DEFINE , NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL },
+ { GROUP, NETPROP AIRPORT, KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys", NULL, NULL },
+
+ { SC_10_2, NETPROP AIRPORT, ALLOWNETCREATION, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFDATA },
+ { SC_10_1, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+ { SC_10_2, NETPROP AIRPORT, JOINMODE, NULL, CFSTRING },
+ { SC_10_1, NETPROP AIRPORT, POWER ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP AIRPORT, PREFERRED NETWORK, NULL, CFSTRING },
+ { SC_10_2, NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP AIRPORT JOINMODE " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL AIRPORT JOINMODE, AUTOMATIC, NULL, NULL },
- { DEFINE , NETVAL AIRPORT JOINMODE, PREFERRED, NULL, NULL },
- { DEFINE , NETVAL AIRPORT JOINMODE, RECENT, NULL, NULL },
- { DEFINE , NETVAL AIRPORT JOINMODE, STRONGEST, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP AIRPORT JOINMODE " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL AIRPORT JOINMODE, AUTOMATIC, NULL, NULL },
+ { SC_10_2, NETVAL AIRPORT JOINMODE, PREFERRED, NULL, NULL },
+ { SC_10_2, NETVAL AIRPORT JOINMODE, RECENT, NULL, NULL },
+ { SC_10_2, NETVAL AIRPORT JOINMODE, STRONGEST, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT APPLETALK " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP APPLETALK, COMPUTERNAME, NULL, CFSTRING },
- { REGULAR, NETPROP APPLETALK, COMPUTERNAME ENCODING, NULL, CFNUMBER },
- { REGULAR, NETPROP APPLETALK, CONFIGMETHOD, NULL, CFSTRING },
- { REGULAR, NETPROP APPLETALK, DEFAULTZONE, NULL, CFSTRING },
- { REGULAR, NETPROP APPLETALK, NETWORKID, NULL, CFNUMBER },
- { REGULAR, NETPROP APPLETALK, NETWORKRANGE, NULL, CFARRAY_CFNUMBER },
- { REGULAR, NETPROP APPLETALK, NODEID, NULL, CFNUMBER },
- { REGULAR, NETPROP APPLETALK, SEEDNETWORKRANGE, NULL, CFARRAY_CFNUMBER },
- { REGULAR, NETPROP APPLETALK, SEEDZONES, NULL, CFARRAY_CFSTRING },
+ { GROUP, NETPROP APPLETALK, KEY_PREFIX NETENT APPLETALK " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP APPLETALK, COMPUTERNAME, NULL, CFSTRING },
+ { SC_10_1, NETPROP APPLETALK, COMPUTERNAME ENCODING, NULL, CFNUMBER },
+ { SC_10_1, NETPROP APPLETALK, CONFIGMETHOD, NULL, CFSTRING },
+ { SC_10_1, NETPROP APPLETALK, DEFAULTZONE, NULL, CFSTRING },
+ { SC_10_1, NETPROP APPLETALK, NETWORKID, NULL, CFNUMBER },
+ { SC_10_2, NETPROP APPLETALK, NETWORKRANGE, NULL, CFARRAY_CFNUMBER },
+ { SC_10_1, NETPROP APPLETALK, NODEID, NULL, CFNUMBER },
+ { SC_10_1, NETPROP APPLETALK, SEEDNETWORKRANGE, NULL, CFARRAY_CFNUMBER },
+ { SC_10_1, NETPROP APPLETALK, SEEDZONES, NULL, CFARRAY_CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP APPLETALK CONFIGMETHOD " values */", NULL, NULL, NULL },
- { REGULAR, NETVAL APPLETALK CONFIGMETHOD, NODE, NULL, NULL },
- { REGULAR, NETVAL APPLETALK CONFIGMETHOD, ROUTER, NULL, NULL },
- { REGULAR, NETVAL APPLETALK CONFIGMETHOD, SEEDROUTER, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP APPLETALK CONFIGMETHOD " values ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL APPLETALK CONFIGMETHOD, NODE, NULL, NULL },
+ { SC_10_1, NETVAL APPLETALK CONFIGMETHOD, ROUTER, NULL, NULL },
+ { SC_10_1, NETVAL APPLETALK CONFIGMETHOD, SEEDROUTER, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT DNS " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP DNS, DOMAINNAME, NULL, CFSTRING },
- { REGULAR, NETPROP DNS, SEARCHDOMAINS, NULL, CFARRAY_CFSTRING},
- { REGULAR, NETPROP DNS, SERVERADDRESSES, NULL, CFARRAY_CFSTRING },
- { DEFINE , NETPROP DNS, SORTLIST, NULL, CFARRAY_CFSTRING },
+ { GROUP, NETPROP DNS, KEY_PREFIX NETENT DNS " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP DNS, DOMAIN NAME, NULL, CFSTRING },
+ { SC_10_4, NETPROP DNS, OPTIONS, NULL, CFSTRING },
+ { SC_10_1, NETPROP DNS, SEARCH DOMAINS, NULL, CFARRAY_CFSTRING},
+ { SC_10_4, NETPROP DNS, SEARCH ORDER, NULL, CFNUMBER},
+ { SC_10_1, NETPROP DNS, SERVER ADDRESSES, NULL, CFARRAY_CFSTRING },
+ { SC_10_4, NETPROP DNS, SERVER PORT, NULL, CFNUMBER },
+ { SC_10_4, NETPROP DNS, SERVER TIMEOUT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP DNS, SORTLIST, NULL, CFARRAY_CFSTRING },
+ { SC_10_4, NETPROP DNS, SUPPLEMENTAL MATCH DOMAINS, NULL, CFARRAY_CFSTRING},
+ { SC_10_4, NETPROP DNS, SUPPLEMENTAL MATCH ORDERS, NULL, CFARRAY_CFNUMBER},
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT ETHERNET " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
- { DEFINE , NETPROP ETHERNET, MEDIA SUBTYPE, NULL, CFSTRING },
- { DEFINE , NETPROP ETHERNET, MEDIA OPTIONS, NULL, CFARRAY_CFSTRING },
- { DEFINE , NETPROP ETHERNET, MTU, NULL, CFNUMBER },
+ { GROUP, NETPROP ETHERNET, KEY_PREFIX NETENT ETHERNET " (Hardware) Entity Keys", NULL, NULL },
+
+ { SC_10_2, NETPROP ETHERNET, MEDIA SUBTYPE, NULL, CFSTRING },
+ { SC_10_2, NETPROP ETHERNET, MEDIA OPTIONS, NULL, CFARRAY_CFSTRING },
+ { SC_10_2, NETPROP ETHERNET, MTU, NULL, CFNUMBER },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT FIREWIRE " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
- { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+ { GROUP, NETPROP FIREWIRE, KEY_PREFIX NETENT FIREWIRE " (Hardware) Entity Keys", NULL, NULL },
+
+ { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT INTERFACE " Entity Keys\n */", NULL },
- { REGULAR, NETPROP INTERFACE, DEVICENAME, NULL, CFSTRING },
- { REGULAR, NETPROP INTERFACE, HARDWARE, NULL, CFSTRING },
- { REGULAR, NETPROP INTERFACE, TYPE, NULL, CFSTRING },
- { REGULAR, NETPROP INTERFACE, SUBTYPE, NULL, CFSTRING },
- { DEFINE , NETPROP INTERFACE, SUPPORTSMODEMONHOLD, NULL, CFNUMBER_BOOL },
+ { GROUP, NETPROP INTERFACE, KEY_PREFIX NETENT INTERFACE " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP INTERFACE, DEVICENAME, NULL, CFSTRING },
+ { SC_10_1, NETPROP INTERFACE, HARDWARE, NULL, CFSTRING },
+ { SC_10_1, NETPROP INTERFACE, TYPE, NULL, CFSTRING },
+ { SC_10_1, NETPROP INTERFACE, SUBTYPE, NULL, CFSTRING },
+ { SC_10_2, NETPROP INTERFACE, SUPPORTSMODEMONHOLD, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP INTERFACE TYPE " values */", NULL, NULL, NULL },
- { REGULAR, NETVAL INTERFACE TYPE, ETHERNET, NULL, NULL },
- { DEFINE , NETVAL INTERFACE TYPE, FIREWIRE, NULL, NULL },
- { REGULAR, NETVAL INTERFACE TYPE, PPP, NULL, NULL },
- { DEFINE , NETVAL INTERFACE TYPE, STF, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP INTERFACE TYPE " values ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL INTERFACE TYPE, ETHERNET, NULL, NULL },
+ { SC_10_3, NETVAL INTERFACE TYPE, FIREWIRE, NULL, NULL },
+ { SC_10_1, NETVAL INTERFACE TYPE, PPP, NULL, NULL },
+ { SC_10_3, NETVAL INTERFACE TYPE, STF, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP SERVICE SUBTYPE " values (for " PPP ") */", NULL, NULL, NULL },
- { REGULAR, NETVAL INTERFACE SUBTYPE, PPPOE, NULL, NULL },
- { REGULAR, NETVAL INTERFACE SUBTYPE, PPPSERIAL, NULL, NULL },
- { DEFINE , NETVAL INTERFACE SUBTYPE, PPTP, NULL, NULL },
- { DEFINE , NETVAL INTERFACE SUBTYPE, L2TP, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP SERVICE SUBTYPE " values (for " PPP ") ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL INTERFACE SUBTYPE, PPPOE, NULL, NULL },
+ { SC_10_1, NETVAL INTERFACE SUBTYPE, PPPSERIAL, NULL, NULL },
+ { SC_10_2, NETVAL INTERFACE SUBTYPE, PPTP, NULL, NULL },
+ { SC_10_3, NETVAL INTERFACE SUBTYPE, L2TP, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV4 " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP IPV4, ADDRESSES, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP IPV4, CONFIGMETHOD, NULL, CFSTRING },
- { REGULAR, NETPROP IPV4, DHCPCLIENTID, NULL, CFSTRING },
- { REGULAR, NETPROP IPV4, ROUTER, NULL, CFSTRING },
- { REGULAR, NETPROP IPV4, SUBNETMASKS, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP IPV4, DESTADDRESSES, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP IPV4, BROADCASTADDRESSES, NULL, CFARRAY_CFSTRING },
+ { GROUP, NETPROP IPV4, KEY_PREFIX NETENT IPV4 " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP IPV4, ADDRESSES, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP IPV4, CONFIGMETHOD, NULL, CFSTRING },
+ { SC_10_1, NETPROP IPV4, DHCPCLIENTID, NULL, CFSTRING },
+ { SC_10_1, NETPROP IPV4, ROUTER, NULL, CFSTRING },
+ { SC_10_1, NETPROP IPV4, SUBNETMASKS, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP IPV4, DEST ADDRESSES, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP IPV4, BROADCAST ADDRESSES, NULL, CFARRAY_CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP IPV4 CONFIGMETHOD " values */", NULL, NULL, NULL },
- { REGULAR, NETVAL IPV4 CONFIGMETHOD, BOOTP, NULL, NULL },
- { REGULAR, NETVAL IPV4 CONFIGMETHOD, DHCP, NULL, NULL },
- { REGULAR, NETVAL IPV4 CONFIGMETHOD, INFORM, NULL, NULL },
- { REGULAR, NETVAL IPV4 CONFIGMETHOD, LINKLOCAL, NULL, NULL },
- { REGULAR, NETVAL IPV4 CONFIGMETHOD, MANUAL, NULL, NULL },
- { REGULAR, NETVAL IPV4 CONFIGMETHOD, PPP, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP IPV4 CONFIGMETHOD " values ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL IPV4 CONFIGMETHOD, BOOTP, NULL, NULL },
+ { SC_10_1, NETVAL IPV4 CONFIGMETHOD, DHCP, NULL, NULL },
+ { SC_10_1, NETVAL IPV4 CONFIGMETHOD, INFORM, NULL, NULL },
+ { SC_10_2, NETVAL IPV4 CONFIGMETHOD, LINKLOCAL, NULL, NULL },
+ { SC_10_1, NETVAL IPV4 CONFIGMETHOD, MANUAL, NULL, NULL },
+ { SC_10_1, NETVAL IPV4 CONFIGMETHOD, PPP, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV6 " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP IPV6, ADDRESSES, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP IPV6, CONFIGMETHOD, NULL, CFSTRING },
- { DEFINE , NETPROP IPV6, DESTADDRESSES, NULL, CFARRAY_CFSTRING },
- { DEFINE , NETPROP IPV6, FLAGS, NULL, CFNUMBER },
- { DEFINE , NETPROP IPV6, PREFIXLENGTH, NULL, CFARRAY_CFNUMBER },
- { DEFINE , NETPROP IPV6, ROUTER, NULL, CFSTRING },
+ { GROUP, NETPROP IPV6, KEY_PREFIX NETENT IPV6 " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP IPV6, ADDRESSES, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP IPV6, CONFIGMETHOD, NULL, CFSTRING },
+ { SC_10_3, NETPROP IPV6, DEST ADDRESSES, NULL, CFARRAY_CFSTRING },
+ { SC_10_3, NETPROP IPV6, FLAGS, NULL, CFNUMBER },
+ { SC_10_3, NETPROP IPV6, PREFIXLENGTH, NULL, CFARRAY_CFNUMBER },
+ { SC_10_3, NETPROP IPV6, ROUTER, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP IPV6 CONFIGMETHOD " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL IPV6 CONFIGMETHOD, AUTOMATIC, NULL, NULL },
- { DEFINE , NETVAL IPV6 CONFIGMETHOD, MANUAL, NULL, NULL },
- { DEFINE , NETVAL IPV6 CONFIGMETHOD, ROUTERADVERTISEMENT, NULL, NULL },
- { DEFINE , NETVAL IPV6 CONFIGMETHOD, STF, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP IPV6 CONFIGMETHOD " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL IPV6 CONFIGMETHOD, AUTOMATIC, NULL, NULL },
+ { SC_10_3, NETVAL IPV6 CONFIGMETHOD, MANUAL, NULL, NULL },
+ { SC_10_3, NETVAL IPV6 CONFIGMETHOD, ROUTERADVERTISEMENT, NULL, NULL },
+ { SC_10_3, NETVAL IPV6 CONFIGMETHOD, STF, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT STF " Entity Keys\n */", NULL, NULL, NULL },
- { DEFINE , NETPROP STF, RELAY, NULL, CFSTRING },
+ { GROUP, NETPROP STF, KEY_PREFIX NETENT STF " Entity Keys", NULL, NULL },
+
+ { SC_10_3, NETPROP STF, RELAY, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT LINK " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP LINK, ACTIVE, NULL, CFBOOLEAN },
- { DEFINE , NETPROP LINK, DETACHING, NULL, CFBOOLEAN },
+ { GROUP, NETPROP LINK, KEY_PREFIX NETENT LINK " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP LINK, ACTIVE, NULL, CFBOOLEAN },
+ { SC_10_2, NETPROP LINK, DETACHING, NULL, CFBOOLEAN },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT MODEM " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP MODEM, CONNECTIONSCRIPT, NULL, CFSTRING },
- { DEFINE , NETPROP MODEM, CONNECTSPEED, NULL, CFNUMBER },
- { DEFINE , NETPROP MODEM, DATACOMPRESSION, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP MODEM, DIALMODE, NULL, CFSTRING },
- { DEFINE , NETPROP MODEM, ERRORCORRECTION, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP MODEM, HOLD CALLWAITINGAUDIBLEALERT, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP MODEM, HOLD DISCONNECTONANSWER, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP MODEM, HOLD ENABLED, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP MODEM, HOLD REMINDER, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP MODEM, HOLD REMINDERTIME, NULL, CFNUMBER },
- { DEFINE , NETPROP MODEM, NOTE, NULL, CFSTRING },
- { REGULAR, NETPROP MODEM, PULSEDIAL, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP MODEM, SPEAKER, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP MODEM, SPEED, NULL, CFNUMBER },
+ { GROUP, NETPROP MODEM, KEY_PREFIX NETENT MODEM " (Hardware) Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP MODEM, CONNECTIONSCRIPT, NULL, CFSTRING },
+ { SC_10_2, NETPROP MODEM, CONNECTSPEED, NULL, CFNUMBER },
+ { SC_10_1, NETPROP MODEM, DATACOMPRESSION, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP MODEM, DIALMODE, NULL, CFSTRING },
+ { SC_10_1, NETPROP MODEM, ERRORCORRECTION, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP MODEM, HOLD CALLWAITINGAUDIBLEALERT, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP MODEM, HOLD DISCONNECTONANSWER, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP MODEM, HOLD ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP MODEM, HOLD REMINDER, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP MODEM, HOLD REMINDERTIME, NULL, CFNUMBER },
+ { SC_10_2, NETPROP MODEM, NOTE, NULL, CFSTRING },
+ { SC_10_1, NETPROP MODEM, PULSEDIAL, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP MODEM, SPEAKER, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP MODEM, SPEED, NULL, CFNUMBER },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP MODEM DIALMODE " values */", NULL, NULL, NULL },
- { REGULAR, NETVAL MODEM DIALMODE, IGNOREDIALTONE, NULL, NULL },
- { REGULAR, NETVAL MODEM DIALMODE, MANUAL, NULL, NULL },
- { REGULAR, NETVAL MODEM DIALMODE, WAITFORDIALTONE, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP MODEM DIALMODE " values ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL MODEM DIALMODE, IGNOREDIALTONE, NULL, NULL },
+ { SC_10_1, NETVAL MODEM DIALMODE, MANUAL, NULL, NULL },
+ { SC_10_1, NETVAL MODEM DIALMODE, WAITFORDIALTONE, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT NETINFO " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP NETINFO, BINDINGMETHODS, NULL, CFSTRING },
- { REGULAR, NETPROP NETINFO, SERVERADDRESSES, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP NETINFO, SERVERTAGS, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP NETINFO, BROADCASTSERVERTAG, NULL, CFSTRING },
- { COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP NETINFO BINDINGMETHODS " values */", NULL, NULL, NULL },
- { REGULAR, NETVAL NETINFO BINDINGMETHODS, BROADCAST, NULL, NULL },
- { REGULAR, NETVAL NETINFO BINDINGMETHODS, DHCP, NULL, NULL },
- { REGULAR, NETVAL NETINFO BINDINGMETHODS, MANUAL, NULL, NULL },
+ { GROUP, NETPROP NETINFO, KEY_PREFIX NETENT NETINFO " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP NETINFO, BINDINGMETHODS, NULL, CFSTRING },
+ { SC_10_1, NETPROP NETINFO, SERVER ADDRESSES, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP NETINFO, SERVER TAGS, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP NETINFO, BROADCAST SERVER TAG, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP NETINFO BROADCASTSERVERTAG " default value */", NULL, NULL, NULL },
- { REGULAR, NETVAL NETINFO, DEFAULTSERVERTAG, "network", NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP NETINFO BINDINGMETHODS " values ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL NETINFO BINDINGMETHODS, BROADCAST, NULL, NULL },
+ { SC_10_1, NETVAL NETINFO BINDINGMETHODS, DHCP, NULL, NULL },
+ { SC_10_1, NETVAL NETINFO BINDINGMETHODS, MANUAL, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
-
- { COMMENT, "/*\n * " KEY_PREFIX NETENT NIS " Entity Keys\n */", NULL, NULL, NULL },
- { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP NETINFO BROADCAST SERVER TAG " default value ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL NETINFO, DEFAULT SERVER TAG, "network", NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT PPP " Entity Keys\n */", NULL, NULL, NULL },
- { DEFINE , NETPROP PPP, ACSPENABLED, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP PPP, CONNECTTIME, NULL, CFNUMBER },
- { DEFINE , NETPROP PPP, DEVICE LASTCAUSE, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, DIALONDEMAND, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, DISCONNECTONIDLE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP PPP, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP PPP, DISCONNECTTIME, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP PPP, LASTCAUSE, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, LOGFILE, NULL, CFSTRING },
- { DEFINE , NETPROP PPP, PLUGINS, NULL, CFARRAY_CFSTRING },
- { DEFINE , NETPROP PPP, RETRYCONNECTTIME, NULL, CFNUMBER },
- { DEFINE , NETPROP PPP, SESSIONTIMER, NULL, CFNUMBER },
- { DEFINE , NETPROP PPP, STATUS, NULL, CFNUMBER },
- { DEFINE , NETPROP PPP, USE SESSIONTIMER, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, VERBOSELOGGING, NULL, CFNUMBER_BOOL },
+ { GROUP, NETPROP PPP, KEY_PREFIX NETENT PPP " Entity Keys", NULL, NULL },
+
+ { SC_10_3, NETPROP PPP, ACSP ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP PPP, CONNECTTIME, NULL, CFNUMBER },
+ { SC_10_2, NETPROP PPP, DEVICE LAST CAUSE, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, DIALONDEMAND, NULL, CFNUMBER_BOOL },
+ { SC_10_4, NETPROP PPP, DISCONNECTONFASTUSERSWITCH, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, DISCONNECTONIDLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP PPP, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL },
+ { SC_10_3, NETPROP PPP, DISCONNECTTIME, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL },
+ { SC_10_2, NETPROP PPP, LAST CAUSE, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, LOGFILE, NULL, CFSTRING },
+ { SC_10_2, NETPROP PPP, PLUGINS, NULL, CFARRAY_CFSTRING },
+ { SC_10_3, NETPROP PPP, RETRYCONNECTTIME, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, SESSIONTIMER, NULL, CFNUMBER },
+ { SC_10_2, NETPROP PPP, STATUS, NULL, CFNUMBER },
+ { SC_10_2, NETPROP PPP, USE SESSIONTIMER, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, VERBOSELOGGING, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " AUTH ": */", NULL, NULL, NULL },
- { DEFINE , NETPROP PPP, AUTH EAP PLUGINS, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP PPP, AUTH NAME, NULL, CFSTRING },
- { REGULAR, NETPROP PPP, AUTH PASSWORD, NULL, CFSTRING },
- { REGULAR, NETPROP PPP, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
- { DEFINE , NETPROP PPP, AUTH PROMPT, NULL, CFSTRING },
- { REGULAR, NETPROP PPP, AUTH PROTOCOL, NULL, CFARRAY_CFSTRING },
+ { COMMENT, "--- " AUTH ": ---", NULL, NULL, NULL },
+ { SC_10_3, NETPROP PPP, AUTH EAP PLUGINS, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, NETPROP PPP, AUTH NAME, NULL, CFSTRING },
+ { SC_10_1, NETPROP PPP, AUTH PASSWORD, NULL, CFSTRING },
+ { SC_10_1, NETPROP PPP, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+ { SC_10_3, NETPROP PPP, AUTH PROMPT, NULL, CFSTRING },
+ { SC_10_1, NETPROP PPP, AUTH PROTOCOL, NULL, CFARRAY_CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PASSWORD ENCRYPTION " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL PPP AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP PPP AUTH PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL PPP AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROMPT " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL PPP AUTH PROMPT, BEFORE, NULL, CFSTRING },
- { DEFINE , NETVAL PPP AUTH PROMPT, AFTER, NULL, CFSTRING },
+ { COMMENT, "--- " KEY_PREFIX NETPROP PPP AUTH PROMPT " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL PPP AUTH PROMPT, BEFORE, NULL, CFSTRING },
+ { SC_10_3, NETVAL PPP AUTH PROMPT, AFTER, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROTOCOL " values */", NULL, NULL, NULL },
- { REGULAR, NETVAL PPP AUTH PROTOCOL, CHAP, NULL, CFSTRING },
- { DEFINE , NETVAL PPP AUTH PROTOCOL, EAP, NULL, CFSTRING },
- { DEFINE , NETVAL PPP AUTH PROTOCOL, MSCHAP1, NULL, CFSTRING },
- { DEFINE , NETVAL PPP AUTH PROTOCOL, MSCHAP2, NULL, CFSTRING },
- { REGULAR, NETVAL PPP AUTH PROTOCOL, PAP, NULL, CFSTRING },
-
- { COMMENT, "\n/* " COMM ": */", NULL, NULL, NULL },
- { REGULAR, NETPROP PPP, COMM ALTERNATEREMOTEADDRESS, NULL, CFSTRING },
- { REGULAR, NETPROP PPP, COMM CONNECTDELAY, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, COMM DISPLAYTERMINALWINDOW, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, COMM REDIALCOUNT, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, COMM REDIALENABLED, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, COMM REDIALINTERVAL, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, COMM REMOTEADDRESS, NULL, CFSTRING },
- { REGULAR, NETPROP PPP, COMM TERMINALSCRIPT, NULL, CFSTRING },
- { DEFINE , NETPROP PPP, COMM USE TERMINALSCRIPT, NULL, CFNUMBER_BOOL },
-
- { COMMENT, "\n/* " CCP ": */", NULL, NULL, NULL },
- { DEFINE , NETPROP PPP, CCP ENABLED, NULL, CFNUMBER_BOOL },
-
- { COMMENT, "\n/* " IPCP ": */", NULL, NULL, NULL },
- { REGULAR, NETPROP PPP, IPCP COMPRESSIONVJ, NULL, CFNUMBER_BOOL },
-
- { COMMENT, "\n/* " LCP ": */", NULL, NULL, NULL },
- { REGULAR, NETPROP PPP, LCP ECHOENABLED, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, LCP ECHOFAILURE, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, LCP ECHOINTERVAL, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, LCP COMPRESSIONACFIELD, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, LCP COMPRESSIONPFIELD, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PPP, LCP MRU, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, LCP MTU, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, LCP RECEIVEACCM, NULL, CFNUMBER },
- { REGULAR, NETPROP PPP, LCP TRANSMITACCM, NULL, CFNUMBER },
+ { COMMENT, "--- " KEY_PREFIX NETPROP PPP AUTH PROTOCOL " values ---", NULL, NULL, NULL },
+ { SC_10_1, NETVAL PPP AUTH PROTOCOL, CHAP, NULL, CFSTRING },
+ { SC_10_3, NETVAL PPP AUTH PROTOCOL, EAP, NULL, CFSTRING },
+ { SC_10_3, NETVAL PPP AUTH PROTOCOL, MSCHAP1, NULL, CFSTRING },
+ { SC_10_3, NETVAL PPP AUTH PROTOCOL, MSCHAP2, NULL, CFSTRING },
+ { SC_10_1, NETVAL PPP AUTH PROTOCOL, PAP, NULL, CFSTRING },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT PPPOE " Entity Keys\n */", NULL, NULL, NULL },
- { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+ { COMMENT, "--- " COMM ": ---", NULL, NULL, NULL },
+ { SC_10_1, NETPROP PPP, COMM ALTERNATEREMOTEADDRESS, NULL, CFSTRING },
+ { SC_10_1, NETPROP PPP, COMM CONNECTDELAY, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, COMM DISPLAYTERMINALWINDOW, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, COMM REDIALCOUNT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, COMM REDIAL ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, COMM REDIALINTERVAL, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, COMM REMOTEADDRESS, NULL, CFSTRING },
+ { SC_10_1, NETPROP PPP, COMM TERMINALSCRIPT, NULL, CFSTRING },
+ { SC_10_2, NETPROP PPP, COMM USE TERMINALSCRIPT, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT PPPSERIAL " Entity Keys\n */", NULL, NULL, NULL },
- { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+ { COMMENT, "--- " CCP ": ---", NULL, NULL, NULL },
+ { SC_10_2, NETPROP PPP, CCP ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_4, NETPROP PPP, CCP MPPE40 ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_4, NETPROP PPP, CCP MPPE128 ENABLED, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT PPTP " Entity Keys\n */", NULL, NULL, NULL },
- { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+ { COMMENT, "--- " IPCP ": ---", NULL, NULL, NULL },
+ { SC_10_1, NETPROP PPP, IPCP COMPRESSIONVJ, NULL, CFNUMBER_BOOL },
+ { SC_10_4, NETPROP PPP, IPCP USE PEERDNS, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT L2TP " Entity Keys\n */", NULL, NULL, NULL },
- { DEFINE , NETPROP L2TP, IPSEC SHAREDSECRET, NULL, CFSTRING },
- { DEFINE , NETPROP L2TP, IPSEC SHAREDSECRET ENCRYPTION, NULL, CFSTRING },
- { DEFINE , NETPROP L2TP, TRANSPORT, NULL, CFSTRING },
+ { COMMENT, "--- " LCP ": ---", NULL, NULL, NULL },
+ { SC_10_1, NETPROP PPP, LCP ECHO ENABLED, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, LCP ECHOFAILURE, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, LCP ECHOINTERVAL, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, LCP COMPRESSIONACFIELD, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, LCP COMPRESSIONPFIELD, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PPP, LCP MRU, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, LCP MTU, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, LCP RECEIVEACCM, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PPP, LCP TRANSMITACCM, NULL, CFNUMBER },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP L2TP IPSEC SHAREDSECRET ENCRYPTION " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL L2TP IPSEC SHAREDSECRET ENCRYPTION, KEYCHAIN, NULL, NULL },
+
+ { GROUP, NETPROP PPPOE, KEY_PREFIX NETENT PPPOE " Entity Keys", NULL, NULL },
+
+ { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX NETPROP L2TP TRANSPORT " values */", NULL, NULL, NULL },
- { DEFINE , NETVAL L2TP TRANSPORT, IP, NULL, NULL },
- { DEFINE , NETVAL L2TP TRANSPORT, IPSEC, NULL, NULL },
+
+ { GROUP, NETPROP PPPSERIAL, KEY_PREFIX NETENT PPPSERIAL " Entity Keys", NULL, NULL },
+
+ { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX NETENT PROXIES " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, NETPROP PROXIES, EXCEPTIONSLIST, NULL, CFARRAY_CFSTRING },
- { REGULAR, NETPROP PROXIES, FTPENABLE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PROXIES, FTPPASSIVE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PROXIES, FTPPORT, NULL, CFNUMBER },
- { REGULAR, NETPROP PROXIES, FTPPROXY, NULL, CFSTRING },
- { REGULAR, NETPROP PROXIES, GOPHERENABLE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PROXIES, GOPHERPORT, NULL, CFNUMBER },
- { REGULAR, NETPROP PROXIES, GOPHERPROXY, NULL, CFSTRING },
- { REGULAR, NETPROP PROXIES, HTTPENABLE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PROXIES, HTTPPORT, NULL, CFNUMBER },
- { REGULAR, NETPROP PROXIES, HTTPPROXY, NULL, CFSTRING },
- { DEFINE , NETPROP PROXIES, HTTPSENABLE, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP PROXIES, HTTPSPORT, NULL, CFNUMBER },
- { DEFINE , NETPROP PROXIES, HTTPSPROXY, NULL, CFSTRING },
- { REGULAR, NETPROP PROXIES, RTSPENABLE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PROXIES, RTSPPORT, NULL, CFNUMBER },
- { REGULAR, NETPROP PROXIES, RTSPPROXY, NULL, CFSTRING },
- { REGULAR, NETPROP PROXIES, SOCKSENABLE, NULL, CFNUMBER_BOOL },
- { REGULAR, NETPROP PROXIES, SOCKSPORT, NULL, CFNUMBER },
- { REGULAR, NETPROP PROXIES, SOCKSPROXY, NULL, CFSTRING },
- { DEFINE , NETPROP PROXIES, PROXYAUTOCONFIGENABLE, NULL, CFNUMBER_BOOL },
- { DEFINE , NETPROP PROXIES, PROXYAUTOCONFIGURLSTRING, NULL, CFSTRING },
+ { GROUP, NETPROP PPTP, KEY_PREFIX NETENT PPTP " Entity Keys", NULL, NULL },
+
+ { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n " KEY_PREFIX COMP USERS " Entity Keys\n */", NULL, NULL, NULL },
- { REGULAR, USERSENT, CONSOLEUSER, NULL, NULL },
+ { GROUP, NETPROP L2TP, KEY_PREFIX NETENT L2TP " Entity Keys", NULL, NULL },
+
+ { SC_10_3, NETPROP L2TP, IPSEC SHAREDSECRET, NULL, CFSTRING },
+ { SC_10_3, NETPROP L2TP, IPSEC SHAREDSECRET ENCRYPTION, NULL, CFSTRING },
+ { SC_10_3, NETPROP L2TP, TRANSPORT, NULL, CFSTRING },
+ { COMMENT, "", NULL, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP L2TP IPSEC SHAREDSECRET ENCRYPTION " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL L2TP IPSEC SHAREDSECRET ENCRYPTION, KEYCHAIN, NULL, NULL },
+ { COMMENT, "", NULL, NULL, NULL },
+ { COMMENT, "--- " KEY_PREFIX NETPROP L2TP TRANSPORT " values ---", NULL, NULL, NULL },
+ { SC_10_3, NETVAL L2TP TRANSPORT, IP, NULL, NULL },
+ { SC_10_3, NETVAL L2TP TRANSPORT, IPSEC, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * " KEY_PREFIX COMP SYSTEM " Properties\n */", NULL, NULL, NULL },
- { REGULAR, SYSTEMPROP, COMPUTERNAME, NULL, CFSTRING },
- { REGULAR, SYSTEMPROP, COMPUTERNAME ENCODING, NULL, CFNUMBER },
+ { GROUP, NETPROP PROXIES, KEY_PREFIX NETENT PROXIES " Entity Keys", NULL, NULL },
+
+ { SC_10_1, NETPROP PROXIES, EXCEPTIONSLIST, NULL, CFARRAY_CFSTRING },
+ { SC_10_4, NETPROP PROXIES, EXCLUDESIMPLEHOSTNAMES, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, FTP ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, FTP PASSIVE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, FTP PORT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PROXIES, FTP PROXY, NULL, CFSTRING },
+ { SC_10_1, NETPROP PROXIES, GOPHER ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, GOPHER PORT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PROXIES, GOPHER PROXY, NULL, CFSTRING },
+ { SC_10_1, NETPROP PROXIES, HTTP ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, HTTP PORT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PROXIES, HTTP PROXY, NULL, CFSTRING },
+ { SC_10_1, NETPROP PROXIES, HTTPS ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, HTTPS PORT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PROXIES, HTTPS PROXY, NULL, CFSTRING },
+ { SC_10_1, NETPROP PROXIES, RTSP ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, RTSP PORT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PROXIES, RTSP PROXY, NULL, CFSTRING },
+ { SC_10_1, NETPROP PROXIES, SOCKS ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_1, NETPROP PROXIES, SOCKS PORT, NULL, CFNUMBER },
+ { SC_10_1, NETPROP PROXIES, SOCKS PROXY, NULL, CFSTRING },
+ { SC_10_4, NETPROP PROXIES, PROXY AUTOCONFIG ENABLE, NULL, CFNUMBER_BOOL },
+ { SC_10_4, NETPROP PROXIES, PROXY AUTOCONFIG URLSTRING, NULL, CFSTRING },
+ { SC_10_4, NETPROP PROXIES, PROXY AUTODISCOVERY ENABLE, NULL, CFNUMBER_BOOL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Configuration Store Definitions\n */", NULL },
- { COMMENT, "/* domain prefixes */", NULL },
- { DEFINE , DYNAMICSTORE DOMAIN, FILE, "File:", NULL },
- { DEFINE , DYNAMICSTORE DOMAIN, PLUGIN, "Plugin:", NULL },
- { DEFINE , DYNAMICSTORE DOMAIN, SETUP, "Setup:", NULL },
- { DEFINE , DYNAMICSTORE DOMAIN, STATE, "State:", NULL },
- { DEFINE , DYNAMICSTORE DOMAIN, PREFS, "Prefs:", NULL },
+ { GROUP, USERSENT CONSOLEUSER, KEY_PREFIX COMP USERS " Entity Keys", NULL, NULL },
+
+ { SC_10_1, USERSENT, CONSOLEUSER, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* " KEY_PREFIX DYNAMICSTORE DOMAIN SETUP " Properties */", NULL },
- { DEFINE , DYNAMICSTORE SETUPPROP, CURRENTSET, NULL, CFSTRING },
- { DEFINE , DYNAMICSTORE SETUPPROP, LASTUPDATED, NULL, NULL },
+ { GROUP, SYSTEMPROP COMPUTERNAME, KEY_PREFIX COMP SYSTEM " Properties", NULL, NULL },
+
+ { SC_10_1, SYSTEMPROP, COMPUTERNAME, NULL, CFSTRING },
+ { SC_10_1, SYSTEMPROP, COMPUTERNAME ENCODING, NULL, CFNUMBER },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/* Properties */", NULL },
- { DEFINE , DYNAMICSTORE NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
- { DEFINE , DYNAMICSTORE NETPROP, PRIMARYINTERFACE, NULL, CFSTRING },
- { DEFINE , DYNAMICSTORE NETPROP, PRIMARYSERVICE, NULL, CFSTRING },
- { DEFINE , DYNAMICSTORE NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING },
+ { GROUP, DYNAMICSTORE DOMAIN, "SCDynamicStore \"domain\" prefixes", NULL, NULL },
+
+ { SC_10_1, DYNAMICSTORE DOMAIN, FILE, "File:", NULL },
+ { SC_10_1, DYNAMICSTORE DOMAIN, PLUGIN, "Plugin:", NULL },
+ { SC_10_1, DYNAMICSTORE DOMAIN, SETUP, "Setup:", NULL },
+ { SC_10_1, DYNAMICSTORE DOMAIN, STATE, "State:", NULL },
+ { SC_10_1, DYNAMICSTORE DOMAIN, PREFS, "Prefs:", NULL },
{ COMMENT, "", NULL, NULL, NULL },
- { COMMENT, "/*\n * Obsolete schema definitions which will be removed \"soon\".\n */", NULL },
- { OBSOLETE, USERSPROP CONSOLEUSER, NAME, NULL, CFSTRING },
- { OBSOLETE, USERSPROP CONSOLEUSER, UID, NULL, CFNUMBER },
- { OBSOLETE, USERSPROP CONSOLEUSER, GID, NULL, CFNUMBER },
+ { GROUP, DYNAMICSTORE SETUPPROP, "Preference (\"location\") Keys", NULL, NULL },
+
+ { SC_10_1, DYNAMICSTORE SETUPPROP, CURRENTSET, NULL, CFSTRING },
+ { SC_10_1, DYNAMICSTORE SETUPPROP, LAST UPDATED, NULL, NULL },
{ COMMENT, "", NULL, NULL, NULL },
+ { GROUP, DYNAMICSTORE NETPROP, "Common/shared Keys", NULL, NULL },
+
+ { SC_10_1, DYNAMICSTORE NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
+ { SC_10_1, DYNAMICSTORE NETPROP, PRIMARYINTERFACE, NULL, CFSTRING },
+ { SC_10_1, DYNAMICSTORE NETPROP, PRIMARYSERVICE, NULL, CFSTRING },
+ { SC_10_1, DYNAMICSTORE NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING },
+// { COMMENT, "", NULL, NULL, NULL },
+
+//{ GROUP, "DEPRECATED", "Deprecated schema definition keys", NULL, NULL },
+
+ { SC_10_1_10_3, USERSPROP CONSOLEUSER, NAME, NULL, CFSTRING },
+ { SC_10_1_10_3, USERSPROP CONSOLEUSER, UID, NULL, CFNUMBER },
+ { SC_10_1_10_3, USERSPROP CONSOLEUSER, GID, NULL, CFNUMBER },
+// { COMMENT, "", NULL, NULL, NULL },
+
{ END, NULL, NULL, NULL, NULL },
};
enum {
gen_header_e,
+ gen_comments_e,
+ gen_headerdoc_e,
gen_hfile_e,
gen_cfile_e,
};
goto done;
break;
}
+
case COMMENT: {
switch (type) {
- case gen_header_e:
- case gen_hfile_e:
- if (names[i].prefix)
- printf("%s\n", names[i].prefix);
- break;
- default:
- break;
+ case gen_header_e:
+ break;
+ case gen_comments_e:
+ if (names[i].prefix)
+ printf(" * %s\n", names[i].prefix);
+ break;
+ case gen_hfile_e:
+// if (names[i].prefix)
+// printf("%s\n", names[i].prefix);
+ break;
+ default:
+ break;
}
break;
}
- case DEFINE: {
- char kbuf[256];
- char vbuf[256];
+ case GROUP: {
switch (type) {
- case gen_header_e:
- snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
- names[i].prefix, names[i].key);
-
- if (names[i].value)
- snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
- names[i].value);
- else
- snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
- names[i].key);
-
- if (names[i].type)
- printf("#define %-40s %-40s /* %s */\n",
- kbuf, vbuf, names[i].type);
- else
- printf("#define %-40s %-40s\n",
- kbuf, vbuf);
- break;
- case gen_hfile_e:
- snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
- names[i].prefix, names[i].key);
- setmax(&maxkbuf, &maxkstr, kbuf);
-
- snprintf(vbuf, sizeof(vbuf), "\"%s\"",
- names[i].value ? names[i].value : names[i].key);
- setmax(&maxvbuf, &maxvstr, vbuf);
-
- printf("SC_SCHEMA_DECLARATION%-42s /* %-17s %-30s */\n",
- kbuf,
- names[i].type ? names[i].type : "",
- vbuf);
- break;
- case gen_cfile_e:
- snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
- names[i].prefix, names[i].key);
-
- if (names[i].value)
- printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
- kbuf, names[i].value);
- else
- printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
- kbuf, names[i].key);
- break;
- default:
- break;
+ case gen_header_e:
+ break;
+ case gen_comments_e:
+ if (names[i].key)
+ printf(" * %s\n *\n", names[i].key);
+ break;
+ case gen_headerdoc_e:
+ if (names[i].prefix)
+ printf("\n/*!\n @group %s\n */\n", names[i].key);
+ break;
+ default:
+ break;
}
break;
}
- case REGULAR: {
- char kbuf[256];
- char vbuf[256];
- switch (type) {
- case gen_header_e:
- snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
- names[i].prefix, names[i].key);
-
- if (names[i].value)
- snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
- names[i].value);
- else
- snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
- names[i].key);
-
- if (names[i].type)
- printf("#define %-40s %-40s /* %s */\n",
- kbuf, vbuf, names[i].type);
- else
- printf("#define %-40s %-40s\n",
- kbuf, vbuf);
- break;
- case gen_hfile_e:
- snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
- names[i].prefix, names[i].key);
- setmax(&maxkbuf, &maxkstr, kbuf);
-
- snprintf(vbuf, sizeof(vbuf), "\"%s\"",
- names[i].value ? names[i].value : names[i].key);
- setmax(&maxvbuf, &maxvstr, vbuf);
-
- printf("SC_SCHEMA_DECLARATION%-42s /* %-17s %-30s */\n",
- kbuf,
- names[i].type ? names[i].type : "",
- vbuf);
- break;
- case gen_cfile_e:
- snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
- names[i].prefix, names[i].key);
-
- if (names[i].value)
- printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
- kbuf, names[i].value);
- else
- printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
- kbuf, names[i].key);
- break;
- default:
- break;
- }
- break;
- }
- case OBSOLETE: {
- static int nObsolete = 0;
+ default: {
char kbuf[256];
char vbuf[256];
switch (type) {
- case gen_hfile_e:
- if (nObsolete++ == 0) {
- printf("#ifndef SCSTR\n");
- printf("#include <CoreFoundation/CFString.h>\n");
- printf("#define SCSTR(s) CFSTR(s)\n");
- printf("#endif\n");
- }
-
- snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
- names[i].prefix, names[i].key);
-
- if (names[i].value)
- snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
- names[i].value);
- else
- snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
- names[i].key);
-
- printf("#define %-40s %-40s /* %s */\n",
- kbuf,
- vbuf,
- names[i].type ? names[i].type : "");
- break;
- default:
- break;
- }
- break;
- }
- case FUTURE: {
- char kbuf[256];
-
- switch (type) {
- case gen_header_e:
- snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
- names[i].prefix, names[i].key);
-
- printf("// #define %-37s %-40s /* %s */\n",
- kbuf,
- "SCSTR(\"???\") */",
- "RESERVED FOR FUTURE USE");
- break;
- case gen_hfile_e:
- snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
- names[i].prefix, names[i].key);
- setmax(&maxkbuf, &maxkstr, kbuf);
-
- printf("// SC_SCHEMA_DECLARATION%-39s /* %s */\n",
- kbuf, "RESERVED FOR FUTURE USE");
- break;
- default:
- break;
+ case gen_header_e:
+ snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+ names[i].prefix, names[i].key);
+
+ if (names[i].value)
+ snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
+ names[i].value);
+ else
+ snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
+ names[i].key);
+
+ printf("#define %-50s %s\n",
+ kbuf, vbuf);
+ break;
+ case gen_comments_e:
+ switch (names[i].control) {
+ case SC_10_1_10_3:
+ // don't report deprecated keys
+ break;
+ default:
+ snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+ names[i].prefix, names[i].key);
+
+ snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+ names[i].value ? names[i].value : names[i].key);
+
+ if (names[i].type)
+ printf(" * %-50s %-30s %s\n",
+ kbuf, vbuf, names[i].type);
+ else
+ printf(" * %-50s %s\n",
+ kbuf, vbuf);
+ break;
+ }
+ break;
+ case gen_headerdoc_e:
+ snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+ names[i].prefix, names[i].key);
+ setmax(&maxkbuf, &maxkstr, kbuf);
+
+ snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+ names[i].value ? names[i].value : names[i].key);
+ setmax(&maxvbuf, &maxvstr, vbuf);
+
+ printf("\n");
+
+ printf("/*!\n");
+ printf(" @const %s\n", kbuf);
+ switch (names[i].control) {
+ case SC_10_1:
+ printf(" @availability Introduced in Mac OS X 10.1.\n");
+ break;
+ case SC_10_2:
+ printf(" @availability Introduced in Mac OS X 10.2.\n");
+ break;
+ case SC_10_1_10_3:
+ printf(" @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.\n");
+ break;
+ case SC_10_3:
+ printf(" @availability Introduced in Mac OS X 10.3.\n");
+ break;
+ case SC_10_4:
+ printf(" @availability Introduced in Mac OS X 10.4.\n");
+ break;
+ }
+ printf(" */\n");
+ printf("extern const CFStringRef %s;\n", kbuf);
+
+ break;
+ case gen_hfile_e:
+ snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+ names[i].prefix, names[i].key);
+ setmax(&maxkbuf, &maxkstr, kbuf);
+
+ snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+ names[i].value ? names[i].value : names[i].key);
+ setmax(&maxvbuf, &maxvstr, vbuf);
+
+ printf("\n");
+
+ switch (names[i].control) {
+ case SC_10_2:
+ printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2\n");
+ break;
+ case SC_10_1_10_3:
+ printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \\\n");
+ printf(" MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3\n");
+ break;
+ case SC_10_3:
+ printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3\n");
+ break;
+ case SC_10_4:
+ printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4\n");
+ break;
+ }
+
+ printf("#define %-48s \\\n",
+ kbuf);
+ printf("\tSC_SCHEMA_KV(%-48s \\\n",
+ kbuf);
+ printf("\t ,%-48s \\\n",
+ vbuf);
+ printf("\t ,%-48s )\n",
+ names[i].type ? names[i].type : "");
+
+ switch (names[i].control) {
+ case SC_10_2:
+ case SC_10_3:
+ case SC_10_1_10_3:
+ case SC_10_4:
+ printf("#endif\n");
+ break;
+ }
+
+ switch (names[i].control) {
+ case SC_10_2:
+ printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);\n", kbuf);
+ break;
+ case SC_10_3:
+ printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);\n", kbuf);
+ break;
+ case SC_10_1_10_3:
+ printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);\n", kbuf);
+ break;
+ case SC_10_4:
+ printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);\n", kbuf);
+ break;
+ default:
+ printf("\tSC_SCHEMA_DECLARATION(%s,);\n", kbuf);
+ break;
+ }
+
+ break;
+ case gen_cfile_e:
+ snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+ names[i].prefix, names[i].key);
+
+ if (names[i].value)
+ printf("const CFStringRef %-48s = CFSTR(\"%s\");\n",
+ kbuf, names[i].value);
+ else
+ printf("const CFStringRef %-48s = CFSTR(\"%s\");\n",
+ kbuf, names[i].key);
+ break;
+ default:
+ break;
}
break;
}
- default: {
- break;
- }
}
}
done:
switch (type) {
- case gen_hfile_e:
- fprintf(stderr, "max key: length = %2d, string = %s\n", maxkbuf, maxkstr);
- fprintf(stderr, "max val: length = %2d, string = %s\n", maxvbuf, maxvstr);
- break;
+ case gen_hfile_e:
+ fprintf(stderr, "max key: length = %2d, string = %s\n", maxkbuf, maxkstr);
+ fprintf(stderr, "max val: length = %2d, string = %s\n", maxvbuf, maxvstr);
+ break;
}
return;
}
printf("#ifndef _SCSCHEMADEFINITIONS_10_1_H\n#define _SCSCHEMADEFINITIONS_10_1_H\n\n");
- printf("#ifndef SCSTR\n");
- printf("#include <CoreFoundation/CFString.h>\n");
- printf("#define SCSTR(s) CFSTR(s)\n");
- printf("#endif\n");
+ printf("#warning USE OF THIS HEADER HAS BEEN DEPRECATED\n");
+
+ printf("#ifndef _SCSCHEMADEFINITIONS_H\n");
+ printf("#warning Please #include <SystemConfiguration/SystemConfiguration.h> instead\n");
+ printf("#warning of including this file directly.\n");
+ printf("#include <SystemConfiguration/SCSchemaDefinitions.h>\n");
+ printf("#endif\n\n");
+
+// printf("#ifndef SCSTR\n");
+// printf("#include <CoreFoundation/CFString.h>\n");
+// printf("#define SCSTR(s) CFSTR(s)\n");
+// printf("#endif\n\n");
+//
+// dump_names(gen_header_e);
+// printf("\n");
- printf("\n");
- dump_names(gen_header_e);
printf("#endif /* _SCSCHEMADEFINITIONS_10_1_H */\n");
}
else if (strcmp(type, "header") == 0) {
printf("/*\n * This file is automatically generated\n * DO NOT EDIT!\n */\n\n");
printf("/*\n");
- printf(" * Note: For Cocoa/Obj-C/Foundation programs accessing these preference\n");
- printf(" * keys you may want to consider the following:\n");
+ dump_names(gen_comments_e);
+ printf(" */\n\n\n");
+
+ printf("/*\n");
+ printf(" * Note: The MACOSX_DEPLOYMENT_TARGET environment variable should be used\n");
+ printf(" * when building an application targeted for an earlier version of\n");
+ printf(" * Mac OS X. Please reference Technical Note TN2064 for more details.\n");
+ printf(" */\n\n");
+
+ printf("/*\n");
+ printf(" * Note: For Cocoa/Obj-C/Foundation applications accessing these preference\n");
+ printf(" * keys you may want to consider the following :\n");
printf(" *\n");
- printf(" * #define " SC_SCHEMA_DECLARATION "(x)\t\textern NSString * x\n");
+ printf(" * #define " SC_SCHEMA_DECLARATION "(k,q)\textern NSString * k\n");
printf(" * #import <SystemConfiguration/SystemConfiguration.h>\n");
printf(" */\n\n");
+ printf("/*\n");
+ printf(" * Note: For CFM applications using these schema keys you may want to\n");
+ printf(" * consider the following :\n");
+ printf(" *\n");
+ printf(" * #define SC_SCHEMA_KV(k,v,t)\tlookup_SC_key( CFSTR( #k ) )\n");
+ printf(" * #define SC_SCHEMA_DECLARATION(k,q)\n");
+ printf(" * #include <SystemConfiguration/SystemConfiguration.h>\n");
+ printf(" *\n");
+ printf(" * CFStringRef lookup_SC_key(CFStringRef key)\n");
+ printf(" * {\n");
+ printf(" * // this function should [dynamically, on-demand] load the\n");
+ printf(" * // SystemConfiguration.framework, look up the provided key,\n");
+ printf(" * // and return the associated value.\n");
+ printf(" * }\n");
+ printf(" */\n\n");
+
+ printf("/*\n");
+ printf(" * Note: Earlier versions of this header file defined a \"SCSTR\" macro\n");
+ printf(" * which helped to facilitate Obj-C development. Use of this macro\n");
+ printf(" * has been deprecated (in Mac OS X 10.4) in favor of the newer\n");
+ printf(" * \"SC_SCHEMA_KV\" and \"SC_SCHEMA_DECLARATION\" macros\n");
+ printf(" */\n\n\n");
+
printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n");
- printf("#ifndef SC_SCHEMA_DECLARATION\n");
- printf("#ifndef SCSTR\n");
- printf("#include <CoreFoundation/CFString.h>\n");
- printf("#define " SC_SCHEMA_DECLARATION "(x)\textern const CFStringRef x\n");
- printf("#else\n");
- printf("#import <Foundation/NSString.h>\n");
- printf("#define " SC_SCHEMA_DECLARATION "(x)\textern NSString * x\n");
- printf("#endif\n");
- printf("#endif\n");
+ printf("/* -------------------- Macro declarations -------------------- */\n\n");
- printf("\n");
- dump_names(gen_hfile_e);
+ printf("#include <AvailabilityMacros.h>\n\n");
+
+ printf("/*\n");
+ printf(" * let's \"do the right thing\" for those wishing to build for\n");
+ printf(" * Mac OS X 10.1 and 10.2\n");
+ printf(" */\n");
- printf("#include <AvailabilityMacros.h>\n");
printf("#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED\n");
printf(" #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
- printf(" #include <SystemConfiguration/SCSchemaDefinitions_10_1.h>\n");
+ printf(" #ifndef SCSTR\n");
+ printf(" #include <CoreFoundation/CFString.h>\n");
+ printf(" #define SCSTR(s) CFSTR(s)\n");
+ printf(" #endif\n");
+ printf(" #ifndef SC_SCHEMA_KV\n");
+ printf(" #define SC_SCHEMA_KV(k,v,t)\tSCSTR( v )\n");
+ printf(" #endif\n");
+ printf(" #ifndef SC_SCHEMA_DECLARATION\n");
+ printf(" #define SC_SCHEMA_DECLARATION(k,q)\n");
+ printf(" #endif\n");
printf(" #endif\n");
printf("#endif\n\n");
+ printf("/*\n");
+ printf(" * Define a schema key/value/type tuple\n");
+ printf(" */\n");
+ printf("#ifndef SC_SCHEMA_KV\n");
+ printf(" #define " SC_SCHEMA_KV "(k,v,t)\tk\n");
+ printf("#endif\n\n");
+
+ printf("/*\n");
+ printf(" * Provide an \"extern\" for the key/value\n");
+ printf(" */\n");
+ printf("#ifndef SC_SCHEMA_DECLARATION\n");
+ printf(" #ifndef SCSTR\n");
+ printf(" #include <CoreFoundation/CFString.h>\n");
+ printf(" #define " SC_SCHEMA_DECLARATION "(k,q)\textern const CFStringRef k q\n");
+ printf(" #else\n");
+ printf(" #import <Foundation/NSString.h>\n");
+ printf(" #define " SC_SCHEMA_DECLARATION "(k,q)\textern NSString * k q\n");
+ printf(" #endif\n");
+ printf("#endif\n");
+
+ // The SCSTR() macro should be availble for 10.1 ... 10.4
+ printf("#if MAC_OS_X_VERSION_10_4 >= MAC_OS_X_VERSION_MIN_REQUIRED\n");
+ printf(" #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
+ printf(" #ifndef SCSTR\n");
+ printf(" #include <CoreFoundation/CFString.h>\n");
+ printf(" #define SCSTR(s) CFSTR(s)\n");
+ printf(" #endif\n");
+ printf(" #endif\n");
+ printf("#endif\n\n\n");
+
+ printf("/* -------------------- HeaderDoc comments -------------------- */\n\n\n");
+ printf("#if\t0\n");
+ printf("/*!\n");
+ printf(" *\t@header SCSchemaDefinitions\n");
+ printf(" */\n");
+ dump_names(gen_headerdoc_e);
+ printf("\n");
+ printf("#endif\t/* 0 */\n\n\n");
+
+ printf("/* -------------------- Schema declarations -------------------- */\n\n");
+ dump_names(gen_hfile_e);
+ printf("\n");
+
printf("#endif /* _SCSCHEMADEFINITIONS_H */\n");
}
else if (strcmp(type, "cfile") == 0) {
+++ /dev/null
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
+++ /dev/null
-$$ Lines starting with $$ are not inserted into newly created files
-$$ The following substitutions are made:
-$$
-$$ $FILENAME$ e.g. foo.m
-$$ $FILENAMESANSEXTENSION$ e.g. foo
-$$ $DIRECTORY$ e.g. /tmp/MyNewApp
-$$ $PROJECTNAME$ e.g. MyNewApp
-$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj
-$$ $USERNAME$ e.g. mwagner
-$$ $DATE$ e.g. Jan-1-1994
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import "$FILENAMESANSEXTENSION$.h"
-
-@implementation $FILENAMESANSEXTENSION$
-
-@end
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * Nov 7, 2002 Allan Nathanson <ajn@apple.com>
- * - use ServiceID *or* LinkID
- *
- * Oct 25, 2002 Christophe Allie <callie@apple.com>
- * - use ServiceID instead of LinkID
- *
- * Feb 28, 2002 Christophe Allie <callie@apple.com>
- * - socket API fixes
- *
- * Feb 10, 2001 Allan Nathanson <ajn@apple.com>
- * - cleanup API
- *
- * Feb 2000 Christophe Allie <callie@apple.com>
- * - initial revision
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-
-#include <ppp/ppp_msg.h>
-#include "ppp.h"
-
-
-static int
-readn(int ref, void *data, int len)
-{
- int left = len;
- int n;
- void *p = data;
-
- while (left > 0) {
- if ((n = read(ref, p, left)) < 0) {
- if (errno != EINTR) {
- return -1;
- }
- n = 0;
- } else if (n == 0) {
- break; /* EOF */
- }
-
- left -= n;
- p += n;
- }
- return (len - left);
-}
-
-
-static int
-writen(int ref, void *data, int len)
-{
- int left = len;
- int n;
- void *p = data;
-
- while (left > 0) {
- if ((n = write(ref, p, left)) <= 0) {
- if (errno != EINTR) {
- return -1;
- }
- n = 0;
- }
- left -= n;
- p += n;
- }
- return len;
-}
-
-
-__private_extern__
-int
-PPPInit(int *ref)
-{
- int sock;
- int status;
- struct sockaddr_un sun;
-
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
-
- bzero(&sun, sizeof(sun));
- sun.sun_family = AF_LOCAL;
- strncpy(sun.sun_path, PPP_PATH, sizeof(sun.sun_path));
-
- status = connect(sock, (struct sockaddr *)&sun, sizeof(sun));
- if (status < 0) {
- return errno;
- }
-
- *ref = sock;
- return 0;
-}
-
-
-__private_extern__
-int
-PPPDispose(int ref)
-{
- if (close(ref) < 0) {
- return errno;
- }
- return 0;
-}
-
-
-static int
-PPPExec(int ref,
- CFStringRef serviceID,
- uint32_t link,
- uint32_t cmd,
- u_int16_t flags,
- void *request,
- uint32_t requestLen,
- void **reply,
- uint32_t *replyLen)
-{
- struct ppp_msg_hdr msg;
- char *buf = NULL;
- ssize_t n;
- CFDataRef sID = NULL;
-
- bzero(&msg, sizeof(msg));
-
- // first send request, if necessary
- if (cmd) {
- msg.m_type = cmd;
- msg.m_flags = flags;
- if (serviceID) {
- sID = CFStringCreateExternalRepresentation(NULL,
- serviceID,
- kCFStringEncodingUTF8,
- 0);
- // serviceID is present, use it
- msg.m_flags |= USE_SERVICEID;
- msg.m_link = CFDataGetLength(sID);
- } else {
- // no service ID, use the requested link
- msg.m_link = link;
- }
- msg.m_len = ((request != NULL) && (requestLen > 0)) ? requestLen : 0;
-
- // send the command
- if (writen(ref, &msg, sizeof(msg)) < 0) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
- if (sID) CFRelease(sID);
- return errno;
- }
-
- if (sID) {
- if (writen(ref, (void *)CFDataGetBytePtr(sID), msg.m_link) < 0) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
- CFRelease(sID);
- return errno;
- }
- CFRelease(sID);
- }
-
- if ((request != NULL) && (requestLen > 0)) {
- if (writen(ref, request, requestLen) < 0) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
- return errno;
- }
- }
- }
-
- // then read replies or incoming message
- n = readn(ref, &msg, sizeof(msg));
- if (n == -1) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
- return errno;
- } else if (n != sizeof(msg)) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n);
- return -1;
- }
-
- if ((msg.m_flags & USE_SERVICEID) && msg.m_link) {
- buf = CFAllocatorAllocate(NULL, msg.m_link, 0);
- if (buf) {
- // read reply
- n = readn(ref, buf, msg.m_link);
- if (n == -1) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
- CFAllocatorDeallocate(NULL, buf);
- return errno;
- } else if (n != (ssize_t)msg.m_link) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
- CFAllocatorDeallocate(NULL, buf);
- return -1;
- }
- // buf contains the service id we passed in the request
- CFAllocatorDeallocate(NULL, buf);
- buf = NULL;
- }
- }
-
- if (msg.m_len) {
- buf = CFAllocatorAllocate(NULL, msg.m_len, 0);
- if (buf) {
- // read reply
- n = readn(ref, buf, msg.m_len);
- if (n == -1) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
- CFAllocatorDeallocate(NULL, buf);
- return errno;
- } else if (n != (ssize_t)msg.m_len) {
- SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n);
- CFAllocatorDeallocate(NULL, buf);
- return -1;
- }
- }
- }
-
- if (reply && replyLen) {
- *reply = buf;
- *replyLen = msg.m_len;
- } else if (buf) {
- // if additional returned data is unwanted
- CFAllocatorDeallocate(NULL, buf);
- }
-
- return msg.m_result;
-}
-
-
-__private_extern__
-int
-PPPGetLinkByInterface(int ref, char *if_name, uint32_t *link)
-{
- void *replyBuf = NULL;
- uint32_t replyBufLen = 0;
- int status;
-
- status = PPPExec(ref,
- NULL,
- -1,
- PPP_GETLINKBYIFNAME,
- 0,
- (void *)if_name,
- strlen(if_name),
- &replyBuf,
- &replyBufLen);
- if (status != 0) {
- return status;
- }
-
- if (replyBuf && (replyBufLen == sizeof(uint32_t))) {
- *link = *(uint32_t *)replyBuf;
- } else {
- status = -2; /* if not found */
- }
- if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
-
- return status;
-}
-
-
-__private_extern__
-int
-PPPConnect(int ref, CFStringRef serviceID, uint32_t link, void *data, uint32_t dataLen, int linger)
-{
- int status;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_CONNECT,
- CONNECT_ARBITRATED_FLAG + (linger ? 0 : CONNECT_AUTOCLOSE_FLAG),
- data,
- dataLen,
- NULL,
- NULL);
- return status;
-}
-
-
-__private_extern__
-int
-PPPDisconnect(int ref, CFStringRef serviceID, uint32_t link, int force)
-{
- int status;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_DISCONNECT,
- force ? 0 : DISCONNECT_ARBITRATED_FLAG,
- NULL,
- 0,
- NULL,
- NULL);
- return status;
-}
-
-
-__private_extern__
-int
-PPPSuspend(int ref, CFStringRef serviceID, uint32_t link)
-{
- int status;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_SUSPEND,
- 0,
- NULL,
- 0,
- NULL,
- NULL);
- return status;
-}
-
-
-__private_extern__
-int
-PPPResume(int ref, CFStringRef serviceID, uint32_t link)
-{
- int status;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_RESUME,
- 0,
- NULL,
- 0,
- NULL,
- NULL);
- return status;
-}
-
-
-__private_extern__
-int
-PPPGetOption(int ref, CFStringRef serviceID, uint32_t link, uint32_t option, void **data, uint32_t *dataLen)
-{
- struct ppp_opt_hdr opt;
- void *replyBuf = NULL;
- uint32_t replyBufLen = 0;
- int status;
-
- *dataLen = 0;
- *data = NULL;
-
- bzero(&opt, sizeof(opt));
- opt.o_type = option;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_GETOPTION,
- 0,
- (void *)&opt,
- sizeof(opt),
- &replyBuf,
- &replyBufLen);
- if (status != 0) {
- return status;
- }
-
- if (replyBuf && (replyBufLen > sizeof(struct ppp_opt_hdr))) {
- *dataLen = replyBufLen - sizeof(struct ppp_opt_hdr);
- *data = CFAllocatorAllocate(NULL, *dataLen, 0);
- bcopy(((struct ppp_opt *)replyBuf)->o_data, *data, *dataLen);
- }
- if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
-
- return status;
-}
-
-
-__private_extern__
-int
-PPPSetOption(int ref, CFStringRef serviceID, uint32_t link, uint32_t option, void *data, uint32_t dataLen)
-{
- void *buf;
- uint32_t bufLen;
- int status;
-
- bufLen = sizeof(struct ppp_opt_hdr) + dataLen;
- buf = CFAllocatorAllocate(NULL, bufLen, 0);
-
- bzero((struct ppp_opt_hdr *)buf, sizeof(struct ppp_opt_hdr));
- ((struct ppp_opt_hdr *)buf)->o_type = option;
- bcopy(data, ((struct ppp_opt *)buf)->o_data, dataLen);
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_SETOPTION,
- 0,
- buf,
- bufLen,
- NULL,
- NULL);
-
- CFAllocatorDeallocate(NULL, buf);
- return status;
-}
-
-
-__private_extern__
-int
-PPPGetConnectData(int ref, CFStringRef serviceID, uint32_t link, void **data, uint32_t *dataLen)
-{
- int status;
-
- *dataLen = 0;
- *data = NULL;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_GETCONNECTDATA,
- 0,
- NULL,
- 0,
- data,
- dataLen);
- return status;
-}
-
-
-__private_extern__
-int
-PPPStatus(int ref, CFStringRef serviceID, uint32_t link, struct ppp_status **stat)
-{
- void *replyBuf = NULL;
- uint32_t replyBufLen = 0;
- int status;
-
- *stat = NULL;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_STATUS,
- 0,
- NULL,
- 0,
- &replyBuf,
- &replyBufLen);
- if (status != 0) {
- return status;
- }
-
- if (replyBuf && (replyBufLen == sizeof(struct ppp_status))) {
- *stat = (struct ppp_status *)replyBuf;
- } else {
- if (replyBuf) CFAllocatorDeallocate(NULL, replyBuf);
- status = -1;
- }
-
- return status;
-}
-
-
-__private_extern__
-int
-PPPExtendedStatus(int ref, CFStringRef serviceID, uint32_t link, void **data, uint32_t *dataLen)
-{
- int status;
-
- *dataLen = 0;
- *data = NULL;
-
- status = PPPExec(ref,
- serviceID,
- link,
- PPP_EXTENDEDSTATUS,
- 0,
- NULL,
- 0,
- data,
- dataLen);
- return status;
-}
-
-
-__private_extern__
-int
-PPPEnableEvents(int ref, CFStringRef serviceID, uint32_t link, u_char enable)
-{
- int status;
- uint32_t lval = 2; // status notifications
-
- status = PPPExec(ref,
- serviceID,
- link,
- enable ? PPP_ENABLE_EVENT : PPP_DISABLE_EVENT,
- 0,
- &lval,
- sizeof(lval),
- NULL,
- NULL);
- return status;
-}
-
-
-__private_extern__
-int
-PPPReadEvent(int ref, uint32_t *event)
-{
-
- *event = PPPExec(ref, NULL, 0, 0, 0, NULL, 0, NULL, NULL);
- return 0;
-}
-
-
-__private_extern__
-CFDataRef
-PPPSerialize(CFPropertyListRef obj, void **data, uint32_t *dataLen)
-{
- CFDataRef xml;
-
- xml = CFPropertyListCreateXMLData(NULL, obj);
- if (xml) {
- *data = (void*)CFDataGetBytePtr(xml);
- *dataLen = CFDataGetLength(xml);
- }
- return xml;
-}
-
-
-__private_extern__
-CFPropertyListRef
-PPPUnserialize(void *data, uint32_t dataLen)
-{
- CFDataRef xml;
- CFStringRef xmlError;
- CFPropertyListRef ref = NULL;
-
- xml = CFDataCreateWithBytesNoCopy(NULL, data, dataLen, kCFAllocatorNull);
- if (xml) {
- ref = CFPropertyListCreateFromXMLData(NULL,
- xml,
- kCFPropertyListImmutable,
- &xmlError);
- if (!ref) {
- if (xmlError) {
- SCLog(TRUE,
- LOG_ERR,
- CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
- xmlError);
- CFRelease(xmlError);
- }
- }
-
- CFRelease(xml);
- }
-
- return ref;
-}
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * Nov 7, 2002 Allan Nathanson <ajn@apple.com>
- * - use ServiceID *or* LinkID
- *
- * Feb 10, 2001 Allan Nathanson <ajn@apple.com>
- * - cleanup API
- *
- * Feb 2000 Christophe Allie <callie@apple.com>
- * - initial revision (as ppplib.h)
- */
-
-#ifndef _PPP_H
-#define _PPP_H
-
-#include <sys/cdefs.h>
-#include <ppp/ppp_msg.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-__BEGIN_DECLS
-
-int PPPInit (int *ref);
-
-int PPPDispose (int ref);
-
-int PPPGetLinkByInterface (int ref,
- char *if_name,
- uint32_t *link);
-
-int PPPConnect (int ref,
- CFStringRef serviceid,
- uint32_t link,
- void *data,
- uint32_t dataLen,
- int linger);
-
-int PPPDisconnect (int ref,
- CFStringRef serviceid,
- uint32_t link,
- int force);
-
-int PPPSuspend (int ref,
- CFStringRef serviceID,
- uint32_t link);
-
-int PPPResume (int ref,
- CFStringRef serviceID,
- uint32_t link);
-
-int PPPGetOption (int ref,
- CFStringRef serviceid,
- uint32_t link,
- uint32_t option,
- void **data,
- uint32_t *dataLen);
-
-int PPPSetOption (int ref,
- CFStringRef serviceid,
- uint32_t link,
- uint32_t option,
- void *data,
- uint32_t dataLen);
-
-int PPPGetConnectData (int ref,
- CFStringRef serviceID,
- uint32_t link,
- void **data,
- uint32_t *dataLen);
-
-int PPPStatus (int ref,
- CFStringRef serviceid,
- uint32_t link,
- struct ppp_status **stat);
-
-int PPPExtendedStatus (int ref,
- CFStringRef serviceid,
- uint32_t link,
- void **data,
- uint32_t *dataLen);
-
-int PPPEnableEvents (int ref,
- CFStringRef serviceid,
- uint32_t link,
- u_char enable);
-
-int PPPReadEvent (int ref,
- uint32_t *event);
-
-CFDataRef PPPSerialize (CFPropertyListRef obj,
- void **data,
- uint32_t *dataLen);
-
-CFPropertyListRef PPPUnserialize (void *data,
- uint32_t dataLen);
-
-__END_DECLS
-
-#endif /* _PPP_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+
+#import <ppp/pppcontroller.defs>
+++ /dev/null
-#
-# 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 = configd
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-HFILES = configd.h _SCD.h configd_server.h notify_server.h\
- plugin_support.h session.h pattern.h notify.h
-
-MFILES = configd.m
-
-CFILES = _SCD.c configd_server.c notify_server.c plugin_support.c\
- session.c pattern.c notify.c _configopen.c _configclose.c\
- _configlock.c _configunlock.c _configlist.c _configadd.c\
- _configadd_s.c _configget.c _configset.c _configremove.c\
- _configtouch.c _confignotify.c _notifyadd.c _notifyremove.c\
- _notifychanges.c _notifyviaport.c _notifyviafd.c\
- _notifyviasignal.c _notifycancel.c _snapshot.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
- h.template config.defs configd.plist
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = -lobjc
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-NEXTSTEP_PB_LDFLAGS = -prebind_all_twolevel_modules
-FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration
-
-
-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 $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
+++ /dev/null
-###############################################################################
-# Makefile.postamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile, which is imported after all other makefiles, to
-# override attributes for a project's Makefile environment. This allows you
-# to take advantage of the environment set up by the other Makefiles.
-# You can also define custom rules at the end of this file.
-#
-###############################################################################
-#
-# These variables are exported by the standard makefiles and can be
-# used in any customizations you make. They are *outputs* of
-# the Makefiles and should be used, not set.
-#
-# PRODUCTS: products to install. All of these products will be placed in
-# the directory $(DSTROOT)$(INSTALLDIR)
-# GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-# OFILE_DIR: Directory into which .o object files are generated.
-# DERIVED_SRC_DIR: Directory used for all other derived files
-#
-# ALL_CFLAGS: flags to pass when compiling .c files
-# ALL_MFLAGS: flags to pass when compiling .m files
-# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files
-# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files
-# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files
-# ALL_LDFLAGS: flags to pass when linking object files
-# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files
-# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files
-# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files
-# ALL_YFLAGS: flags to pass when processing .y (yacc) files
-# ALL_LFLAGS: flags to pass when processing .l (lex) files
-#
-# NAME: name of application, bundle, subproject, palette, etc.
-# LANGUAGES: langages in which the project is written (default "English")
-# English_RESOURCES: localized resources (e.g. nib's, images) of project
-# GLOBAL_RESOURCES: non-localized resources of project
-#
-# SRCROOT: base directory in which to place the new source files
-# SRCPATH: relative path from SRCROOT to present subdirectory
-#
-# INSTALLDIR: Directory the product will be installed into by 'install' target
-# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-#
-# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost)
-# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults
-# to -g)
-# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG)
-# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults
-# to -O)
-# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults
-# to -pg -DPROFILE)
-# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to
-# the include path (defaults to -I.)
-# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-# passed to ld/libtool (defaults to nothing)
-WARNING_CFLAGS=-Wall
-
-
-# Library and Framework projects only:
-# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked
-# against the framework will run against the correct version even if
-# the current version of the framework changes. You may override this
-# to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-# development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
- # User/group ownership
-#INSTALL_AS_GROUP = wheel
- # (probably want to set both of these)
-#INSTALL_PERMISSIONS =
- # If set, 'install' chmod's executable to this
-
-
-# Options to strip. Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here. Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where
-# derived files should go.
-#
-MACH_INIT_DIR = /private/etc/mach_init.d
-install_extra:
- $(MKDIRS) $(DSTROOT)$(MACH_INIT_DIR)
- install -c -m 644 configd.plist $(DSTROOT)$(MACH_INIT_DIR)/configd.plist
-
+++ /dev/null
-###############################################################################
-# Makefile.preamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile for configuring the standard application makefiles
-# associated with ProjectBuilder. It is included before the main makefile.
-# In Makefile.preamble you set attributes for a project, so they are available
-# to the project's makefiles. In contrast, you typically write additional rules or
-# override built-in behavior in the Makefile.postamble.
-#
-# Each directory in a project tree (main project plus subprojects) should
-# have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-# MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults: The OTHER_* variables will be
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible. To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler
-# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-# .cc, .cxx, .C, and .M files. There is no need to respecify the
-# flags in OTHER_MFLAGS, etc.
-# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files
-# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files
-# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files
-# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when
-# precompiling header files
-# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool
-# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap
-# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen
-# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc
-# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every
-# stage of the make:
-#
-# BEFORE_PREBUILD: targets to build before installing headers for a subproject
-# AFTER_PREBUILD: targets to build after installing headers for a subproject
-# BEFORE_BUILD_RECURSION: targets to make before building subprojects
-# BEFORE_BUILD: targets to make before a build, but after subprojects
-# AFTER_BUILD: targets to make after a build
-#
-# BEFORE_INSTALL: targets to build before installing the product
-# AFTER_INSTALL: targets to build after installing the product
-# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-# AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-# BEFORE_INSTALLHDRS: targets to build before installing headers for a
-# subproject
-# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-# BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-# AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-# BEFORE_DEPEND: targets to build before building dependencies for a
-# subproject
-# AFTER_DEPEND: targets to build after building dependencies for a
-# subproject
-#
-# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-# updated every time the project is built. If NO, the dependency
-# file is only built when the depend target is invoked.
-
-# Framework-related variables:
-# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the framework's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-# PUBLIC_HEADER_DIR: Determines where public exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically. For library projects you should
-# set this to something like /Developer/Headers/$(NAME). Do not set
-# this variable for framework projects unless you do not want the
-# header files included in the framework.
-# PRIVATE_HEADER_DIR: Determines where private exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically.
-# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines
-# whether the libraries produced are statically linked when they
-# are used or if they are dynamically loadable. This defaults to
-# DYNAMIC.
-# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the library's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-#
-# INSTALL_AS_USER: owner of the intalled products (default root)
-# INSTALL_AS_GROUP: group of the installed products (default wheel)
-# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-# passed on the command line to recursive invocations of make. Note that
-# the values in OTHER_*FLAGS are inherited by subprojects automatically --
-# you do not have to (and shouldn't) add OTHER_*FLAGS to
-# OTHER_RECURSIVE_VARIABLES.
-
-# Additional headers to export beyond those in the PB.project:
-# OTHER_PUBLIC_HEADERS
-# OTHER_PROJECT_HEADERS
-# OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-# OTHER_RESOURCES: (non-localized) resources for this project
-# OTHER_OFILES: relocatables to be linked into this project
-# OTHER_LIBS: more libraries to link against
-# OTHER_PRODUCT_DEPENDS: other dependencies of this project
-# OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-# OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-# BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed. By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object). Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
-AFTER_INSTALL = install_extra
-
-# Additional flags (for MiG generated files)
-ALL_MIGFLAGS = -F$(SYMROOT)
-OTHER_OFILES = configServer.o
-
+++ /dev/null
-{
- "DYNAMIC_CODE_GEN" = YES;
- FILESTABLE = {
- FRAMEWORKS = ("CoreFoundation.framework", "SystemConfiguration.framework");
- FRAMEWORKSEARCH = ();
- HEADERSEARCH = ();
- "H_FILES" = (
- "configd.h",
- "_SCD.h",
- "configd_server.h",
- "notify_server.h",
- "plugin_support.h",
- "session.h",
- "pattern.h",
- "notify.h"
- );
- "OTHER_LIBS" = (objc);
- "OTHER_LINKED" = (
- "configd.m",
- "_SCD.c",
- "configd_server.c",
- "notify_server.c",
- "plugin_support.c",
- "session.c",
- "pattern.c",
- "notify.c",
- "_configopen.c",
- "_configclose.c",
- "_configlock.c",
- "_configunlock.c",
- "_configlist.c",
- "_configadd.c",
- "_configadd_s.c",
- "_configget.c",
- "_configset.c",
- "_configremove.c",
- "_configtouch.c",
- "_confignotify.c",
- "_notifyadd.c",
- "_notifyremove.c",
- "_notifychanges.c",
- "_notifyviaport.c",
- "_notifyviafd.c",
- "_notifyviasignal.c",
- "_notifycancel.c",
- "_snapshot.c"
- );
- "OTHER_SOURCES" = (
- "Makefile.preamble",
- Makefile,
- "Makefile.postamble",
- "m.template",
- "h.template",
- "config.defs",
- "configd.plist"
- );
- "PRECOMPILED_HEADERS" = ();
- "PROJECT_HEADERS" = ();
- "PUBLIC_HEADERS" = ();
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
- "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake";
- "NEXTSTEP_INSTALLDIR" = "/usr/sbin";
- "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac";
- "NEXTSTEP_LINKEROPTIONS" = "-prebind_all_twolevel_modules";
- "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc";
- "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make";
- "PDO_UNIX_INSTALLDIR" = "/bin";
- "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac";
- "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = configd;
- PROJECTTYPE = Tool;
- PROJECTVERSION = "2.8";
- "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make";
- "WINDOWS_INSTALLDIR" = "/Library/Executables";
- "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe";
- "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc";
-}
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*/
+#include <unistd.h>
+
#include "configd.h"
+#include "configd_server.h"
+#include "session.h"
__private_extern__ CFMutableDictionaryRef sessionData = NULL;
i = CFArrayGetFirstIndexOfValue(newWatchers,
CFRangeMake(0, CFArrayGetCount(newWatchers)),
sessionNum);
- if (i == -1) {
+ if (i == kCFNotFound) {
/* if this is the first instance of this session watching this key */
CFArrayAppendValue(newWatchers, sessionNum);
refCnt = 1;
CFDictionarySetValue(storeData, watchedKey, newDict);
CFRelease(newDict);
+#ifdef DEBUG
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey);
+#endif /* DEBUG */
return;
}
dict = CFDictionaryGetValue(storeData, watchedKey);
if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) {
/* key doesn't exist (isn't this really fatal?) */
+#ifdef DEBUG
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey);
+#endif /* DEBUG */
return;
}
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
i = CFArrayGetFirstIndexOfValue(newWatchers,
CFRangeMake(0, CFArrayGetCount(newWatchers)),
sessionNum);
- if (i == -1) {
+ if (i == kCFNotFound) {
+#ifdef DEBUG
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, session not watching"), sessionNum, watchedKey);
+#endif /* DEBUG */
CFRelease(newDict);
CFRelease(newWatchers);
CFRelease(newWatcherRefs);
}
CFRelease(newDict);
+#ifdef DEBUG
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@"), sessionNum, watchedKey);
+#endif /* DEBUG */
+
+ return;
+}
+
+
+__private_extern__
+void
+pushNotifications()
+{
+ const void **sessionsToNotify;
+ CFIndex notifyCnt;
+ int server;
+ serverSessionRef theSession;
+ SCDynamicStorePrivateRef storePrivate;
+
+ if (needsNotification == NULL)
+ return; /* if no sessions need to be kicked */
+
+ notifyCnt = CFSetGetCount(needsNotification);
+ sessionsToNotify = malloc(notifyCnt * sizeof(CFNumberRef));
+ CFSetGetValues(needsNotification, sessionsToNotify);
+ while (--notifyCnt >= 0) {
+ (void) CFNumberGetValue(sessionsToNotify[notifyCnt],
+ kCFNumberIntType,
+ &server);
+ theSession = getSession(server);
+ storePrivate = (SCDynamicStorePrivateRef)theSession->store;
+
+ /*
+ * deliver notifications to client sessions
+ */
+ if ((storePrivate->notifyStatus == Using_NotifierInformViaMachPort) &&
+ (storePrivate->notifyPort != MACH_PORT_NULL)) {
+ mach_msg_empty_send_t msg;
+ mach_msg_option_t options;
+ kern_return_t status;
+ /*
+ * Post notification as mach message
+ */
+#ifdef DEBUG
+ if (_configd_verbose) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("sending mach message notification."));
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" port = %d"), storePrivate->notifyPort);
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyPortIdentifier);
+ }
+#endif /* DEBUG */
+ msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
+ msg.header.msgh_size = sizeof(msg);
+ msg.header.msgh_remote_port = storePrivate->notifyPort;
+ msg.header.msgh_local_port = MACH_PORT_NULL;
+ msg.header.msgh_id = storePrivate->notifyPortIdentifier;
+ options = MACH_SEND_TIMEOUT;
+ status = mach_msg(&msg.header, /* msg */
+ MACH_SEND_MSG|options, /* options */
+ msg.header.msgh_size, /* send_size */
+ 0, /* rcv_size */
+ MACH_PORT_NULL, /* rcv_name */
+ 0, /* timeout */
+ MACH_PORT_NULL); /* notify */
+ if (status == MACH_SEND_TIMED_OUT) {
+ mach_msg_destroy(&msg.header);
+ }
+ }
+
+ if ((storePrivate->notifyStatus == Using_NotifierInformViaFD) &&
+ (storePrivate->notifyFile >= 0)) {
+ ssize_t written;
+
+#ifdef DEBUG
+ if (_configd_verbose) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification"));
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" fd = %d"), storePrivate->notifyFile);
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyFileIdentifier);
+ }
+#endif /* DEBUG */
+
+ written = write(storePrivate->notifyFile,
+ &storePrivate->notifyFileIdentifier,
+ sizeof(storePrivate->notifyFileIdentifier));
+ if (written == -1) {
+ if (errno == EWOULDBLOCK) {
+#ifdef DEBUG
+ SCLog(_configd_verbose, LOG_DEBUG,
+ CFSTR("sorry, only one outstanding notification per session."));
+#endif /* DEBUG */
+ } else {
+#ifdef DEBUG
+ SCLog(_configd_verbose, LOG_DEBUG,
+ CFSTR("could not send notification, write() failed: %s"),
+ strerror(errno));
+#endif /* DEBUG */
+ storePrivate->notifyFile = -1;
+ }
+ } else if (written != sizeof(storePrivate->notifyFileIdentifier)) {
+#ifdef DEBUG
+ SCLog(_configd_verbose, LOG_DEBUG,
+ CFSTR("could not send notification, incomplete write()"));
+#endif /* DEBUG */
+ storePrivate->notifyFile = -1;
+ }
+ }
+
+ if ((storePrivate->notifyStatus == Using_NotifierInformViaSignal) &&
+ (storePrivate->notifySignal > 0)) {
+ kern_return_t status;
+ pid_t pid;
+ /*
+ * Post notification as signal
+ */
+ status = pid_for_task(storePrivate->notifySignalTask, &pid);
+ if (status == KERN_SUCCESS) {
+#ifdef DEBUG
+ if (_configd_verbose) {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("sending signal notification"));
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" pid = %d"), pid);
+ SCLog(TRUE, LOG_DEBUG, CFSTR(" signal = %d"), storePrivate->notifySignal);
+ }
+#endif /* DEBUG */
+ if (kill(pid, storePrivate->notifySignal) != 0) {
+#ifdef DEBUG
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno));
+#endif /* DEBUG */
+ status = KERN_FAILURE;
+ }
+ } else {
+ mach_port_type_t pt;
+
+ if ((mach_port_type(mach_task_self(), storePrivate->notifySignalTask, &pt) == KERN_SUCCESS) &&
+ (pt & MACH_PORT_TYPE_DEAD_NAME)) {
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal, process died"));
+ } else {
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status));
+ }
+ }
+
+ if (status != KERN_SUCCESS) {
+ /* don't bother with any more attempts */
+ (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask);
+ storePrivate->notifySignal = 0;
+ storePrivate->notifySignalTask = TASK_NULL;
+ }
+ }
+ }
+ free(sessionsToNotify);
+
+ /*
+ * this list of notifications have been posted, wait for some more.
+ */
+ CFRelease(needsNotification);
+ needsNotification = NULL;
return;
}
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* June 1, 2001 Allan Nathanson <ajn@apple.com>
* - public API conversion
*
- * June 2, 2000 Allan Nathanson <ajn@apple.com>
+ * June 2, 2000 Allan Nathanson <ajn@apple.com>
* - initial revision
*/
int
__SCDynamicStoreAddValue (SCDynamicStoreRef store,
CFStringRef key,
- CFDataRef value);
-
-int
-__SCDynamicStoreAddTemporaryValue (SCDynamicStoreRef store,
- CFStringRef key,
- CFDataRef value);
+ CFDataRef value,
+ Boolean internal);
int
__SCDynamicStoreCopyValue (SCDynamicStoreRef store,
_removeWatcher (CFNumberRef sessionNum,
CFStringRef watchedKey);
+void
+pushNotifications ();
+
__END_DECLS
#endif /* !_S_SCD_H */
__private_extern__
int
-__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value)
+__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value, Boolean internal)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
CFDataRef tempValue;
- if (_configd_verbose) {
- CFPropertyListRef val;
-
- (void) _SCUnserialize(&val, value, NULL, NULL);
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val);
- CFRelease(val);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
if (_configd_trace) {
- SCTrace(TRUE, _configd_trace, CFSTR("add : %5d : %@\n"), storePrivate->server, key);
+ SCTrace(TRUE, _configd_trace,
+ CFSTR("%s%s : %5d : %@\n"),
+ internal ? "*add " : "add ",
+ storePrivate->useSessionKeys ? "t " : " ",
+ storePrivate->server,
+ key);
}
/*
goto done;
default :
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
+#ifdef DEBUG
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreAddValue __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
+#endif /* DEBUG */
goto done;
}
/*
* 4. Release our lock.
*/
+
done:
+
__SCDynamicStoreUnlock(store, TRUE);
return sc_status;
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
- CFDataRef data; /* data (un-serialized) */
+ CFStringRef key = NULL; /* key (un-serialized) */
+ CFDataRef data = NULL; /* data (un-serialized) */
+ serverSessionRef mySession = getSession(server);
+
+ /* un-serialize the key */
+ if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
+ *sc_status = kSCStatusFailed;
+ goto done;
+ }
+
+ if (!isA_CFString(key)) {
+ *sc_status = kSCStatusInvalidArgument;
+ goto done;
+ }
+
+ /* un-serialize the data */
+ if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
+ *sc_status = kSCStatusFailed;
+ goto done;
+ }
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Add key to configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
+ if (!mySession) {
+ *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ goto done;
}
- *sc_status = kSCStatusOK;
+ *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+ if (*sc_status == kSCStatusOK) {
+ *newInstance = 0;
+ }
+
+ done :
+
+ if (key) CFRelease(key);
+ if (data) CFRelease(data);
+
+ return KERN_SUCCESS;
+}
+
+
+__private_extern__
+kern_return_t
+_configadd_s(mach_port_t server,
+ xmlData_t keyRef, /* raw XML bytes */
+ mach_msg_type_number_t keyLen,
+ xmlData_t dataRef, /* raw XML bytes */
+ mach_msg_type_number_t dataLen,
+ int *newInstance,
+ int *sc_status
+)
+{
+ CFDataRef data = NULL; /* data (un-serialized) */
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
+ SCDynamicStorePrivateRef storePrivate;
+ Boolean useSessionKeys;
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- } else if (!isA_CFString(key)) {
+ goto done;
+ }
+
+ if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
/* un-serialize the data */
if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
*sc_status = kSCStatusFailed;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ goto done;
}
- if (*sc_status != kSCStatusOK) {
- if (key) CFRelease(key);
- if (data) CFRelease(data);
- return KERN_SUCCESS;
+ // force "useSessionKeys"
+ storePrivate = (SCDynamicStorePrivateRef)mySession->store;
+ useSessionKeys = storePrivate->useSessionKeys;
+ storePrivate->useSessionKeys = TRUE;
+
+ *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+ if (*sc_status == kSCStatusOK) {
+ *newInstance = 0;
}
- *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data);
- *newInstance = 0;
+ // restore "useSessionKeys"
+ storePrivate->useSessionKeys = useSessionKeys;
+
+ done :
- CFRelease(key);
- CFRelease(data);
+ if (key) CFRelease(key);
+ if (data) CFRelease(data);
return KERN_SUCCESS;
}
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * October 17, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include "configd.h"
-#include "session.h"
-
-__private_extern__
-int
-__SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value)
-{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- int sc_status = kSCStatusOK;
- CFStringRef sessionKey;
- CFDictionaryRef dict;
- CFMutableDictionaryRef newDict;
- CFArrayRef keys;
- CFMutableArrayRef newKeys;
-
- if (_configd_verbose) {
- CFPropertyListRef val;
-
- (void) _SCUnserialize(&val, value, NULL, NULL);
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddTemporaryValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val);
- CFRelease(val);
- }
-
- if (!store || (storePrivate->server == MACH_PORT_NULL)) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
- /*
- * 1. Add the key
- */
- sc_status = __SCDynamicStoreAddValue(store, key, value);
- if (sc_status != kSCStatusOK) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreAddValue(): %s"), SCErrorString(sc_status));
- return sc_status;
- }
-
- /*
- * 2. Create the session key
- */
- sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
-
- /*
- * 3. Add this key to my list of per-session keys
- */
- dict = CFDictionaryGetValue(sessionData, sessionKey);
- keys = CFDictionaryGetValue(dict, kSCDSessionKeys);
- if ((keys == NULL) ||
- (CFArrayGetFirstIndexOfValue(keys,
- CFRangeMake(0, CFArrayGetCount(keys)),
- key) == -1)) {
- /*
- * if no session keys defined "or" keys defined but not
- * this one...
- */
- if (keys) {
- /* this is a new session key */
- newKeys = CFArrayCreateMutableCopy(NULL, 0, keys);
- } else {
- /* this is an additional session key */
- newKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- }
- CFArrayAppendValue(newKeys, key);
-
- /* update session dictionary */
- newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
- CFDictionarySetValue(newDict, kSCDSessionKeys, newKeys);
- CFRelease(newKeys);
- CFDictionarySetValue(sessionData, sessionKey, newDict);
- CFRelease(newDict);
- }
-
- /*
- * 4. Mark the key as a "session" key and track the creator.
- */
- dict = CFDictionaryGetValue(storeData, key);
- newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
- CFDictionarySetValue(newDict, kSCDSession, sessionKey);
- CFDictionarySetValue(storeData, key, newDict);
- CFRelease(newDict);
-
- CFRelease(sessionKey);
- return sc_status;
-}
-
-
-__private_extern__
-kern_return_t
-_configadd_s(mach_port_t server,
- xmlData_t keyRef, /* raw XML bytes */
- mach_msg_type_number_t keyLen,
- xmlData_t dataRef, /* raw XML bytes */
- mach_msg_type_number_t dataLen,
- int *newInstance,
- int *sc_status
-)
-{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
- CFDataRef data; /* data (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Add (session) key to configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
- *sc_status = kSCStatusOK;
-
- /* un-serialize the key */
- if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
- *sc_status = kSCStatusFailed;
- } else if (!isA_CFString(key)) {
- *sc_status = kSCStatusInvalidArgument;
- }
-
- /* un-serialize the data */
- if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
- *sc_status = kSCStatusFailed;
- }
-
- if (!mySession) {
- *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
- if (*sc_status != kSCStatusOK) {
- if (key) CFRelease(key);
- if (data) CFRelease(data);
- return KERN_SUCCESS;
- }
-
- *sc_status = __SCDynamicStoreAddTemporaryValue(mySession->store, key, data);
- if (*sc_status == kSCStatusOK) {
- *newInstance = 1;
- }
- CFRelease(key);
- CFRelease(data);
-
- return KERN_SUCCESS;
-}
int
__SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store;
- CFIndex keyCnt;
- CFStringRef sessionKey;
CFDictionaryRef dict;
CFArrayRef keys;
+ CFIndex keyCnt;
serverSessionRef mySession;
-
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreClose:"));
+ CFStringRef sessionKey;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store;
if ((*store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
/*
- * Remove the run loop source on the server port (for this
- * client). Then, invalidate and release the port.
+ * invalidate and release our run loop source on the server
+ * port (for this client). Then, release the port.
*/
mySession = getSession(storePrivate->server);
if (mySession->serverRunLoopSource) {
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
- mySession->serverRunLoopSource,
- kCFRunLoopDefaultMode);
+ CFRunLoopSourceInvalidate(mySession->serverRunLoopSource);
CFRelease(mySession->serverRunLoopSource);
}
CFMachPortInvalidate(mySession->serverPort);
{
serverSessionRef mySession = getSession(server);
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Close session."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
return KERN_SUCCESS;
*/
*sc_status = __SCDynamicStoreClose(&mySession->store, FALSE);
if (*sc_status != kSCStatusOK) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreClose(): %s"), SCErrorString(*sc_status));
return KERN_SUCCESS;
}
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFDictionaryRef dict;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
/* Return the data associated with the key */
*value = CFRetain(CFDictionaryGetValue(dict, kSCDData));
- if (_configd_verbose) {
- CFPropertyListRef val;
-
- (void) _SCUnserialize(&val, *value, NULL, NULL);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val);
- CFRelease(val);
- }
-
return kSCStatusOK;
}
int *sc_status
)
{
- CFStringRef key; /* key (un-serialized) */
- serverSessionRef mySession = getSession(server);
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
Boolean ok;
CFDataRef value;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Get key from configuration database."));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
*dataRef = NULL;
*dataLen = 0;
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value, FALSE);
- CFRelease(key);
if (*sc_status != kSCStatusOK) {
- return KERN_SUCCESS;
+ goto done;
}
/* serialize the data */
CFRelease(value);
if (!ok) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
/*
*/
*newInstance = 1;
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
addSpecific myContext;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyMultiple:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
/* Return the keys/values associated with the key */
*values = myContext.dict;
- if (_configd_verbose) {
- CFDictionaryRef expDict;
-
- expDict = _SCUnserializeMultiple(*values);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" values = %@"), expDict);
- CFRelease(expDict);
- }
-
return kSCStatusOK;
}
Boolean ok;
CFArrayRef patterns = NULL; /* patterns (un-serialized) */
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Get keys from configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
*dataRef = NULL;
*dataLen = 0;
- *sc_status = kSCStatusOK;
if (keysRef && (keysLen > 0)) {
/* un-serialize the keys */
if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) {
*sc_status = kSCStatusFailed;
+ goto done;
}
if (!isA_CFArray(keys)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
}
/* un-serialize the patterns */
if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) {
*sc_status = kSCStatusFailed;
+ goto done;
}
if (!isA_CFArray(patterns)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
+ goto done;
}
- if (*sc_status != kSCStatusOK) {
- if (keys) CFRelease(keys);
- if (patterns) CFRelease(patterns);
- return KERN_SUCCESS;
- }
-
+ /* fetch the requested information */
*sc_status = __SCDynamicStoreCopyMultiple(mySession->store, keys, patterns, &dict);
- if (keys) CFRelease(keys);
- if (patterns) CFRelease(patterns);
/* serialize the dictionary of matching keys/patterns */
ok = _SCSerialize(dict, NULL, (void **)dataRef, (CFIndex *)dataLen);
CFRelease(dict);
if (!ok) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
}
+ done :
+
+ if (keys) CFRelease(keys);
+ if (patterns) CFRelease(patterns);
return KERN_SUCCESS;
}
CFStringRef storeStr;
CFDictionaryRef storeValue;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
- storeCnt = CFDictionaryGetCount(storeData);
- keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
-
if (isRegex) {
CFStringRef reErrStr;
if (!patternCompile(key, &preg, &reErrStr)) {
- CFArrayAppendValue(keyArray, reErrStr);
+ *subKeys = CFArrayCreate(NULL, (const void **)&reErrStr, 1, &kCFTypeArrayCallBacks);
CFRelease(reErrStr);
- *subKeys = CFArrayCreateCopy(NULL, keyArray);
- CFRelease(keyArray);
return kSCStatusFailed;
}
}
+ storeCnt = CFDictionaryGetCount(storeData);
+ keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
if (storeCnt > 0) {
int i;
const void * storeKeys_q[N_QUICK];
if (storeKeyLen > (CFIndex)sizeof(storeKey_q))
storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0);
if (_SC_cfstring_to_cstring(storeStr, storeKey, storeKeyLen, kCFStringEncodingASCII) == NULL) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList(): could not convert store key to C string"));
if (storeKey != storeKey_q) CFAllocatorDeallocate(NULL, storeKey);
continue;
}
&preg,
reErrBuf,
sizeof(reErrBuf));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+ SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList regexec() failed: %s"), reErrBuf);
break;
}
}
regfree(&preg);
}
- *subKeys = keyArray;
-
+ *subKeys = CFArrayCreateCopy(NULL, keyArray);
+ CFRelease(keyArray);
return kSCStatusOK;
}
int *sc_status
)
{
- CFStringRef key; /* key (un-serialized) */
- serverSessionRef mySession = getSession(server);
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
Boolean ok;
- CFArrayRef subKeys; /* array of CFStringRef's */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("List keys in configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFArrayRef subKeys; /* array of CFStringRef's */
*listRef = NULL;
*listLen = 0;
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys);
- CFRelease(key);
if (*sc_status != kSCStatusOK) {
- return KERN_SUCCESS;
+ goto done;
}
/* serialize the list of keys */
CFRelease(subKeys);
if (!ok) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
int
__SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
serverSessionRef mySession;
-
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreLock:"));
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
{
serverSessionRef mySession = getSession(server);
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Lock configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
return KERN_SUCCESS;
*sc_status = __SCDynamicStoreLock(mySession->store, FALSE);
if (*sc_status != kSCStatusOK) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" SCDynamicStoreLock(): %s"), SCErrorString(*sc_status));
return KERN_SUCCESS;
}
Boolean newValue = FALSE;
CFDataRef value;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Notify key in configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreNotifyValue(mySession->store, key, FALSE);
- CFRelease(key);
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
int
__SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
{
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreOpen:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" name = %@"), name);
- }
-
/*
* allocate and initialize a new session
*/
_configopen(mach_port_t server,
xmlData_t nameRef, /* raw XML bytes */
mach_msg_type_number_t nameLen,
+ xmlData_t optionsRef, /* raw XML bytes */
+ mach_msg_type_number_t optionsLen,
mach_port_t *newServer,
int *sc_status)
{
- kern_return_t status;
- serverSessionRef mySession, newSession;
- CFStringRef name; /* name (un-serialized) */
- mach_port_t oldNotify;
- CFStringRef sessionKey;
- CFDictionaryRef info;
- CFMutableDictionaryRef newInfo;
- CFMachPortRef mp;
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Open new session."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFDictionaryRef info;
+ CFMachPortRef mp;
+ serverSessionRef mySession;
+ CFStringRef name = NULL; /* name (un-serialized) */
+ CFMutableDictionaryRef newInfo;
+ serverSessionRef newSession;
+ mach_port_t oldNotify;
+ CFDictionaryRef options = NULL; /* options (un-serialized) */
+ CFStringRef sessionKey;
+ kern_return_t status;
+ SCDynamicStorePrivateRef storePrivate;
+ CFBooleanRef useSessionKeys = NULL;
/* un-serialize the name */
if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(name)) {
- CFRelease(name);
*sc_status = kSCStatusInvalidArgument;
- return KERN_SUCCESS;
+ goto done;
+ }
+
+ if (optionsRef && (optionsLen > 0)) {
+ /* un-serialize the [session] options */
+ if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) {
+ *sc_status = kSCStatusFailed;
+ goto done;
+ }
+
+ if (!isA_CFDictionary(options)) {
+ *sc_status = kSCStatusInvalidArgument;
+ goto done;
+ }
+
+ /*
+ * [pre-]process any provided options
+ */
+ useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys);
+ if (useSessionKeys != NULL) {
+ if (!isA_CFBoolean(useSessionKeys)) {
+ *sc_status = kSCStatusInvalidArgument;
+ goto done;
+ }
+ }
}
mySession = getSession(server);
if (mySession->store) {
- CFRelease(name);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" Sorry, this session is already open."));
+#ifdef DEBUG
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open."));
+#endif /* DEBUG */
*sc_status = kSCStatusFailed; /* you can't re-open an "open" session */
- return KERN_SUCCESS;
+ goto done;
}
/* Create the server port for this session */
}
*sc_status = __SCDynamicStoreOpen(&newSession->store, name);
+ storePrivate = (SCDynamicStorePrivateRef)newSession->store;
/*
* Make the server port accessible to the framework routines.
*/
- ((SCDynamicStorePrivateRef)newSession->store)->server = *newServer;
+ storePrivate->server = *newServer;
+
+ /*
+ * Process any provided [session] options
+ */
+ if (useSessionKeys != NULL) {
+ storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys);
+ }
/* Request a notification when/if the client dies */
status = mach_port_request_notification(mach_task_self(),
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
- CFRelease(name);
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen() mach_port_request_notification() failed: %s"), mach_error_string(status));
cleanupSession(*newServer);
*newServer = MACH_PORT_NULL;
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
+#ifdef DEBUG
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_configd_verbose, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
}
+#endif /* DEBUG */
/*
* Save the name of the calling application / plug-in with the session data.
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(newInfo, kSCDName, name);
- CFRelease(name);
CFDictionarySetValue(sessionData, sessionKey, newInfo);
CFRelease(newInfo);
CFRelease(sessionKey);
+ done :
+
+ if (name) CFRelease(name);
+ if (options) CFRelease(options);
return KERN_SUCCESS;
}
CFMutableDictionaryRef newDict;
CFStringRef sessionKey;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Remove key from configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreRemoveValue(mySession->store, key, FALSE);
- CFRelease(key);
+
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
CFStringRef sessionKey;
CFStringRef storeSessionKey;
- if (_configd_verbose) {
- CFPropertyListRef val;
-
- (void) _SCUnserialize(&val, value, NULL, NULL);
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" value = %@"), val);
- CFRelease(val);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
if (_configd_trace) {
SCTrace(TRUE, _configd_trace,
- CFSTR("%s : %5d : %@\n"),
- internal ? "*set " : "set ",
+ CFSTR("%s%s : %5d : %@\n"),
+ internal ? "*set " : "set ",
+ storePrivate->useSessionKeys ? "t " : " ",
storePrivate->server,
key);
}
newEntry = !CFDictionaryContainsKey(newDict, kSCDData);
CFDictionarySetValue(newDict, kSCDData, value);
- /*
- * 4. Since we are updating this key we need to check and, if
- * necessary, remove the indication that this key is on
- * another session's remove-on-close list.
- */
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
- if (CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) &&
- !CFEqual(sessionKey, storeSessionKey)) {
- CFStringRef removedKey;
-
- /* We are no longer a session key! */
- CFDictionaryRemoveValue(newDict, kSCDSession);
- /* add this session key to the (session) removal list */
- removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key);
- CFSetAddValue(removedSessionKeys, removedKey);
- CFRelease(removedKey);
+ /*
+ * 4. Manage per-session keys.
+ */
+ if (storePrivate->useSessionKeys) {
+ if (newEntry) {
+ CFArrayRef keys;
+ CFMutableDictionaryRef newSession;
+ CFMutableArrayRef newKeys;
+ CFDictionaryRef session;
+
+ /*
+ * Add this key to my list of per-session keys
+ */
+ session = CFDictionaryGetValue(sessionData, sessionKey);
+ keys = CFDictionaryGetValue(session, kSCDSessionKeys);
+ if ((keys == NULL) ||
+ (CFArrayGetFirstIndexOfValue(keys,
+ CFRangeMake(0, CFArrayGetCount(keys)),
+ key) == kCFNotFound)) {
+ /*
+ * if no session keys defined "or" keys defined but not
+ * this one...
+ */
+ if (keys != NULL) {
+ /* this is the first session key */
+ newKeys = CFArrayCreateMutableCopy(NULL, 0, keys);
+ } else {
+ /* this is an additional session key */
+ newKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(newKeys, key);
+
+ /* update session dictionary */
+ newSession = CFDictionaryCreateMutableCopy(NULL, 0, session);
+ CFDictionarySetValue(newSession, kSCDSessionKeys, newKeys);
+ CFRelease(newKeys);
+ CFDictionarySetValue(sessionData, sessionKey, newSession);
+ CFRelease(newSession);
+ }
+
+ /*
+ * Mark the key as a "session" key and track the creator.
+ */
+ CFDictionarySetValue(newDict, kSCDSession, sessionKey);
+ } else {
+ /*
+ * Since we are using per-session keys and this key already
+ * exists, check if it was created by "our" session
+ */
+ dict = CFDictionaryGetValue(storeData, key);
+ if (!CFDictionaryGetValueIfPresent(dict, kSCDSession, (void *)&storeSessionKey) ||
+ !CFEqual(sessionKey, storeSessionKey)) {
+ /*
+ * if the key exists and is not a session key or
+ * if the key exists it's not "our" session.
+ */
+ sc_status = kSCStatusKeyExists;
+ CFRelease(sessionKey);
+ CFRelease(newDict);
+ goto done;
+ }
+ }
+ } else {
+ /*
+ * Since we are updating this key we need to check and, if
+ * necessary, remove the indication that this key is on
+ * another session's remove-on-close list.
+ */
+ if (!newEntry &&
+ CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) &&
+ !CFEqual(sessionKey, storeSessionKey)) {
+ CFStringRef removedKey;
+
+ /* We are no longer a session key! */
+ CFDictionaryRemoveValue(newDict, kSCDSession);
+
+ /* add this session key to the (session) removal list */
+ removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key);
+ CFSetAddValue(removedSessionKeys, removedKey);
+ CFRelease(removedKey);
+ }
}
+
CFRelease(sessionKey);
/*
*/
CFSetAddValue(changedKeys, key);
+ done :
+
/*
* 8. Release our lock.
*/
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
- CFDataRef data; /* data (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Set key to configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
- *sc_status = kSCStatusOK;
+ CFDataRef data = NULL; /* data (un-serialized) */
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- } else if (!isA_CFString(key)) {
+ goto done;
+ }
+
+ if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
/* un-serialize the data */
if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
*sc_status = kSCStatusFailed;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
- if (*sc_status != kSCStatusOK) {
- if (key) CFRelease(key);
- if (data) CFRelease(data);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreSetValue(mySession->store, key, data, FALSE);
*newInstance = 0;
- CFRelease(key);
- CFRelease(data);
+ done :
+ if (key) CFRelease(key);
+ if (data) CFRelease(data);
return KERN_SUCCESS;
}
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
int sc_status = kSCStatusOK;
- if (_configd_verbose) {
- CFDictionaryRef expDict;
-
- expDict = keysToSet ? _SCUnserializeMultiple(keysToSet) : NULL;
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetMultiple:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToSet = %@"), expDict);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToRemove = %@"), keysToRemove);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keysToNotify = %@"), keysToNotify);
- if (expDict) CFRelease(expDict);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
mach_msg_type_number_t notifyLen,
int *sc_status)
{
- serverSessionRef mySession = getSession(server);
- CFDictionaryRef dict = NULL; /* key/value dictionary (un-serialized) */
- CFArrayRef remove = NULL; /* keys to remove (un-serialized) */
- CFArrayRef notify = NULL; /* keys to notify (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Set/remove/notify keys to configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
- *sc_status = kSCStatusOK;
+ CFDictionaryRef dict = NULL; /* key/value dictionary (un-serialized) */
+ serverSessionRef mySession = getSession(server);
+ CFArrayRef notify = NULL; /* keys to notify (un-serialized) */
+ CFArrayRef remove = NULL; /* keys to remove (un-serialized) */
if (dictRef && (dictLen > 0)) {
/* un-serialize the key/value pairs to set */
if (!_SCUnserialize((CFPropertyListRef *)&dict, NULL, (void *)dictRef, dictLen)) {
*sc_status = kSCStatusFailed;
- } else if (!isA_CFDictionary(dict)) {
+ goto done;
+ }
+
+ if (!isA_CFDictionary(dict)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
}
/* un-serialize the keys to remove */
if (!_SCUnserialize((CFPropertyListRef *)&remove, NULL, (void *)removeRef, removeLen)) {
*sc_status = kSCStatusFailed;
- } else if (!isA_CFArray(remove)) {
+ goto done;
+ }
+
+ if (!isA_CFArray(remove)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
}
/* un-serialize the keys to notify */
if (!_SCUnserialize((CFPropertyListRef *)¬ify, NULL, (void *)notifyRef, notifyLen)) {
*sc_status = kSCStatusFailed;
- } else if (!isA_CFArray(notify)) {
+ goto done;
+ }
+
+ if (!isA_CFArray(notify)) {
*sc_status = kSCStatusInvalidArgument;
+ goto done;
}
}
if (!mySession) {
/* you must have an open session to play */
*sc_status = kSCStatusNoStoreSession;
- }
-
- if (*sc_status != kSCStatusOK) {
goto done;
}
int sc_status;
CFDataRef value;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreTouchValue:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
/* store entry does not exist, create */
now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), now);
(void) _SCSerialize(now, &value, NULL, NULL);
CFRelease(now);
break;
/* store entry exists */
- (void) _SCUnserialize((CFPropertyListRef *)&now, value, NULL, NULL);
+ (void) _SCUnserialize((CFPropertyListRef *)&now, value, NULL, 0);
if (isA_CFDate(now)) {
/* the value is a CFDate, update the time stamp */
CFRelease(now);
CFRelease(value);
now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" new time stamp = %@"), now);
(void) _SCSerialize(now, &value, NULL, NULL);
} /* else, we'll just save the data (again) to bump the instance */
CFRelease(now);
break;
}
default :
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
goto done;
}
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Touch key in configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreTouchValue(mySession->store, key);
- CFRelease(key);
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
i = CFArrayGetFirstIndexOfValue(sessionKeys,
CFRangeMake(0, CFArrayGetCount(sessionKeys)),
key);
- if (i == -1) {
+ if (i == kCFNotFound) {
/* if this session key has already been removed */
goto done;
}
int
__SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
{
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
serverSessionRef mySession;
-
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreUnlock:"));
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
CFSetRemoveAllValues (deferredRemovals_s);
CFSetRemoveAllValues (removedSessionKeys_s);
-#ifdef DEBUG
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys I changed = %@"), changedKeys);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys flagged for removal = %@"), deferredRemovals);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys I'm watching = %@"), storePrivate->keys);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("patterns I'm watching = %@"), storePrivate->patterns);
-#endif /* DEBUG */
-
/*
* push notifications to any session watching those keys which
* were recently changed.
CFSetApplyFunction(removedSessionKeys, _cleanupRemovedSessionKeys, NULL);
CFSetRemoveAllValues(removedSessionKeys);
-#ifdef DEBUG
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sessions to notify = %@"), needsNotification);
-#endif /* DEBUG */
-
/* Remove the "locked" run loop source for this port */
mySession = getSession(storePrivate->server);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, CFSTR("locked"));
{
serverSessionRef mySession = getSession(server);
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Unlock configuration database."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
return KERN_SUCCESS;
*sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE);
if (*sc_status != kSCStatusOK) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreUnlock(): %s"), SCErrorString(*sc_status));
return KERN_SUCCESS;
}
CFNumberRef sessionNum = NULL;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddWatchedKey:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Add notification key for this session."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex != 0, FALSE);
- CFRelease(key);
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
updateKeysContext myContext;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetNotificationKeys:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" keys = %@"), keys);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" patterns = %@"), patterns);
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
CFArrayRef keys = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
CFArrayRef patterns = NULL; /* patterns (un-serialized) */
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Add notification key for this session."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
*sc_status = kSCStatusOK;
if (keysRef && (keysLen > 0)) {
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyCancel:"));
-
- if (!store) {
- return kSCStatusNoStoreSession; /* you must have an open session to play */
- }
-
/*
* cleanup any mach port based notifications.
*/
* cleanup any file based notifications.
*/
if (storePrivate->notifyFile >= 0) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" closing (notification) fd %d"), storePrivate->notifyFile);
+ // close (notification) fd
(void) close(storePrivate->notifyFile);
storePrivate->notifyFile = -1;
}
{
serverSessionRef mySession = getSession(server);
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Cancel requested notifications."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
return KERN_SUCCESS;
}
*sc_status = __SCDynamicStoreNotifyCancel(mySession->store);
- if (*sc_status != kSCStatusOK) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreNotifyCancel(): %s"), SCErrorString(*sc_status));
- }
-
return KERN_SUCCESS;
}
CFDictionaryRef info;
CFMutableDictionaryRef newInfo;
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyNotifiedKeys:"));
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
CFArrayRef notifierKeys; /* array of CFStringRef's */
Boolean ok;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("List notification keys which have changed."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
-
*listRef = NULL;
*listLen = 0;
CFNumberRef sessionNum;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveWatchedKey:"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" key = %@"), key);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
- }
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
int *sc_status
)
{
- serverSessionRef mySession = getSession(server);
- CFStringRef key; /* key (un-serialized) */
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Remove notification key for this session."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- }
+ CFStringRef key = NULL; /* key (un-serialized) */
+ serverSessionRef mySession = getSession(server);
/* un-serialize the key */
if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
- return KERN_SUCCESS;
+ goto done;
}
if (!isA_CFString(key)) {
*sc_status = kSCStatusInvalidArgument;
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
- CFRelease(key);
- return KERN_SUCCESS;
+ goto done;
}
*sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store,
key,
isRegex != 0,
FALSE);
- CFRelease(key);
+ done :
+
+ if (key) CFRelease(key);
return KERN_SUCCESS;
}
CFStringRef sessionKey;
CFDictionaryRef info;
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyFileDescriptor:"));
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
}
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- SCLog(_configd_verbose, LOG_NOTICE, CFSTR("socket: %s"), strerror(errno));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("__SCDynamicStoreNotifyFileDescriptor socket() failed: %s"), strerror(errno));
return kSCStatusFailed;
}
int *sc_status
)
{
- kern_return_t status;
- serverSessionRef mySession = getSession(server);
- SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store;
- struct sockaddr_un un;
- int sock;
- int bufSiz = sizeof(storePrivate->notifyFileIdentifier);
- int nbioYes = 1;
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Send message via UNIX domain socket when a notification key changes."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" path = %s"), pathRef);
- }
+ int bufSiz;
+ serverSessionRef mySession = getSession(server);
+ int nbioYes;
+ int sock;
+ kern_return_t status;
+ SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store;
+ struct sockaddr_un un;
/*
* if socket currently open, close it!
*/
/* validate the UNIX domain socket path */
if (pathLen > (sizeof(un.sun_path) - 1)) {
- SCLog(_configd_verbose, LOG_NOTICE, CFSTR("domain socket path length too long!"));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("_notifyviafd(): domain socket path length too long!"));
status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd vm_deallocate() failed: %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
+#endif /* DEBUG */
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
}
bcopy(pathRef, un.sun_path, pathLen);
un.sun_path[pathLen] = '\0';
status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen);
+#ifdef DEBUG
if (status != KERN_SUCCESS) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd vm_deallocate() failed: %s"), mach_error_string(status));
/* non-fatal???, proceed */
}
+#endif /* DEBUG */
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
/* establish the connection, get ready for a read() */
if (connect(sock, (struct sockaddr *)&un, sizeof(un)) == -1) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("connect: %s"), strerror(errno));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd connect() failed: %s"), strerror(errno));
(void) close(sock);
storePrivate->notifyStatus = NotifierNotRegistered;
storePrivate->notifyFile = -1;
return KERN_SUCCESS;
}
- SCLog(_configd_verbose, LOG_NOTICE, CFSTR(" fd = %d"), sock);
(void) unlink(un.sun_path);
+ bufSiz = sizeof(storePrivate->notifyFileIdentifier);
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufSiz, sizeof(bufSiz)) < 0) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("setsockopt: %s"), strerror(errno));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd setsockopt() failed: %s"), strerror(errno));
(void) close(sock);
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
}
+ nbioYes = 1;
if (ioctl(sock, FIONBIO, &nbioYes) == -1) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("ioctl(,FIONBIO,): %s"), strerror(errno));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd ioctl(,FIONBIO,) failed: %s"), strerror(errno));
(void) close(sock);
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
CFStringRef sessionKey;
CFDictionaryRef info;
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyMachPort:"));
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
serverSessionRef mySession = getSession(server);
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)mySession->store;
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Send mach message when a notification key changes."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" port = %d"), port);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" message id = %d"), identifier);
- }
-
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
return KERN_SUCCESS;
}
if (storePrivate->notifyPort != MACH_PORT_NULL) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" destroying old callback mach port %d"), storePrivate->notifyPort);
+ // destroying [old] callback mach port
(void) mach_port_destroy(mach_task_self(), storePrivate->notifyPort);
}
* - initial revision
*/
+#include <unistd.h>
+#include <sys/types.h>
+
#include "configd.h"
#include "configd_server.h"
#include "session.h"
CFStringRef sessionKey;
CFDictionaryRef info;
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifySignal:"));
-
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession; /* you must have an open session to play */
}
mach_port_t oldNotify;
#endif /* NOTYET */
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("Send signal when a notification key changes."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" server = %d"), server);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" task = %d"), task);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" signal = %d"), sig);
- }
-
status = pid_for_task(task, &pid);
if (status != KERN_SUCCESS) {
*sc_status = kSCStatusFailed; /* could not determine pid for task */
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviasignal mach_port_request_notification() failed: %s"), mach_error_string(status));
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
}
+#ifdef NOTYET_DEBUG
if (oldNotify != MACH_PORT_NULL) {
- SCLog(_configd_verbose, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?"));
+ SCLog(TRUE, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?"));
}
+#endif /* NOTYET_DEBUG */
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task);
+ // add task notification port to the server's port set
status = mach_port_move_member(mach_task_self(), task, server_ports);
if (status != KERN_SUCCESS) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviasignal mach_port_move_member() failed: %s"), mach_error_string(status));
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
}
if (data) {
CFPropertyListRef plist;
- if (!_SCUnserialize(&plist, data, NULL, NULL)) {
+ if (!_SCUnserialize(&plist, data, NULL, 0)) {
goto done;
}
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFDataRef xmlData;
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSnapshot:"));
-
/* check credentials */
mySession = getSession(storePrivate->server);
xmlData = CFPropertyListCreateXMLData(NULL, expandedStoreData);
CFRelease(expandedStoreData);
if (!xmlData) {
- SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+ SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateXMLData() failed"));
close(fd);
return kSCStatusFailed;
}
xmlData = CFPropertyListCreateXMLData(NULL, patternData);
if (!xmlData) {
- SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+ SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateXMLData() failed"));
close(fd);
return kSCStatusFailed;
}
xmlData = CFPropertyListCreateXMLData(NULL, sessionData);
if (!xmlData) {
- SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+ SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateXMLData() failed"));
close(fd);
return kSCStatusFailed;
}
{
serverSessionRef mySession = getSession(server);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Snapshot configuration database."));
-
if (!mySession) {
*sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
return KERN_SUCCESS;
}
*sc_status = __SCDynamicStoreSnapshot(mySession->store);
- if (*sc_status != kSCStatusOK) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreSnapshot(): %s"), SCErrorString(*sc_status));
- }
-
return KERN_SUCCESS;
}
+++ /dev/null
-/*
- * Copyright (c) 2003 Apple Computer, 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@
- */
-/*
- * Import the real "config.defs" file from the framework.
- *
- * The ultimate goal is to have a single ".defs" file in
- * the project which is used to generate a shared "config.h"
- * header, the "configUser.c" file used by (and included in)
- * the built framework, and the "configServer.c" file used
- * by the server.
- *
- * To date, I have been unable to determine the needed flags
- * and/or rules to add to the Makefile to ensure that any
- * changes made to the real projects ".defs" file results in
- * the[re-]generation of both framework and servers MiG files.
- *
- * As such... IF YOU CHANGE THE ".defs" FILE, MAKE CLEAN!
- */
-
-#include <SystemConfiguration/config.defs>
--- /dev/null
+.\"
+.\" @(#)configd.8
+.\"
+.Dd November 4, 2003
+.Dt CONFIGD 8
+.Os Mac OS X
+.Sh NAME
+.Nm configd
+.Nd System Configuration Daemon
+.Sh SYNOPSIS
+.Nm
+.Op Fl bdv
+.Op Fl B Ar bundleID
+.Op Fl V Ar bundleID
+.Op Fl t Ar bundle-path
+.Sh DESCRIPTION
+The
+.Nm
+daemon
+is responsible for many configuration aspects of the local system.
+.Nm
+maintains data reflecting the desired and current state of the system,
+provides notifications to applications when this data changes,
+and hosts a number of configuration agents in the form of loadable
+bundles.
+.Pp
+Each configuration agent is responsible for a well-defined aspect
+of configuration management. The agents look to one or more input
+sources (preferences, low-level kernel events,
+.Nm
+notifications, etc) and, through
+a set of policy modules, interacts with the system to establish
+the desired operational configuration.
+.Pp
+Access to the data maintained by
+.Nm
+is via the SystemConfiguration.framework SCDynamicStore APIs.
+.Sh OPTIONS
+.Pp
+The command line options are as follows:
+.Bl -tag -width xx
+.It Fl b
+Don't actually load any bundles.
+.It Fl B Ar bundleID
+Prevents the loading of the bundle with the specified
+.Ar bundleID .
+.It Fl d
+Run
+.Nm
+in the foreground without forking. This is useful for debugging.
+.It Fl v
+Puts
+.Nm
+into verbose mode. Displays debugging information about
+bundles as they are being loaded.
+.It Fl V Ar bundleID
+Turns verbose mode on for the bundle with the specified
+.Ar bundleID .
+.It Fl t Ar bundle-path
+Loads only the bundle specified by
+.Ar bundle-path .
+.El
+.Sh BUNDLES
+At the present time, the majority of the configuration agents (or bundles) hosted by
+.Nm
+are used to establish and maintain the network configuration.
+These agents include:
+.Pp
+.Ss ATconfig
+This bundle is responsible for establishing and maintaining the AppleTalk network configuration on the system.
+.Ss KernelEventMonitor
+This bundle is responsible for monitoring kernel events and conveying changes to the network state (e.g. link status) to other configuration agents and interested applications.
+.Ss InterfaceNamer
+This bundle provides a name to each of the system's network interfaces. The bundle queries the
+IOKit Registry for a list of network devices attached to the system and gives them BSD style names such as
+.Qq en0 .
+.Ss IPConfiguration
+This agent is responsible for establishing and maintaining IPv4 addresses on the system. These addresses may be manually specified in the network preferences or acquired using DHCP (or BOOTP).
+.Ss IP6Configuration
+This agent is responsible for establishing and maintaining IPv6 addresses on the system.
+.Ss IPMonitor
+This agent is responsible for establishing and maintaining the primary network service, the default route, the active DNS configuration, and the active network proxies on the system.
+.Ss LinkConfiguration
+This agent is responsible for establishing and maintaining the media type, media options, and MTU for ethernet interfaces.
+.Ss PreferencesMonitor
+This agent is responsible for conveying the network configuration preferences specified by the administrator to the various configuration agents (AppleTalk, IPv4, IPv6, ...).
+.Ss PPPController
+This agent is responsible for establishing and maintaining PPP connections on the system.
+.Sh FILES
+.Bl -tag -width xx
+.It Pa /System/Library/SystemConfiguration/
+Directory of
+.Nm
+bundles
+.It Pa /Library/Preferences/SystemConfiguration/
+Default directory for system configuration persistent store files.
+.Bl -tag -width .../VirtualNetworkInterfaces.plist
+.It Pa .../preferences.plist
+System configuration
+.It Pa .../NetworkInterfaces.plist
+Network interface --> BSD interface mappings
+.It Pa .../VirtualNetworkInterfaces.plist
+Virtual network interface (VLAN) configuration
+.El
+.El
+.Sh ERRORS
+Log messages generated by
+.Nm
+and any configuration agents will are
+sent to the system log daemon by
+.Xr syslog 3 .
+The syslog facility used is LOG_DAEMON.
+If the
+.Fl d
+option is specified, log messages with written to stdout (or stderr if
+the priority is greater than LOG_NOTICE).
+.Sh SIGNALS
+.Nm
+was designed to run without any intervention but if you insist on sending a signal to the daemon then the following are available:
+.Bl -tag -width SIGTERM
+.It Dv SIGHUP
+This signal, typically used to tell a daemon to reload it's configuration, is ignored (there is no configuration).
+.It Dv SIGTERM
+This signal initiates a
+.Qq graceful
+shutdown of the daemon.
+.El
+.Sh SEE ALSO
+./".Xr SystemConfiguration.framework 3 ,
+.Xr scutil 8 ,
+.Xr scselect 8
+./".Xr mach_init 8
+.Sh HISTORY
+The
+.Nm
+daemon appeared in Mac OS X Public Beta.
+.Sh NOTES
+Unless started with the
+.Fl d
+option,
+.Nm
+will register with
+.Xr mach_init 8
+such that the daemon will be restarted in the event of a crash.
+This registration will be removed during
+.Qq graceful
+shutdowns of the daemon.
+.Pp
+This daemon and its current behavior may change without notice. Do not rely
+on its existence or its behavior. Consider it an unsupported command.
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * October 30, 2003 Allan Nathanson <ajn@apple.com>
+ * - add plugin "stop()" function support
+ *
* June 1, 2001 Allan Nathanson <ajn@apple.com>
* - public API conversion
*
#include "configd_server.h"
#include "plugin_support.h"
+__private_extern__
Boolean _configd_verbose = FALSE; /* TRUE if verbose logging enabled */
__private_extern__
static CFMachPortRef termRequested = NULL; /* Mach port used to notify runloop of a shutdown request */
-static struct option longopts[] = {
+static const struct option longopts[] = {
// { "no-bundles", no_argument, 0, 'b' },
// { "exclude-plugin", required_argument, 0, 'B' },
// { "no-fork", no_argument, 0, 'd' },
static void
usage(const char *prog)
{
- SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t plugin-path]\n"), prog);
+ SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t bundle-path]\n"), prog);
SCPrint(TRUE, stderr, CFSTR("options:\n"));
SCPrint(TRUE, stderr, CFSTR("\t-d\tdisable daemon/run in foreground\n"));
SCPrint(TRUE, stderr, CFSTR("\t-v\tenable verbose logging\n"));
{
switch (signum) {
case SIGTERM :
- if (termRequested) {
+ if (termRequested != NULL) {
mach_msg_empty_send_t msg;
mach_msg_option_t options;
kern_return_t status;
MACH_PORT_NULL, /* rcv_name */
0, /* timeout */
MACH_PORT_NULL); /* notify */
+ if (status == MACH_SEND_TIMED_OUT) {
+ mach_msg_destroy(&msg.header);
+ }
+ } else {
+ _exit(EX_OK);
}
break;
}
static void
term(CFMachPortRef port, void *msg, CFIndex size, void *info)
{
- server_shutdown();
+ int status = EX_OK;
+ Boolean wait;
+
+ wait = plugin_term(&status);
+ if (!wait) {
+ // if we are not waiting on a plugin
+ status = server_shutdown();
+ exit (status);
+ }
+
+ return;
}
{
Boolean enableRestart = (argc <= 1); /* only if there are no arguments */
Boolean forceForeground = FALSE;
+ mach_port_limits_t limits;
Boolean loadBundles = TRUE;
struct sigaction nact;
int opt;
extern int optind;
const char *prog = argv[0];
+ CFRunLoopSourceRef rls;
mach_port_t service_port = MACH_PORT_NULL;
+ kern_return_t status;
CFStringRef str;
const char *testBundle = NULL;
strerror(errno));
}
- /* add signal handler to catch a SIGTERM (if dynamic store) */
- if (testBundle == NULL) {
- if (enableRestart) {
- mach_port_limits_t limits;
- CFRunLoopSourceRef rls;
- kern_return_t status;
-
- /* add signal handler */
- if (sigaction(SIGTERM, &nact, NULL) == -1) {
- SCLog(_configd_verbose, LOG_ERR,
- CFSTR("sigaction(SIGTERM, ...) failed: %s"),
- strerror(errno));
- }
+ /* add signal handler to catch a SIGTERM */
+ if (sigaction(SIGTERM, &nact, NULL) == -1) {
+ SCLog(_configd_verbose, LOG_ERR,
+ CFSTR("sigaction(SIGTERM, ...) failed: %s"),
+ strerror(errno));
+ }
- /* create the "shutdown requested" notification port */
- termRequested = CFMachPortCreate(NULL, term, NULL, NULL);
-
- // set queue limit
- limits.mpl_qlimit = 1;
- status = mach_port_set_attributes(mach_task_self(),
- CFMachPortGetPort(termRequested),
- MACH_PORT_LIMITS_INFO,
- (mach_port_info_t)&limits,
- MACH_PORT_LIMITS_INFO_COUNT);
- if (status != KERN_SUCCESS) {
- perror("mach_port_set_attributes");
- }
+ /* create the "shutdown requested" notification port */
+ termRequested = CFMachPortCreate(NULL, term, NULL, NULL);
+
+ // set queue limit
+ limits.mpl_qlimit = 1;
+ status = mach_port_set_attributes(mach_task_self(),
+ CFMachPortGetPort(termRequested),
+ MACH_PORT_LIMITS_INFO,
+ (mach_port_info_t)&limits,
+ MACH_PORT_LIMITS_INFO_COUNT);
+ if (status != KERN_SUCCESS) {
+ perror("mach_port_set_attributes");
+ }
- // add to our runloop
- rls = CFMachPortCreateRunLoopSource(NULL, termRequested, 0);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
- CFRelease(rls);
- }
+ // add to our runloop
+ rls = CFMachPortCreateRunLoopSource(NULL, termRequested, 0);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+ CFRelease(rls);
+ if (testBundle == NULL) {
/* initialize primary (store management) thread */
server_init(service_port, enableRestart);
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * March 9, 2004 Allan Nathanson <ajn@apple.com>
+ * - add DNS configuration server
+ *
* June 1, 2001 Allan Nathanson <ajn@apple.com>
* - public API conversion
*
* - initial revision
*/
-#include <servers/bootstrap.h>
#include <sysexits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <servers/bootstrap.h>
#include "configd.h"
#include "configd_server.h"
#include "notify_server.h"
#include "session.h"
-#include "notify.h"
/* MiG generated externals and functions */
-extern struct rpc_subsystem _config_subsystem;
+extern struct mig_subsystem _config_subsystem;
extern boolean_t config_server(mach_msg_header_t *, mach_msg_header_t *);
+#include "shared_dns_info_types.h"
+#include "dnsinfo_server.h"
+
+/* MiG generated externals and functions */
+extern struct mig_subsystem _shared_dns_info_subsystem;
+extern boolean_t shared_dns_info_server(mach_msg_header_t *, mach_msg_header_t *);
+
/* configd server port (for new session requests) */
static CFMachPortRef configd_port = NULL;
(trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) {
thisSession->callerEUID = trailer->msgh_sender.val[0];
thisSession->callerEGID = trailer->msgh_sender.val[1];
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("caller has eUID = %d, eGID = %d"),
- thisSession->callerEUID,
- thisSession->callerEGID);
} else {
static Boolean warned = FALSE;
if (!warned) {
- SCLog(_configd_verbose, LOG_WARNING, CFSTR("caller's credentials not available."));
+ SCLog(TRUE, LOG_WARNING, CFSTR("caller's credentials not available."));
warned = TRUE;
}
thisSession->callerEUID = 0;
}
/*
- * (attemp to) process configd requests.
+ * (attempt to) process SCDynamicStore requests.
*/
processed = config_server(request, reply);
-
- if (!processed) {
- /*
- * (attempt to) process (NO MORE SENDERS) notification messages.
- */
- processed = notify_server(request, reply);
+ if (processed) {
+ return TRUE;
}
- if (!processed) {
- SCLog(TRUE, LOG_ERR, CFSTR("unknown message ID (%d) received"), request->msgh_id);
+ /*
+ * (attempt to) process DNS configuration requests.
+ */
+ processed = shared_dns_info_server(request, reply);
+ if (processed) {
+ return TRUE;
+ }
- reply->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->msgh_bits), 0);
- reply->msgh_remote_port = request->msgh_remote_port;
- reply->msgh_size = sizeof(mig_reply_error_t); /* Minimal size */
- reply->msgh_local_port = MACH_PORT_NULL;
- reply->msgh_id = request->msgh_id + 100;
- ((mig_reply_error_t *)reply)->NDR = NDR_record;
- ((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID;
+ /*
+ * (attempt to) process (NO MORE SENDERS) notification messages.
+ */
+ processed = notify_server(request, reply);
+ if (processed) {
+ return TRUE;
}
- return processed;
+ /*
+ * unknown message ID, log and return an error.
+ */
+ SCLog(TRUE, LOG_ERR, CFSTR("config_demux(): unknown message ID (%d) received"), request->msgh_id);
+ reply->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->msgh_bits), 0);
+ reply->msgh_remote_port = request->msgh_remote_port;
+ reply->msgh_size = sizeof(mig_reply_error_t); /* Minimal size */
+ reply->msgh_local_port = MACH_PORT_NULL;
+ reply->msgh_id = request->msgh_id + 100;
+ ((mig_reply_error_t *)reply)->NDR = NDR_record;
+ ((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID;
+
+ return FALSE;
}
mig_reply_error_t * bufRequest = msg;
uint32_t bufReply_q[MACH_MSG_BUFFER_SIZE/sizeof(uint32_t)];
mig_reply_error_t * bufReply = (mig_reply_error_t *)bufReply_q;
+ static CFIndex bufSize = 0;
mach_msg_return_t mr;
int options;
- if (_config_subsystem.maxsize > sizeof(bufReply_q)) {
- static Boolean warned = FALSE;
+ if (bufSize == 0) {
+ // get max size for MiG reply buffers
+ bufSize = _config_subsystem.maxsize;
+ if (_shared_dns_info_subsystem.maxsize > bufSize) {
+ bufSize = _shared_dns_info_subsystem.maxsize;
+ }
- if (!warned) {
- SCLog(_configd_verbose, LOG_NOTICE,
+ // check if our on-the-stack reply buffer will be big enough
+ if (bufSize > sizeof(bufReply_q)) {
+ SCLog(TRUE, LOG_NOTICE,
CFSTR("configdCallback(): buffer size should be increased > %d"),
_config_subsystem.maxsize);
- warned = TRUE;
}
+ }
+
+ if (bufSize > sizeof(bufReply_q)) {
bufReply = CFAllocatorAllocate(NULL, _config_subsystem.maxsize, 0);
}
boolean_t
server_active(mach_port_t *restart_service_port)
{
- mach_port_t bootstrap_port;
char *service_name;
kern_return_t status;
service_name = SCD_SERVER;
}
- /* Getting bootstrap server port */
- status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
- if (status != KERN_SUCCESS) {
- fprintf(stderr, "task_get_bootstrap_port(): %s\n",
- mach_error_string(status));
- exit (EX_UNAVAILABLE);
- }
-
/* Check "configd" server status */
status = bootstrap_check_in(bootstrap_port, service_name, restart_service_port);
switch (status) {
void
server_init(mach_port_t restart_service_port, Boolean enableRestart)
{
- mach_port_t bootstrap_port;
CFRunLoopSourceRef rls;
char *service_name;
mach_port_t service_port = restart_service_port;
kern_return_t status;
+ mach_port_t unpriv_bootstrap_port;
service_name = getenv("SCD_SERVER");
if (!service_name) {
service_name = SCD_SERVER;
}
- /* Getting bootstrap server port */
- status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
- if (status != KERN_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
- exit (EX_UNAVAILABLE);
- }
-
if (service_port == MACH_PORT_NULL) {
mach_port_t service_send_port;
FALSE, /* not onDemand == restart now */
&priv_bootstrap_port);
if (status != BOOTSTRAP_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_create_server() failed: status=%d"), status);
+ SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_create_server() failed: status=%d"), status);
exit (EX_UNAVAILABLE);
}
} else {
status = bootstrap_create_service(priv_bootstrap_port, service_name, &service_send_port);
if (status != BOOTSTRAP_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_create_service() failed: status=%d"), status);
+ SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_create_service() failed: status=%d"), status);
exit (EX_UNAVAILABLE);
}
status = bootstrap_check_in(priv_bootstrap_port, service_name, &service_port);
if (status != BOOTSTRAP_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_check_in() failed: status=%d"), status);
+ SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_check_in() failed: status=%d"), status);
exit (EX_UNAVAILABLE);
}
break;
SCLog(TRUE, LOG_ERR, CFSTR("'%s' server already active"), service_name);
exit (EX_UNAVAILABLE);
default :
- SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_check_in() failed: status=%d"), status);
+ SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_check_in() failed: status=%d"), status);
exit (EX_UNAVAILABLE);
}
}
/* we don't want to pass our priviledged bootstrap port along to any spawned helpers so... */
- status = bootstrap_unprivileged(priv_bootstrap_port, &bootstrap_port);
+ status = bootstrap_unprivileged(priv_bootstrap_port, &unpriv_bootstrap_port);
if (status != BOOTSTRAP_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_unprivileged() failed: status=%d"), status);
+ SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_unprivileged() failed: status=%d"), status);
exit (EX_UNAVAILABLE);
}
- status = task_set_bootstrap_port(mach_task_self(), bootstrap_port);
+ status = task_set_bootstrap_port(mach_task_self(), unpriv_bootstrap_port);
if (status != BOOTSTRAP_SUCCESS) {
- SCLog(TRUE, LOG_ERR, CFSTR("task_set_bootstrap_port(): %s"),
+ SCLog(TRUE, LOG_ERR, CFSTR("server_init task_set_bootstrap_port(): %s"),
mach_error_string(status));
exit (EX_UNAVAILABLE);
}
__private_extern__
-void
+int
server_shutdown()
{
char *service_name;
* logging thread lock is held.
*/
if ((priv_bootstrap_port == MACH_PORT_NULL) || (configd_port == NULL)) {
- return;
+ return EX_OK;
}
service_name = getenv("SCD_SERVER");
fprintf(stderr, "bootstrap_register() failed: status=%d\n", status);
fflush (stderr);
}
- exit (EX_UNAVAILABLE);
+ return EX_UNAVAILABLE;
}
- exit(EX_OK);
+ return EX_OK;
}
#include <sys/cdefs.h>
#include <mach/mach.h>
-
-#include <CoreFoundation/CFRunLoop.h>
-#include <CoreFoundation/CFMachPort.h>
+#include <CoreFoundation/CoreFoundation.h>
__BEGIN_DECLS
void server_init (mach_port_t service_port,
Boolean enableRestart);
-void server_shutdown ();
+int server_shutdown ();
void server_loop ();
kern_return_t _configopen (mach_port_t server,
xmlData_t nameRef,
mach_msg_type_number_t nameLen,
+ xmlData_t optionsRef,
+ mach_msg_type_number_t optionsLen,
mach_port_t *newServer,
int *sc_status);
+++ /dev/null
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
+++ /dev/null
-$$ Lines starting with $$ are not inserted into newly created files
-$$ The following substitutions are made:
-$$
-$$ $FILENAME$ e.g. foo.m
-$$ $FILENAMESANSEXTENSION$ e.g. foo
-$$ $DIRECTORY$ e.g. /tmp/MyNewApp
-$$ $PROJECTNAME$ e.g. MyNewApp
-$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj
-$$ $USERNAME$ e.g. mwagner
-$$ $DATE$ e.g. Jan-1-1994
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import "$FILENAMESANSEXTENSION$.h"
-
-@implementation $FILENAMESANSEXTENSION$
-
-@end
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * March 31, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-
-#include <unistd.h>
-
-#include "configd.h"
-#include "configd_server.h"
-#include "session.h"
-
-
-__private_extern__
-void
-pushNotifications()
-{
- const void **sessionsToNotify;
- CFIndex notifyCnt;
- int server;
- serverSessionRef theSession;
- SCDynamicStorePrivateRef storePrivate;
-
- if (needsNotification == NULL)
- return; /* if no sessions need to be kicked */
-
- notifyCnt = CFSetGetCount(needsNotification);
- sessionsToNotify = malloc(notifyCnt * sizeof(CFNumberRef));
- CFSetGetValues(needsNotification, sessionsToNotify);
- while (--notifyCnt >= 0) {
- (void) CFNumberGetValue(sessionsToNotify[notifyCnt],
- kCFNumberIntType,
- &server);
- theSession = getSession(server);
- storePrivate = (SCDynamicStorePrivateRef)theSession->store;
-
- /*
- * deliver notifications to client sessions
- */
- if ((storePrivate->notifyStatus == Using_NotifierInformViaMachPort) &&
- (storePrivate->notifyPort != MACH_PORT_NULL)) {
- mach_msg_empty_send_t msg;
- mach_msg_option_t options;
- kern_return_t status;
- /*
- * Post notification as mach message
- */
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("sending mach message notification."));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" port = %d"), storePrivate->notifyPort);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyPortIdentifier);
- }
- msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_remote_port = storePrivate->notifyPort;
- msg.header.msgh_local_port = MACH_PORT_NULL;
- msg.header.msgh_id = storePrivate->notifyPortIdentifier;
- options = MACH_SEND_TIMEOUT;
- status = mach_msg(&msg.header, /* msg */
- MACH_SEND_MSG|options, /* options */
- msg.header.msgh_size, /* send_size */
- 0, /* rcv_size */
- MACH_PORT_NULL, /* rcv_name */
- 0, /* timeout */
- MACH_PORT_NULL); /* notify */
- }
-
- if ((storePrivate->notifyStatus == Using_NotifierInformViaFD) &&
- (storePrivate->notifyFile >= 0)) {
- ssize_t written;
-
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" fd = %d"), storePrivate->notifyFile);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" msgid = %d"), storePrivate->notifyFileIdentifier);
- }
-
- written = write(storePrivate->notifyFile,
- &storePrivate->notifyFileIdentifier,
- sizeof(storePrivate->notifyFileIdentifier));
- if (written == -1) {
- if (errno == EWOULDBLOCK) {
- SCLog(_configd_verbose, LOG_DEBUG,
- CFSTR("sorry, only one outstanding notification per session."));
- } else {
- SCLog(_configd_verbose, LOG_DEBUG,
- CFSTR("could not send notification, write() failed: %s"),
- strerror(errno));
- storePrivate->notifyFile = -1;
- }
- } else if (written != sizeof(storePrivate->notifyFileIdentifier)) {
- SCLog(_configd_verbose, LOG_DEBUG,
- CFSTR("could not send notification, incomplete write()"));
- storePrivate->notifyFile = -1;
- }
- }
-
- if ((storePrivate->notifyStatus == Using_NotifierInformViaSignal) &&
- (storePrivate->notifySignal > 0)) {
- kern_return_t status;
- pid_t pid;
- /*
- * Post notification as signal
- */
- status = pid_for_task(storePrivate->notifySignalTask, &pid);
- if (status == KERN_SUCCESS) {
- if (_configd_verbose) {
- SCLog(TRUE, LOG_DEBUG, CFSTR("sending signal notification"));
- SCLog(TRUE, LOG_DEBUG, CFSTR(" pid = %d"), pid);
- SCLog(TRUE, LOG_DEBUG, CFSTR(" signal = %d"), storePrivate->notifySignal);
- }
- if (kill(pid, storePrivate->notifySignal) != 0) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno));
- status = KERN_FAILURE;
- }
- } else {
- mach_port_type_t pt;
-
- if ((mach_port_type(mach_task_self(), storePrivate->notifySignalTask, &pt) == KERN_SUCCESS) &&
- (pt & MACH_PORT_TYPE_DEAD_NAME)) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal, process died"));
- } else {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status));
- }
- }
-
- if (status != KERN_SUCCESS) {
- /* don't bother with any more attempts */
- (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask);
- storePrivate->notifySignal = 0;
- storePrivate->notifySignalTask = TASK_NULL;
- }
- }
- }
- free(sessionsToNotify);
-
- /*
- * this list of notifications have been posted, wait for some more.
- */
- CFRelease(needsNotification);
- needsNotification = NULL;
-
- return;
-}
+++ /dev/null
-/*
- * Copyright (c) 2000 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * March 31, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#ifndef _S_NOTIFY_H
-#define _S_NOTIFY_H
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-void pushNotifications ();
-
-__END_DECLS
-
-#endif /* !_S_NOTIFY_H */
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "configd.h"
#include "session.h"
-#include "notify.h"
__private_extern__
boolean_t
}
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("HELP!, Received notification: port=%d, msgh_id=%d"),
- Request->not_header.msgh_local_port,
- Request->not_header.msgh_id);
+ Request->not_header.msgh_local_port,
+ Request->not_header.msgh_id);
Reply->NDR = NDR_record;
Reply->RetCode = MIG_BAD_ID;
if (len > (CFIndex)sizeof(str_q))
str = CFAllocatorAllocate(NULL, len, 0);
if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern(): could not convert store key to C string"));
goto done;
}
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+ SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern regexec(): %s"), reErrBuf);
break;
}
}
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
*error = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingASCII);
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp(%s) failed: %s"), str, reErrBuf);
+#ifdef DEBUG
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("patternCompile regcomp(%s) failed: %s"), str, reErrBuf);
+#endif /* DEBUG */
ok = FALSE;
}
} else {
*error = CFRetain(CFSTR("could not convert pattern to regex string"));
+#ifdef DEBUG
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error);
+#endif /* DEBUG */
}
if (str != str_q) CFAllocatorDeallocate(NULL, str);
if (len > (CFIndex)sizeof(str_q))
str = CFAllocatorAllocate(NULL, len, 0);
if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+ SCLog(TRUE, LOG_DEBUG, CFSTR("addKeyForPattern(): could not convert store key to C string"));
goto done;
}
char reErrBuf[256];
(void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+ SCLog(TRUE, LOG_DEBUG, CFSTR("addKeyForPattern regexec(): %s"), reErrBuf);
break;
}
}
}
i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey);
- if (i == -1) {
+ if (i == kCFNotFound) {
/* if this key wasn't matched by this pattern */
return;
}
/*
* Modification History
*
+ * October 30, 2003 Allan Nathanson <ajn@apple.com>
+ * - add plugin "stop()" function support
+ *
* June 11, 2001 Allan Nathanson <ajn@apple.com>
* - start using CFBundle code
*
#include <sys/stat.h>
#include <sys/param.h>
#include <dirent.h>
+#include <sysexits.h>
#include <unistd.h>
#include <NSSystemDirectories.h>
#include "configd.h"
+#include "configd_server.h"
#include <SystemConfiguration/SCDPlugin.h>
void _SCDPluginExecInit();
#define BUNDLE_DIR_EXTENSION ".bundle"
-static CFMutableArrayRef allBundles = NULL;
-
-
-/* exception handling functions */
-typedef kern_return_t (*cer_func_t) (mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t codeCnt);
-
-typedef kern_return_t (*cer_state_func_t) (mach_port_t exception_port,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt);
-
-typedef kern_return_t (*cer_identity_func_t) (mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt);
-
-static cer_func_t catch_exception_raise_func = NULL;
-static cer_state_func_t catch_exception_raise_state_func = NULL;
-static cer_identity_func_t catch_exception_raise_identity_func = NULL;
-
-kern_return_t
-catch_exception_raise(mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t codeCnt)
-{
-
- if (catch_exception_raise_func == NULL) {
- /* The user hasn't defined catch_exception_raise in their binary */
- abort();
+typedef struct {
+ CFBundleRef bundle;
+ Boolean loaded;
+ Boolean builtin;
+ Boolean verbose;
+ SCDynamicStoreBundleLoadFunction load;
+ SCDynamicStoreBundleStartFunction start;
+ SCDynamicStoreBundlePrimeFunction prime;
+ SCDynamicStoreBundleStopFunction stop;
+} *bundleInfoRef;
+
+
+// all loaded bundles
+static CFMutableArrayRef allBundles = NULL;
+
+// exiting bundles
+static CFMutableDictionaryRef exiting = NULL;
+
+// plugin CFRunLoopRef
+static CFRunLoopRef plugin_runLoop = NULL;
+
+
+#ifdef ppc
+//extern SCDynamicStoreBundleLoadFunction load_ATconfig;
+//extern SCDynamicStoreBundleStopFunction stop_ATconfig;
+#endif /* ppc */
+extern SCDynamicStoreBundleLoadFunction load_IPMonitor;
+extern SCDynamicStoreBundlePrimeFunction prime_IPMonitor;
+extern SCDynamicStoreBundleLoadFunction load_InterfaceNamer;
+extern SCDynamicStoreBundleLoadFunction load_KernelEventMonitor;
+extern SCDynamicStoreBundlePrimeFunction prime_KernelEventMonitor;
+extern SCDynamicStoreBundleLoadFunction load_Kicker;
+extern SCDynamicStoreBundleLoadFunction load_LinkConfiguration;
+extern SCDynamicStoreBundleLoadFunction load_PreferencesMonitor;
+extern SCDynamicStoreBundlePrimeFunction prime_PreferencesMonitor;
+extern SCDynamicStoreBundleStopFunction stop_PreferencesMonitor;
+
+
+typedef struct {
+ const CFStringRef bundleID;
+ const void *load; // SCDynamicStoreBundleLoadFunction
+ const void *start; // SCDynamicStoreBundleStartFunction
+ const void *prime; // SCDynamicStoreBundlePrimeFunction
+ const void *stop; // SCDynamicStoreBundleStopFunction
+} builtin, *builtinRef;
+
+
+static const builtin builtin_plugins[] = {
+#ifdef ppc
+// {
+// CFSTR("com.apple.SystemConfiguration.ATconfig"),
+// &load_ATconfig,
+// NULL,
+// NULL,
+// &stop_ATconfig
+// },
+#endif /* ppc */
+ {
+ CFSTR("com.apple.SystemConfiguration.IPMonitor"),
+ &load_IPMonitor,
+ NULL,
+ &prime_IPMonitor,
+ NULL
+ },
+ {
+ CFSTR("com.apple.SystemConfiguration.InterfaceNamer"),
+ &load_InterfaceNamer,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ CFSTR("com.apple.SystemConfiguration.KernelEventMonitor"),
+ &load_KernelEventMonitor,
+ NULL,
+ &prime_KernelEventMonitor,
+ NULL
+ },
+ {
+ CFSTR("com.apple.SystemConfiguration.Kicker"),
+ &load_Kicker,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ CFSTR("com.apple.SystemConfiguration.LinkConfiguration"),
+ &load_LinkConfiguration,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ CFSTR("com.apple.SystemConfiguration.PreferencesMonitor"),
+ &load_PreferencesMonitor,
+ NULL,
+ &prime_PreferencesMonitor,
+ &stop_PreferencesMonitor
}
- return (*catch_exception_raise_func)(exception_port,
- thread,
- task,
- exception,
- code,
- codeCnt);
-}
+};
-kern_return_t
-catch_exception_raise_state(mach_port_t exception_port,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt)
+static void
+addBundle(CFBundleRef bundle)
{
- if (catch_exception_raise_state_func == 0) {
- /* The user hasn't defined catch_exception_raise_state in their binary */
- abort();
- }
- return (*catch_exception_raise_state_func)(exception_port,
- exception,
- code,
- codeCnt,
- flavor,
- old_state,
- old_stateCnt,
- new_state,
- new_stateCnt);
-}
+ CFDictionaryRef bundleDict;
+ bundleInfoRef bundleInfo;
+
+ bundleInfo = CFAllocatorAllocate(NULL, sizeof(*bundleInfo), 0);
+ bundleInfo->bundle = (CFBundleRef)CFRetain(bundle);
+ bundleInfo->loaded = FALSE;
+ bundleInfo->builtin = FALSE;
+ bundleInfo->verbose = FALSE;
+ bundleInfo->load = NULL;
+ bundleInfo->start = NULL;
+ bundleInfo->prime = NULL;
+ bundleInfo->stop = NULL;
+
+ bundleDict = CFBundleGetInfoDictionary(bundle);
+ if (isA_CFDictionary(bundleDict)) {
+ CFBooleanRef bVal;
+
+ bVal = CFDictionaryGetValue(bundleDict, kSCBundleIsBuiltinKey);
+ if (isA_CFBoolean(bVal) && CFBooleanGetValue(bVal)) {
+ bundleInfo->builtin = TRUE;
+ }
+ bVal = CFDictionaryGetValue(bundleDict, kSCBundleVerboseKey);
+ if (isA_CFBoolean(bVal) && CFBooleanGetValue(bVal)) {
+ bundleInfo->verbose = TRUE;
+ }
+ }
-kern_return_t
-catch_exception_raise_state_identity(mach_port_t exception_port,
- mach_port_t thread,
- mach_port_t task,
- exception_type_t exception,
- exception_data_t code,
- mach_msg_type_number_t codeCnt,
- int *flavor,
- thread_state_t old_state,
- mach_msg_type_number_t old_stateCnt,
- thread_state_t new_state,
- mach_msg_type_number_t *new_stateCnt)
-{
- if (catch_exception_raise_identity_func == 0) {
- /* The user hasn't defined catch_exception_raise_identify in their binary */
- abort();
- }
- return (*catch_exception_raise_identity_func)(exception_port,
- thread,
- task,
- exception,
- code,
- codeCnt,
- flavor,
- old_state,
- old_stateCnt,
- new_state,
- new_stateCnt);
+ CFArrayAppendValue(allBundles, bundleInfo);
+ return;
}
static CFStringRef
shortBundleIdentifier(CFStringRef bundleID)
{
- CFIndex len = CFStringGetLength(bundleID);
- CFRange range;
+ CFIndex len = CFStringGetLength(bundleID);
+ CFRange range;
CFStringRef shortID = NULL;
if (CFStringFindWithOptions(bundleID,
}
-static void
-loadBundle(const void *value, void *context) {
- CFBundleRef bundle = (CFBundleRef)value;
- CFStringRef bundleID = CFBundleGetIdentifier(bundle);
- Boolean bundleExclude = FALSE;
- Boolean bundleVerbose = FALSE;
- CFDictionaryRef dict;
- void *func;
- SCDynamicStoreBundleLoadFunction load;
- Boolean loaded;
- CFIndex *nLoaded = (CFIndex *)context;
-
- SCLog(TRUE, LOG_DEBUG, CFSTR("loading %@"), bundleID);
-
- bundleExclude = CFSetContainsValue(_plugins_exclude, bundleID);
- if (!bundleExclude) {
- CFStringRef shortID = shortBundleIdentifier(bundleID);
+static void *
+getBundleSymbol(CFBundleRef bundle, CFStringRef functionName, CFStringRef shortID)
+{
+ void *func;
- if (shortID) {
- bundleExclude = CFSetContainsValue(_plugins_exclude, shortID);
- CFRelease(shortID);
- }
+ // search for load(), start(), prime(), stop(), ...
+ func = CFBundleGetFunctionPointerForName(bundle, functionName);
+ if (func != NULL) {
+ return func;
}
- if (bundleExclude) {
- SCLog(TRUE,
- LOG_DEBUG,
- CFSTR("%@ load skipped"),
- bundleID);
- return;
+ if (shortID != NULL) {
+ CFStringRef altFunctionName;
+
+ // search for load_XXX(), ...
+ altFunctionName = CFStringCreateWithFormat(NULL,
+ NULL,
+ CFSTR("%@_%@"),
+ functionName,
+ shortID);
+ func = CFBundleGetFunctionPointerForName(bundle, altFunctionName);
+ CFRelease(altFunctionName);
}
- loaded = CFBundleLoadExecutable(bundle);
- if (!loaded) {
- SCLog(TRUE,
- LOG_NOTICE,
- CFSTR("%@ load failed"),
- bundleID);
- return;
- }
+ return func;
+}
- if (!CFBundleIsExecutableLoaded(bundle)) {
- SCLog(TRUE,
- LOG_NOTICE,
- CFSTR("%@ executable not loaded"),
- bundleID);
+
+static void
+loadBundle(const void *value, void *context) {
+ CFStringRef bundleID;
+ bundleInfoRef bundleInfo = (bundleInfoRef)value;
+ Boolean bundleExclude;
+ CFIndex *nLoaded = (CFIndex *)context;
+ CFStringRef shortID;
+
+ bundleID = CFBundleGetIdentifier(bundleInfo->bundle);
+ if (bundleID == NULL) {
+ // sorry, no bundles without a bundle identifier
+ SCLog(TRUE, LOG_DEBUG, CFSTR("skipped %@"), bundleInfo->bundle);
return;
}
- /* bump the count of loaded bundles */
- *nLoaded = *nLoaded + 1;
+ shortID = shortBundleIdentifier(bundleID);
- /* identify any exception handling functions */
-
- func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise"));
- if (func) {
- catch_exception_raise_func = func;
+ bundleExclude = CFSetContainsValue(_plugins_exclude, bundleID);
+ if (bundleExclude) {
+ if (shortID != NULL) {
+ bundleExclude = CFSetContainsValue(_plugins_exclude, shortID);
+ }
}
- func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise_state"));
- if (func) {
- catch_exception_raise_state_func = func;
+ if (bundleExclude) {
+ // sorry, this bundle has been excluded
+ SCLog(TRUE, LOG_DEBUG, CFSTR("excluded %@"), bundleID);
+ goto done;
}
- func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise_identity"));
- if (func) {
- catch_exception_raise_identity_func = func;
+ if (!bundleInfo->verbose) {
+ bundleInfo->verbose = CFSetContainsValue(_plugins_verbose, bundleID);
+ if (!bundleInfo->verbose) {
+ if (shortID != NULL) {
+ bundleInfo->verbose = CFSetContainsValue(_plugins_verbose, shortID);
+ }
+ }
}
- /* if defined, call the bundles load() function */
+ if (bundleInfo->builtin) {
+ int i;
- load = CFBundleGetFunctionPointerForName(bundle, CFSTR("load"));
- if (!load) {
- return;
- }
+ SCLog(TRUE, LOG_DEBUG, CFSTR("adding %@"), bundleID);
- bundleVerbose = CFSetContainsValue(_plugins_verbose, bundleID);
- if (!bundleVerbose) {
- CFStringRef shortID = shortBundleIdentifier(bundleID);
+ for (i = 0; i < sizeof(builtin_plugins)/sizeof(builtin_plugins[0]); i++) {
+ if (CFEqual(bundleID, builtin_plugins[i].bundleID)) {
+ bundleInfo->load = builtin_plugins[i].load;
+ bundleInfo->start = builtin_plugins[i].start;
+ bundleInfo->prime = builtin_plugins[i].prime;
+ bundleInfo->stop = builtin_plugins[i].stop;
+ break;
+ }
+ }
+ } else {
+ SCLog(TRUE, LOG_DEBUG, CFSTR("loading %@"), bundleID);
- if (shortID) {
- bundleVerbose = CFSetContainsValue(_plugins_verbose, shortID);
- CFRelease(shortID);
+ if (!CFBundleLoadExecutable(bundleInfo->bundle)) {
+ SCLog(TRUE, LOG_NOTICE, CFSTR("%@ load failed"), bundleID);
+ goto done;
}
+
+ // get bundle entry points
+ bundleInfo->load = getBundleSymbol(bundleInfo->bundle, CFSTR("load" ), shortID);
+ bundleInfo->start = getBundleSymbol(bundleInfo->bundle, CFSTR("start"), shortID);
+ bundleInfo->prime = getBundleSymbol(bundleInfo->bundle, CFSTR("prime"), shortID);
+ bundleInfo->stop = getBundleSymbol(bundleInfo->bundle, CFSTR("stop" ), shortID);
}
- if (!bundleVerbose) {
- dict = CFBundleGetInfoDictionary(bundle);
- if (isA_CFDictionary(dict)) {
- CFBooleanRef bVal;
+ /* mark this bundle as having been loaded */
+ bundleInfo->loaded = TRUE;
- bVal = CFDictionaryGetValue(dict, kSCBundleVerbose);
- if (isA_CFBoolean(bVal) && CFBooleanGetValue(bVal)) {
- bundleVerbose = TRUE;
- }
- }
- }
+ /* bump the count of loaded bundles */
+ *nLoaded = *nLoaded + 1;
+
+ done :
- (*load)(bundle, bundleVerbose);
+ if (shortID != NULL) CFRelease(shortID);
return;
}
-static void
-startBundle(const void *value, void *context) {
- CFBundleRef bundle = (CFBundleRef)value;
- CFURLRef bundleURL;
- char bundleName[MAXNAMLEN + 1];
- char bundlePath[MAXPATHLEN];
- char *cp;
- CFDictionaryRef dict;
- int len;
- Boolean ok;
- SCDynamicStoreBundleStartFunction start;
+void
+callLoadFunction(const void *value, void *context) {
+ bundleInfoRef bundleInfo = (bundleInfoRef)value;
- if (!CFBundleIsExecutableLoaded(bundle)) {
+ if (!bundleInfo->loaded) {
return;
}
- start = CFBundleGetFunctionPointerForName(bundle, CFSTR("start"));
- if (!start) {
+ if (bundleInfo->load == NULL) {
+ // if no load() function
+ return;
+ }
+
+ (*bundleInfo->load)(bundleInfo->bundle, bundleInfo->verbose);
+ return;
+}
+
+
+void
+callStartFunction(const void *value, void *context) {
+ bundleInfoRef bundleInfo = (bundleInfoRef)value;
+ CFURLRef bundleURL;
+ char bundleName[MAXNAMLEN + 1];
+ char bundlePath[MAXPATHLEN];
+ char *cp;
+ int len;
+ Boolean ok;
+
+ if (!bundleInfo->loaded) {
return;
}
- dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle));
- if (!dict) {
+ if (bundleInfo->start == NULL) {
+ // if no start() function
return;
}
- bundleURL = CFBundleCopyBundleURL(bundle);
- if (!bundleURL) {
+ bundleURL = CFBundleCopyBundleURL(bundleInfo->bundle);
+ if (bundleURL == NULL) {
return;
}
bundleName[0] = '\0';
(void) strncat(bundleName, cp, len);
- (*start)(bundleName, bundlePath);
+ (*bundleInfo->start)(bundleName, bundlePath);
+ return;
+}
+
+
+void
+callPrimeFunction(const void *value, void *context) {
+ bundleInfoRef bundleInfo = (bundleInfoRef)value;
+
+ if (!bundleInfo->loaded) {
+ return;
+ }
+
+ if (bundleInfo->prime == NULL) {
+ // if no prime() function
+ return;
+ }
+
+ (*bundleInfo->prime)();
return;
}
static void
-primeBundle(const void *value, void *context) {
- CFBundleRef bundle = (CFBundleRef)value;
- SCDynamicStoreBundlePrimeFunction prime;
+stopComplete(void *info)
+{
+ CFBundleRef bundle = (CFBundleRef)info;
+ CFStringRef bundleID = CFBundleGetIdentifier(bundle);
+ CFRunLoopSourceRef stopRls;
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("** %@ complete (%f)"), bundleID, CFAbsoluteTimeGetCurrent());
+
+ stopRls = (CFRunLoopSourceRef)CFDictionaryGetValue(exiting, bundle);
+ CFRunLoopSourceInvalidate(stopRls);
+
+ CFDictionaryRemoveValue(exiting, bundle);
+
+ if (CFDictionaryGetCount(exiting) == 0) {
+ int status;
+
+ // if all of the plugins are happy
+ status = server_shutdown();
+ SCLog(TRUE, LOG_DEBUG, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
+ exit (status);
+ }
- if (!CFBundleIsExecutableLoaded(bundle)) {
+ return;
+}
+
+
+static void
+stopDelayed(CFRunLoopTimerRef timer, void *info)
+{
+ const void **keys;
+ CFIndex i;
+ CFIndex n;
+ int status;
+
+ SCLog(TRUE, LOG_ERR, CFSTR("server shutdown was delayed, unresponsive plugins:"));
+
+ /*
+ * we've asked our plugins to shutdown but someone
+ * isn't listening.
+ */
+ n = CFDictionaryGetCount(exiting);
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ CFDictionaryGetKeysAndValues(exiting, keys, NULL);
+ for (i = 0; i < n; i++) {
+ CFBundleRef bundle;
+ CFStringRef bundleID;
+
+ bundle = (CFBundleRef)keys[i];
+ bundleID = CFBundleGetIdentifier(bundle);
+ SCLog(TRUE, LOG_ERR, CFSTR("** %@"), bundleID);
+ }
+ CFAllocatorDeallocate(NULL, keys);
+
+ status = server_shutdown();
+ exit (status);
+}
+
+static void
+stopBundle(const void *value, void *context) {
+ bundleInfoRef bundleInfo = (bundleInfoRef)value;
+ CFRunLoopSourceRef stopRls;
+ CFRunLoopSourceContext stopContext = { 0 // version
+ , bundleInfo->bundle // info
+ , CFRetain // retain
+ , CFRelease // release
+ , CFCopyDescription // copyDescription
+ , CFEqual // equal
+ , CFHash // hash
+ , NULL // schedule
+ , NULL // cancel
+ , stopComplete // perform
+ };
+
+ if (!bundleInfo->loaded) {
return;
}
- prime = CFBundleGetFunctionPointerForName(bundle, CFSTR("prime"));
- if (!prime) {
+ if (bundleInfo->stop == NULL) {
+ // if no stop() function
return;
}
- (*prime)();
+ stopRls = CFRunLoopSourceCreate(NULL, 0, &stopContext);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), stopRls, kCFRunLoopDefaultMode);
+ CFDictionaryAddValue(exiting, bundleInfo->bundle, stopRls);
+ CFRelease(stopRls);
+
+ (*bundleInfo->stop)(stopRls);
+
+ return;
+}
+
+
+static void
+stopBundles()
+{
+ /*
+ * If defined, call each bundles stop() function. This function is
+ * called when configd has been asked to shut down (via a SIGTERM). The
+ * function should signal the provided run loop source when it is "ready"
+ * for the shut down to proceeed.
+ */
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle stop() functions"));
+ CFArrayApplyFunction(allBundles,
+ CFRangeMake(0, CFArrayGetCount(allBundles)),
+ stopBundle,
+ NULL);
+
+ if (CFDictionaryGetCount(exiting) == 0) {
+ int status;
+
+ // if all of the plugins are happy
+ status = server_shutdown();
+ SCLog(TRUE, LOG_DEBUG, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
+ exit (status);
+ } else {
+ CFRunLoopTimerRef timer;
+
+ /* sorry, we're not going to wait longer than 20 seconds */
+ timer = CFRunLoopTimerCreate(NULL, /* allocator */
+ CFAbsoluteTimeGetCurrent() + 20.0, /* fireDate (in 20 seconds) */
+ 0.0, /* interval (== one-shot) */
+ 0, /* flags */
+ 0, /* order */
+ stopDelayed, /* callout */
+ NULL); /* context */
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
+ CFRelease(timer);
+ }
+
return;
}
+__private_extern__
+Boolean
+plugin_term(int *status)
+{
+ CFRunLoopSourceRef stopRls;
+ CFRunLoopSourceContext stopContext = { 0 // version
+ , NULL // info
+ , NULL // retain
+ , NULL // release
+ , NULL // copyDescription
+ , NULL // equal
+ , NULL // hash
+ , NULL // schedule
+ , NULL // cancel
+ , stopBundles // perform
+ };
+
+ if (plugin_runLoop == NULL) {
+ // if no plugins
+ *status = EX_OK;
+ return FALSE; // don't delay shutdown
+ }
+
+ if (exiting != NULL) {
+ // if shutdown already active
+ return TRUE;
+ }
+
+ SCLog(TRUE, LOG_DEBUG, CFSTR("starting server shutdown (%f)"), CFAbsoluteTimeGetCurrent());
+
+ exiting = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ stopRls = CFRunLoopSourceCreate(NULL, 0, &stopContext);
+ CFRunLoopAddSource(plugin_runLoop, stopRls, kCFRunLoopDefaultMode);
+ CFRunLoopSourceSignal(stopRls);
+ CFRelease(stopRls);
+ CFRunLoopWakeUp(plugin_runLoop);
+
+ return TRUE;
+}
+
+
#ifdef DEBUG
static void
static void
sortBundles(CFMutableArrayRef orig)
{
- CFMutableArrayRef new;
+ CFMutableArrayRef new;
- new = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ new = CFArrayCreateMutable(NULL, 0, NULL);
while (CFArrayGetCount(orig) > 0) {
int i;
Boolean inserted = FALSE;
int nOrig = CFArrayGetCount(orig);
for (i = 0; i < nOrig; i++) {
- CFBundleRef bundle1 = (CFBundleRef)CFArrayGetValueAtIndex(orig, i);
- CFStringRef bundleID1 = CFBundleGetIdentifier(bundle1);
+ bundleInfoRef bundleInfo1 = (bundleInfoRef)CFArrayGetValueAtIndex(orig, i);
+ CFStringRef bundleID1 = CFBundleGetIdentifier(bundleInfo1->bundle);
int count;
CFDictionaryRef dict;
int j;
int nRequires;
CFArrayRef requires = NULL;
- dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle1));
+ dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundleInfo1->bundle));
if (dict) {
- requires = CFDictionaryGetValue(dict, kSCBundleRequires);
+ requires = CFDictionaryGetValue(dict, kSCBundleRequiresKey);
requires = isA_CFArray(requires);
}
if (bundleID1 == NULL || requires == NULL) {
- CFArrayInsertValueAtIndex(new, 0, bundle1);
+ CFArrayInsertValueAtIndex(new, 0, bundleInfo1);
CFArrayRemoveValueAtIndex(orig, i);
inserted = TRUE;
break;
nNew = CFArrayGetCount(new);
for (k = 0; k < nNew; k++) {
- CFBundleRef bundle2 = (CFBundleRef)CFArrayGetValueAtIndex(new, k);
- CFStringRef bundleID2 = CFBundleGetIdentifier(bundle2);
+ bundleInfoRef bundleInfo2 = (bundleInfoRef)CFArrayGetValueAtIndex(new, k);
+ CFStringRef bundleID2 = CFBundleGetIdentifier(bundleInfo2->bundle);
if (bundleID2 && CFEqual(bundleID2, r)) {
count--;
}
if (count == 0) {
/* all dependencies are met, append */
- CFArrayAppendValue(new, bundle1);
+ CFArrayAppendValue(new, bundleInfo1);
CFArrayRemoveValueAtIndex(orig, i);
inserted = TRUE;
break;
void *
plugin_exec(void *arg)
{
- CFIndex nLoaded = 0;
+ CFIndex nLoaded = 0;
/* keep track of bundles */
- allBundles = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ allBundles = CFArrayCreateMutable(NULL, 0, NULL);
/* allow plug-ins to exec child/helper processes */
_SCDPluginExecInit();
* identify and load all bundles
*/
state = NSStartSearchPathEnumeration(NSLibraryDirectory,
- NSLocalDomainMask|NSSystemDomainMask);
+ NSSystemDomainMask);
while ((state = NSGetNextSearchPathEnumeration(state, path))) {
CFArrayRef bundles;
CFURLRef url;
bundles = CFBundleCreateBundlesFromDirectory(NULL, url, CFSTR(".bundle"));
CFRelease(url);
- if (bundles) {
- CFArrayAppendArray(allBundles,
- bundles,
- CFRangeMake(0, CFArrayGetCount(bundles)));
+ if (bundles != NULL) {
+ CFIndex i;
+ CFIndex n;
+
+ n = CFArrayGetCount(bundles);
+ for (i = 0; i < n; i++) {
+ CFBundleRef bundle;
+
+ bundle = (CFBundleRef)CFArrayGetValueAtIndex(bundles, i);
+ addBundle(bundle);
+ }
CFRelease(bundles);
}
}
strlen((char *)arg),
TRUE);
bundle = CFBundleCreate(NULL, url);
- if (bundle) {
- CFArrayAppendValue(allBundles, bundle);
+ if (bundle != NULL) {
+ addBundle(bundle);
CFRelease(bundle);
}
CFRelease(url);
}
/*
- * load each bundle and, if defined, call its load() function. This
- * function (or the start() function) should initialize any variables,
- * open any sessions with "configd", and register any needed notifications.
+ * load each bundle.
+ */
+ SCLog(_configd_verbose, LOG_DEBUG, CFSTR("loading bundles"));
+ CFArrayApplyFunction(allBundles,
+ CFRangeMake(0, CFArrayGetCount(allBundles)),
+ loadBundle,
+ &nLoaded);
+
+ /*
+ * If defined, call each bundles load() function. This function (or
+ * the start() function) should initialize any variables, open any
+ * sessions with "configd", and register any needed notifications.
*
* Note: Establishing initial information in the store should be
* deferred until the prime() initialization function so that
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle load() functions"));
CFArrayApplyFunction(allBundles,
CFRangeMake(0, CFArrayGetCount(allBundles)),
- loadBundle,
- &nLoaded);
+ callLoadFunction,
+ NULL);
/*
* If defined, call each bundles start() function. This function is
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle start() functions"));
CFArrayApplyFunction(allBundles,
CFRangeMake(0, CFArrayGetCount(allBundles)),
- startBundle,
+ callStartFunction,
NULL);
/*
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle prime() functions"));
CFArrayApplyFunction(allBundles,
CFRangeMake(0, CFArrayGetCount(allBundles)),
- primeBundle,
+ callPrimeFunction,
NULL);
#ifdef DEBUG
* private thread.
*/
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("starting plugin CFRunLoop"));
+ plugin_runLoop = CFRunLoopGetCurrent();
CFRunLoopRun();
- SCLog(_configd_verbose, LOG_INFO, CFSTR("what, no more work for the \"configd\" bundles?"));
+
+ SCLog(_configd_verbose, LOG_INFO, CFSTR("No more work for the \"configd\" plugins"));
+ plugin_runLoop = NULL;
return NULL;
}
void plugin_init ();
void plugin_exec (void *arg);
+Boolean plugin_term (int *status);
__END_DECLS
int i;
if (server == MACH_PORT_NULL) {
- SCLog(_configd_verbose, LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?"));
+ SCLog(TRUE, LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?"));
return NULL;
}
if (n < 0) {
/* no empty slots, add one to the list */
n = nSessions++;
- sessions = realloc(sessions, ((nSessions) * sizeof(serverSessionRef)));
+ sessions = reallocf(sessions, ((nSessions) * sizeof(serverSessionRef)));
}
}
- SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Allocating new session for port %d"), CFMachPortGetPort(server));
+ // allocate a new session for this server
sessions[n] = malloc(sizeof(serverSession));
sessions[n]->key = CFMachPortGetPort(server);
sessions[n]->serverPort = server;
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 39;
+ objects = {
+ 150607BD075A00A200B147BA = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCSchemaDefinitions.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 150607DE075A00A300B147BA = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCSchemaDefinitions.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15060818075A00A300B147BA = {
+ fileRef = 150607BD075A00A200B147BA;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1506081A075A00A300B147BA = {
+ fileRef = 150607DE075A00A300B147BA;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ 1508E39F07552B6A0062B350 = {
+ fileRef = 159D53C707528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1508E3A007552B6B0062B350 = {
+ fileRef = 159D53C507528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1508E3A107552B720062B350 = {
+ fileRef = 159D53CA07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1514D76D05C08A5F00757DC9 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = config_types.h;
+ path = SystemConfiguration.fproj/config_types.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1514D77D05C08AB700757DC9 = {
+ children = (
+ 15CB690505C0722A0099E85F,
+ );
+ isa = PBXGroup;
+ name = "Initial Preferences";
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 151BDA2B05D9E28B00657BC7 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = SCPreferencesPathKey.h;
+ path = SystemConfiguration.fproj/SCPreferencesPathKey.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ 151BDA5D05D9E2ED00657BC7 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = SCPreferencesPathKey.c;
+ path = SystemConfiguration.fproj/SCPreferencesPathKey.c;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1521FC5C060F296A003B28F5 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = dnsinfo_create.c;
+ path = dnsinfo/dnsinfo_create.c;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ 1523F6EE075A36210066F0B2 = {
+ fileRef = 15DAD6C807591A1A0084A6ED;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1523F6F1075A36F70066F0B2 = {
+ fileRef = 15DAD6C807591A1A0084A6ED;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1523F6F2075A37050066F0B2 = {
+ fileRef = 15DAD6C807591A1A0084A6ED;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1523F710075A371D0066F0B2 = {
+ fileRef = 15DAD6C807591A1A0084A6ED;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1523F715075A376B0066F0B2 = {
+ fileRef = 15DAD5EE075913CE0084A6ED;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1523F719075A37C70066F0B2 = {
+ fileRef = 15DAD5EE075913CE0084A6ED;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 152CEED0070CF6640050F23C = {
+ isa = PBXFileReference;
+ lastKnownFileType = "compiled.mach-o.dylib";
+ name = libedit.dylib;
+ path = /usr/lib/libedit.2.dylib;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 1532629006281C9D00B1C10C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dnsinfo_create.h;
+ path = dnsinfo/dnsinfo_create.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 154361E00752C81800A8EC6C = {
+ fileRef = 159D53AB07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1543636A0752D03C00A8EC6C = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = IOKit.framework;
+ path = /System/Library/Frameworks/IOKit.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 1543636B0752D03C00A8EC6C = {
+ fileRef = 1543636A0752D03C00A8EC6C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15481BF7075A2B3900B32F56 = {
+ buildPhases = (
+ 15481C14075A2B7300B32F56,
+ );
+ buildSettings = {
+ INSTALLHDRS_SCRIPT_PHASE = YES;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = genSCPreferences;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wall -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXToolTarget;
+ name = Schema;
+ productInstallPath = /usr/local/bin;
+ productName = Schema;
+ productReference = 15481BF8075A2B3900B32F56;
+ };
+ 15481BF8075A2B3900B32F56 = {
+ explicitFileType = "compiled.mach-o.executable";
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = genSCPreferences;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15481C14075A2B7300B32F56 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ SystemConfiguration.fproj/genSCPreferences.c,
+ );
+ isa = PBXShellScriptBuildPhase;
+ outputPaths = (
+ "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h",
+ "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "cc -o ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} ${SRCROOT}/SystemConfiguration.fproj/genSCPreferences.c\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} header > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} cfile > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c\nexit 0";
+ };
+ 154CF3F307E1EA4D00D8302E = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferencesGetSpecificPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 154CF3F407E1EA4D00D8302E = {
+ fileRef = 154CF3F307E1EA4D00D8302E;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 155847430754FDCD0046C2E9 = {
+ buildPhases = (
+ 155847460754FDCD0046C2E9,
+ 155847540754FDCD0046C2E9,
+ 155847620754FDCD0046C2E9,
+ 155847670754FDCD0046C2E9,
+ 155847680754FDCD0046C2E9,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ CURRENT_PROJECT_VERSION = 130;
+ DEAD_CODE_STRIPPING = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/sbin;
+ LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = scutil;
+ STRIPFLAGS = "-S";
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = scutil;
+ productInstallPath = /usr/sbin;
+ productName = "scutil (Tool)";
+ productReference = 1558476A0754FDCD0046C2E9;
+ productType = "com.apple.product-type.tool";
+ };
+ 155847460754FDCD0046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ 155847470754FDCD0046C2E9,
+ 155847480754FDCD0046C2E9,
+ 155847490754FDCD0046C2E9,
+ 1558474A0754FDCD0046C2E9,
+ 1558474B0754FDCD0046C2E9,
+ 1558474C0754FDCD0046C2E9,
+ 1558474D0754FDCD0046C2E9,
+ 1558474E0754FDCD0046C2E9,
+ 1558474F0754FDCD0046C2E9,
+ 155847500754FDCD0046C2E9,
+ 155847510754FDCD0046C2E9,
+ 155847520754FDCD0046C2E9,
+ 155847530754FDCD0046C2E9,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 155847470754FDCD0046C2E9 = {
+ fileRef = 15CB6A4305C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847480754FDCD0046C2E9 = {
+ fileRef = 15CB6A4505C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847490754FDCD0046C2E9 = {
+ fileRef = 15CB6A4705C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558474A0754FDCD0046C2E9 = {
+ fileRef = 15CB6A4905C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558474B0754FDCD0046C2E9 = {
+ fileRef = 15CB6A4B05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558474C0754FDCD0046C2E9 = {
+ fileRef = 15CB6A4D05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558474D0754FDCD0046C2E9 = {
+ fileRef = 15CB6A4F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558474E0754FDCD0046C2E9 = {
+ fileRef = 15CB6A5105C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558474F0754FDCD0046C2E9 = {
+ fileRef = 15A509A406C2518F001F0AB7;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847500754FDCD0046C2E9 = {
+ fileRef = 15DC34680711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847510754FDCD0046C2E9 = {
+ fileRef = 15DC346A0711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847520754FDCD0046C2E9 = {
+ fileRef = 15DC346C0711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847530754FDCD0046C2E9 = {
+ fileRef = 15DC346E0711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847540754FDCD0046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ 155847550754FDCD0046C2E9,
+ 155847560754FDCD0046C2E9,
+ 155847570754FDCD0046C2E9,
+ 155847580754FDCD0046C2E9,
+ 155847590754FDCD0046C2E9,
+ 1558475A0754FDCD0046C2E9,
+ 1558475B0754FDCD0046C2E9,
+ 1558475C0754FDCD0046C2E9,
+ 1558475D0754FDCD0046C2E9,
+ 1558475E0754FDCD0046C2E9,
+ 1558475F0754FDCD0046C2E9,
+ 155847600754FDCD0046C2E9,
+ 155847610754FDCD0046C2E9,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 155847550754FDCD0046C2E9 = {
+ fileRef = 15CB6A5405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 155847560754FDCD0046C2E9 = {
+ fileRef = 15CB6A5605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 155847570754FDCD0046C2E9 = {
+ fileRef = 15CB6A5805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 155847580754FDCD0046C2E9 = {
+ fileRef = 15CB6A5A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 155847590754FDCD0046C2E9 = {
+ fileRef = 15CB6A5C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 1558475A0754FDCD0046C2E9 = {
+ fileRef = 15CB6A5E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 1558475B0754FDCD0046C2E9 = {
+ fileRef = 15CB6A6005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 1558475C0754FDCD0046C2E9 = {
+ fileRef = 15CB6A6205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 1558475D0754FDCD0046C2E9 = {
+ fileRef = 15A509A306C2518F001F0AB7;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558475E0754FDCD0046C2E9 = {
+ fileRef = 15DC34670711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558475F0754FDCD0046C2E9 = {
+ fileRef = 15DC34690711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847600754FDCD0046C2E9 = {
+ fileRef = 15DC346B0711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847610754FDCD0046C2E9 = {
+ fileRef = 15DC346D0711D49400A3311C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847620754FDCD0046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ 155847640754FDCD0046C2E9,
+ 1523F710075A371D0066F0B2,
+ 1523F719075A37C70066F0B2,
+ 155847660754FDCD0046C2E9,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 155847640754FDCD0046C2E9 = {
+ fileRef = 15CB6A6F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847660754FDCD0046C2E9 = {
+ fileRef = 152CEED0070CF6640050F23C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 155847670754FDCD0046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 155847680754FDCD0046C2E9 = {
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8;
+ dstSubfolderSpec = 0;
+ files = (
+ 155847690754FDCD0046C2E9,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 155847690754FDCD0046C2E9 = {
+ fileRef = 15CB6A6A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558476A0754FDCD0046C2E9 = {
+ explicitFileType = "compiled.mach-o.executable";
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = scutil;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 155847FA07550D210046C2E9 = {
+ buildPhases = (
+ );
+ buildSettings = {
+ DEAD_CODE_STRIPPING = YES;
+ PRODUCT_NAME = configd_executables;
+ STRIPFLAGS = "-S";
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ 1558480607550D470046C2E9,
+ 1558480807550D470046C2E9,
+ 1558480A07550D470046C2E9,
+ );
+ isa = PBXAggregateTarget;
+ name = configd_executables;
+ productName = configd_executables;
+ };
+ 1558480507550D470046C2E9 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D549F07529FFF004F8947;
+ remoteInfo = configd;
+ };
+ 1558480607550D470046C2E9 = {
+ isa = PBXTargetDependency;
+ target = 159D549F07529FFF004F8947;
+ targetProxy = 1558480507550D470046C2E9;
+ };
+ 1558480707550D470046C2E9 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15CB6A2705C0722B0099E85F;
+ remoteInfo = scselect;
+ };
+ 1558480807550D470046C2E9 = {
+ isa = PBXTargetDependency;
+ target = 1558481207550EC10046C2E9;
+ targetProxy = 1558480707550D470046C2E9;
+ };
+ 1558480907550D470046C2E9 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 155847430754FDCD0046C2E9;
+ remoteInfo = scutil;
+ };
+ 1558480A07550D470046C2E9 = {
+ isa = PBXTargetDependency;
+ target = 155847430754FDCD0046C2E9;
+ targetProxy = 1558480907550D470046C2E9;
+ };
+ 1558480E07550DD00046C2E9 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 155847FA07550D210046C2E9;
+ remoteInfo = configd_executables;
+ };
+ 1558480F07550DD00046C2E9 = {
+ isa = PBXTargetDependency;
+ target = 155847FA07550D210046C2E9;
+ targetProxy = 1558480E07550DD00046C2E9;
+ };
+ 1558481207550EC10046C2E9 = {
+ buildPhases = (
+ 1558481407550EC10046C2E9,
+ 1558481507550EC10046C2E9,
+ 1558481707550EC10046C2E9,
+ 1558481A07550EC10046C2E9,
+ 1558481B07550EC10046C2E9,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ CURRENT_PROJECT_VERSION = 130;
+ DEAD_CODE_STRIPPING = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
+ INSTALL_PATH = /usr/sbin;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = scselect;
+ STRIPFLAGS = "-S";
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = scselect;
+ productInstallPath = /usr/sbin;
+ productName = "scselect (Tool)";
+ productReference = 1558481D07550EC10046C2E9;
+ productType = "com.apple.product-type.tool";
+ };
+ 1558481407550EC10046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1558481507550EC10046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ 1558481607550EC10046C2E9,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1558481607550EC10046C2E9 = {
+ fileRef = 15CB6A2E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 1558481707550EC10046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ 1558481907550EC10046C2E9,
+ 1523F6F2075A37050066F0B2,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1558481907550EC10046C2E9 = {
+ fileRef = 15CB6A6F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558481A07550EC10046C2E9 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1558481B07550EC10046C2E9 = {
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man8;
+ dstSubfolderSpec = 0;
+ files = (
+ 1558481C07550EC10046C2E9,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1558481C07550EC10046C2E9 = {
+ fileRef = 15CB6A3605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1558481D07550EC10046C2E9 = {
+ explicitFileType = "compiled.mach-o.executable";
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = scselect;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 156BD6BB07E0DFA9008698FF = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferencesSetSpecificPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 156BD6BC07E0DFA9008698FF = {
+ fileRef = 156BD6BB07E0DFA9008698FF;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 1577252F06EFB96700D7B52B = {
+ fileEncoding = 10;
+ isa = PBXFileReference;
+ lastKnownFileType = text.plist.strings;
+ name = English;
+ path = English.lproj/NetworkInterface.strings;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 1577253606EFBF3100D7B52B = {
+ children = (
+ 1577252F06EFB96700D7B52B,
+ );
+ isa = PBXVariantGroup;
+ name = NetworkInterface.strings;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 157BB8AE075924360025DA7A = {
+ buildPhases = (
+ );
+ buildSettings = {
+ PRODUCT_NAME = Frameworks;
+ WARNING_CFLAGS = "-Wmost -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ 157BB8C2075924470025DA7A,
+ 157BB8C0075924460025DA7A,
+ );
+ isa = PBXAggregateTarget;
+ name = configd_base;
+ productName = Frameworks;
+ };
+ 157BB8BF075924460025DA7A = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15DAD63F07591A1A0084A6ED;
+ remoteInfo = SystemConfiguration.framework;
+ };
+ 157BB8C0075924460025DA7A = {
+ isa = PBXTargetDependency;
+ target = 15DAD63F07591A1A0084A6ED;
+ targetProxy = 157BB8BF075924460025DA7A;
+ };
+ 157BB8C1075924470025DA7A = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15DAD5DF075913CE0084A6ED;
+ remoteInfo = DNSConfiguration;
+ };
+ 157BB8C2075924470025DA7A = {
+ isa = PBXTargetDependency;
+ target = 15DAD5DF075913CE0084A6ED;
+ targetProxy = 157BB8C1075924470025DA7A;
+ };
+ 157BB8C30759244B0025DA7A = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 157BB8AE075924360025DA7A;
+ remoteInfo = Frameworks;
+ };
+ 157BB8C40759244B0025DA7A = {
+ isa = PBXTargetDependency;
+ target = 157BB8AE075924360025DA7A;
+ targetProxy = 157BB8C30759244B0025DA7A;
+ };
+ 15828AE30753B5F900AD4710 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15828AE60753B5F900AD4710 = {
+ buildPhases = (
+ 15828AE30753B5F900AD4710,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/KernelEventMonitor/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ LIBRARY_STYLE = BUNDLE;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = KernelEventMonitor;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = KernelEventMonitor.bundle;
+ productName = KernelEventMonitor.bundle;
+ productReference = 15828AE70753B5F900AD4710;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>KernelEventMonitor.bundle</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.KernelEventMonitor_bundle</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CSResourcesFileMapped</key>
+ <string>yes</string>
+</dict>
+</plist>
+";
+ productType = "com.apple.product-type.bundle";
+ };
+ 15828AE70753B5F900AD4710 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = KernelEventMonitor.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15828B060753B77E00AD4710 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15828AE60753B5F900AD4710;
+ remoteInfo = KernelEventMonitor.bundle;
+ };
+ 15828B070753B77E00AD4710 = {
+ isa = PBXTargetDependency;
+ target = 15828AE60753B5F900AD4710;
+ targetProxy = 15828B060753B77E00AD4710;
+ };
+ 1582B36B05FD1A4D009C2750 = {
+ children = (
+ 1582B37205FD1A5B009C2750,
+ 1582B37905FD1A66009C2750,
+ );
+ isa = PBXGroup;
+ name = DNSConfiguration;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 1582B37205FD1A5B009C2750 = {
+ children = (
+ 15B73F0905FD1B670096477F,
+ 1532629006281C9D00B1C10C,
+ 15B73F0C05FD1B670096477F,
+ 15B73F0E05FD1B670096477F,
+ );
+ isa = PBXGroup;
+ name = Headers;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 1582B37905FD1A66009C2750 = {
+ children = (
+ 15B73F0B05FD1B670096477F,
+ 15B73F0805FD1B670096477F,
+ 1521FC5C060F296A003B28F5,
+ 15B73F0D05FD1B670096477F,
+ );
+ isa = PBXGroup;
+ name = Sources;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158AD85B0754E38F00124717 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158AD8700754E3D400124717 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158AD8C00754E3EF00124717 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158AD9100754E40E00124717 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158AD9850754E72500124717 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15FD72A10754DA4C001CC321;
+ remoteInfo = IPMonitor.bundle;
+ };
+ 158AD9860754E72500124717 = {
+ isa = PBXTargetDependency;
+ target = 15FD72A10754DA4C001CC321;
+ targetProxy = 158AD9850754E72500124717;
+ };
+ 158AD9870754E72500124717 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15FD72930754DA2B001CC321;
+ remoteInfo = InterfaceNamer.bundle;
+ };
+ 158AD9880754E72500124717 = {
+ isa = PBXTargetDependency;
+ target = 15FD72930754DA2B001CC321;
+ targetProxy = 158AD9870754E72500124717;
+ };
+ 158AD9890754E72500124717 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15FD70FF0754D627001CC321;
+ remoteInfo = Kicker.bundle;
+ };
+ 158AD98A0754E72500124717 = {
+ isa = PBXTargetDependency;
+ target = 15FD70FF0754D627001CC321;
+ targetProxy = 158AD9890754E72500124717;
+ };
+ 158AD98B0754E72500124717 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15FD72B10754DA69001CC321;
+ remoteInfo = LinkConfiguration.bundle;
+ };
+ 158AD98C0754E72500124717 = {
+ isa = PBXTargetDependency;
+ target = 15FD72B10754DA69001CC321;
+ targetProxy = 158AD98B0754E72500124717;
+ };
+ 158AD98D0754E72500124717 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15FD72C50754DA7E001CC321;
+ remoteInfo = PreferencesMonitor.bundle;
+ };
+ 158AD98E0754E72500124717 = {
+ isa = PBXTargetDependency;
+ target = 15FD72C50754DA7E001CC321;
+ targetProxy = 158AD98D0754E72500124717;
+ };
+ 158AD9F80754EA2F00124717 = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = AppleTalk.framework;
+ path = /System/Library/Frameworks/AppleTalk.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 158ADA160754EA2F00124717 = {
+ fileRef = 158AD9F80754EA2F00124717;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 158ADA3D0754EA5A00124717 = {
+ fileRef = 15CB6A6F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 158ADABB0754EAAE00124717 = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = SystemConfiguration.framework;
+ path = /System/Library/Frameworks/SystemConfiguration.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 158ADBFD0754ECB100124717 = {
+ children = (
+ 15FD73400754DBDA001CC321,
+ 15FD73220754DB9F001CC321,
+ 159D53EC07528C61004F8947,
+ 15FD72A50754DA4C001CC321,
+ 159D53E507528C4A004F8947,
+ 15FD72970754DA2B001CC321,
+ 159D53D407528BDA004F8947,
+ 15828AE70753B5F900AD4710,
+ 159D53DE07528C2E004F8947,
+ 15FD71090754D628001CC321,
+ 159D53F307528C79004F8947,
+ 15FD72B50754DA69001CC321,
+ 159D53FA07528C95004F8947,
+ 15FD72C90754DA7E001CC321,
+ );
+ isa = PBXGroup;
+ name = Plugins;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158ADCA60754ECC800124717 = {
+ children = (
+ 159D54D907529FFF004F8947,
+ );
+ isa = PBXGroup;
+ name = "configd, scutil, scselect";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 158ADD0E0754F1A000124717 = {
+ fileRef = 159D53A807528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 158ADD190754F1F100124717 = {
+ fileRef = 159D53BC07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 158ADD1B0754F1F400124717 = {
+ fileRef = 159D53BD07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D53A207528B06004F8947 = {
+ children = (
+ 159D53C907528B36004F8947,
+ 159D53C407528B36004F8947,
+ 159D53A607528B36004F8947,
+ 159D53AC07528B36004F8947,
+ 159D53AF07528B36004F8947,
+ 159D53BB07528B36004F8947,
+ 159D53C007528B36004F8947,
+ 159D53C207528B36004F8947,
+ );
+ isa = PBXGroup;
+ name = Plugins;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53A607528B36004F8947 = {
+ children = (
+ 159D53A707528B36004F8947,
+ 159D53AA07528B36004F8947,
+ 159D53AB07528B36004F8947,
+ 159D53A807528B36004F8947,
+ 15FD743E0754DE7A001CC321,
+ );
+ isa = PBXGroup;
+ name = IPMonitor;
+ path = Plugins/IPMonitor;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53A707528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = ip_plugin.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53A807528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Resolvers.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53AA07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = "dns-configuration.c";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53AB07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = "set-hostname.c";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53AC07528B36004F8947 = {
+ children = (
+ 159D53AE07528B36004F8947,
+ 15FD73EE0754DE62001CC321,
+ );
+ isa = PBXGroup;
+ name = InterfaceNamer;
+ path = Plugins/InterfaceNamer;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53AE07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = ifnamer.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53AF07528B36004F8947 = {
+ children = (
+ 159D53B707528B36004F8947,
+ 159D53B607528B36004F8947,
+ 159D53B207528B36004F8947,
+ 159D53B807528B36004F8947,
+ 159D53BA07528B36004F8947,
+ 159D53B007528B36004F8947,
+ 159D53B907528B36004F8947,
+ 159D53B107528B36004F8947,
+ 159D53B307528B36004F8947,
+ 159D53B407528B36004F8947,
+ 158AD8700754E3D400124717,
+ );
+ isa = PBXGroup;
+ name = KernelEventMonitor;
+ path = Plugins/KernelEventMonitor;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B007528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = eventmon.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B107528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = ev_dlil.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B207528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = ev_dlil.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B307528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = ev_ipv4.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B407528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = ev_ipv6.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B607528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = ev_appletalk.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B707528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = eventmon.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B807528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = ev_ipv4.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53B907528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = ev_appletalk.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53BA07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = ev_ipv6.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53BB07528B36004F8947 = {
+ children = (
+ 159D53BE07528B36004F8947,
+ 158AD85B0754E38F00124717,
+ 159D53BC07528B36004F8947,
+ 159D53BD07528B36004F8947,
+ );
+ isa = PBXGroup;
+ name = Kicker;
+ path = Plugins/Kicker;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53BC07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Kicker.xml;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53BD07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.script.sh;
+ path = "enable-network";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53BE07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = kicker.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C007528B36004F8947 = {
+ children = (
+ 159D53C107528B36004F8947,
+ 158AD8C00754E3EF00124717,
+ );
+ isa = PBXGroup;
+ name = LinkConfiguration;
+ path = Plugins/LinkConfiguration;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C107528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = linkconfig.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C207528B36004F8947 = {
+ children = (
+ 159D53C307528B36004F8947,
+ 158AD9100754E40E00124717,
+ );
+ isa = PBXGroup;
+ name = PreferencesMonitor;
+ path = Plugins/PreferencesMonitor;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C307528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = prefsmon.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C407528B36004F8947 = {
+ children = (
+ 159D53C507528B36004F8947,
+ 159D53C607528B36004F8947,
+ 159D53C707528B36004F8947,
+ 15FD73970754DE49001CC321,
+ );
+ isa = PBXGroup;
+ name = ATconfig;
+ path = Plugins/ATconfig;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C507528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = cfManager.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C607528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = cfManager.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C707528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = atconfig.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53C907528B36004F8947 = {
+ children = (
+ 159D53CA07528B36004F8947,
+ 159D53CB07528B36004F8947,
+ );
+ isa = PBXGroup;
+ name = common;
+ path = Plugins/common;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53CA07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = cache.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53CB07528B36004F8947 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = cache.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 159D53D007528BDA004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D540A07528D3B004F8947,
+ 159D540C07528DAA004F8947,
+ 159D540E07528DAE004F8947,
+ 159D541007528DB1004F8947,
+ 159D541207528DB3004F8947,
+ 159D541407528DB5004F8947,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53D107528BDA004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D540907528D3A004F8947,
+ 159D540B07528DA9004F8947,
+ 159D540D07528DAE004F8947,
+ 159D540F07528DB0004F8947,
+ 159D541107528DB2004F8947,
+ 159D541307528DB5004F8947,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53D207528BDA004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53D307528BDA004F8947 = {
+ buildPhases = (
+ 159D53D007528BDA004F8947,
+ 159D53D107528BDA004F8947,
+ 159D53D207528BDA004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ HEADER_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = KernelEventMonitor;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = KernelEventMonitor;
+ productName = KernelEventMonitor;
+ productReference = 159D53D407528BDA004F8947;
+ productType = "com.apple.product-type.library.static";
+ };
+ 159D53D407528BDA004F8947 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libKernelEventMonitor.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 159D53DA07528C2E004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53DB07528C2E004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D541507528DDE004F8947,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53DC07528C2E004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53DD07528C2E004F8947 = {
+ buildPhases = (
+ 159D53DA07528C2E004F8947,
+ 159D53DB07528C2E004F8947,
+ 159D53DC07528C2E004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = Kicker;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = Kicker;
+ productName = Kicker;
+ productReference = 159D53DE07528C2E004F8947;
+ productType = "com.apple.product-type.library.static";
+ };
+ 159D53DE07528C2E004F8947 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libKicker.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 159D53E107528C4A004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53E207528C4A004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D541607528DF1004F8947,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53E307528C4A004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53E407528C4A004F8947 = {
+ buildPhases = (
+ 159D53E107528C4A004F8947,
+ 159D53E207528C4A004F8947,
+ 159D53E307528C4A004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = InterfaceNamer;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = InterfaceNamer;
+ productName = InterfaceNamer;
+ productReference = 159D53E507528C4A004F8947;
+ productType = "com.apple.product-type.library.static";
+ };
+ 159D53E507528C4A004F8947 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libInterfaceNamer.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 159D53E807528C61004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53E907528C61004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D541707528E05004F8947,
+ 159D541807528E09004F8947,
+ 154361E00752C81800A8EC6C,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53EA07528C61004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53EB07528C61004F8947 = {
+ buildPhases = (
+ 159D53E807528C61004F8947,
+ 159D53E907528C61004F8947,
+ 159D53EA07528C61004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = IPMonitor;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = IPMonitor;
+ productName = IPMonitor;
+ productReference = 159D53EC07528C61004F8947;
+ productType = "com.apple.product-type.library.static";
+ };
+ 159D53EC07528C61004F8947 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libIPMonitor.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 159D53EF07528C79004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53F007528C79004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D541B07528E4A004F8947,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53F107528C79004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53F207528C79004F8947 = {
+ buildPhases = (
+ 159D53EF07528C79004F8947,
+ 159D53F007528C79004F8947,
+ 159D53F107528C79004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = LinkConfiguration;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = LinkConfiguration;
+ productName = LinkConfiguration;
+ productReference = 159D53F307528C79004F8947;
+ productType = "com.apple.product-type.library.static";
+ };
+ 159D53F307528C79004F8947 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libLinkConfiguration.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 159D53F607528C95004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53F707528C95004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D541C07528E58004F8947,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53F807528C95004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D53F907528C95004F8947 = {
+ buildPhases = (
+ 159D53F607528C95004F8947,
+ 159D53F707528C95004F8947,
+ 159D53F807528C95004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = PreferencesMonitor;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = PreferencesMonitor;
+ productName = PreferencesMonitor;
+ productReference = 159D53FA07528C95004F8947;
+ productType = "com.apple.product-type.library.static";
+ };
+ 159D53FA07528C95004F8947 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libPreferencesMonitor.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 159D540907528D3A004F8947 = {
+ fileRef = 159D53CA07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D540A07528D3B004F8947 = {
+ fileRef = 159D53CB07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D540B07528DA9004F8947 = {
+ fileRef = 159D53B907528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D540C07528DAA004F8947 = {
+ fileRef = 159D53B607528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D540D07528DAE004F8947 = {
+ fileRef = 159D53B107528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D540E07528DAE004F8947 = {
+ fileRef = 159D53B207528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D540F07528DB0004F8947 = {
+ fileRef = 159D53B307528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541007528DB1004F8947 = {
+ fileRef = 159D53B807528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541107528DB2004F8947 = {
+ fileRef = 159D53B407528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541207528DB3004F8947 = {
+ fileRef = 159D53BA07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541307528DB5004F8947 = {
+ fileRef = 159D53B007528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541407528DB5004F8947 = {
+ fileRef = 159D53B707528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541507528DDE004F8947 = {
+ fileRef = 159D53BE07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541607528DF1004F8947 = {
+ fileRef = 159D53AE07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541707528E05004F8947 = {
+ fileRef = 159D53A707528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541807528E09004F8947 = {
+ fileRef = 159D53AA07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541B07528E4A004F8947 = {
+ fileRef = 159D53C107528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D541C07528E58004F8947 = {
+ fileRef = 159D53C307528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D542007528E7C004F8947 = {
+ buildPhases = (
+ );
+ buildSettings = {
+ PRODUCT_NAME = Plugins;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ 15DAD5740759115F0084A6ED,
+ 159D542807528E85004F8947,
+ 158AD9860754E72500124717,
+ 159D542607528E85004F8947,
+ 158AD9880754E72500124717,
+ 15828B070753B77E00AD4710,
+ 159D542207528E85004F8947,
+ 159D542407528E85004F8947,
+ 158AD98A0754E72500124717,
+ 159D542A07528E85004F8947,
+ 158AD98C0754E72500124717,
+ 159D542C07528E85004F8947,
+ 158AD98E0754E72500124717,
+ );
+ isa = PBXAggregateTarget;
+ name = configd_plugins;
+ productName = Plugins;
+ };
+ 159D542107528E85004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D53D307528BDA004F8947;
+ remoteInfo = KernelEventMonitor;
+ };
+ 159D542207528E85004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D53D307528BDA004F8947;
+ targetProxy = 159D542107528E85004F8947;
+ };
+ 159D542307528E85004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D53DD07528C2E004F8947;
+ remoteInfo = Kicker;
+ };
+ 159D542407528E85004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D53DD07528C2E004F8947;
+ targetProxy = 159D542307528E85004F8947;
+ };
+ 159D542507528E85004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D53E407528C4A004F8947;
+ remoteInfo = InterfaceNamer;
+ };
+ 159D542607528E85004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D53E407528C4A004F8947;
+ targetProxy = 159D542507528E85004F8947;
+ };
+ 159D542707528E85004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D53EB07528C61004F8947;
+ remoteInfo = IPMonitor;
+ };
+ 159D542807528E85004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D53EB07528C61004F8947;
+ targetProxy = 159D542707528E85004F8947;
+ };
+ 159D542907528E85004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D53F207528C79004F8947;
+ remoteInfo = LinkConfiguration;
+ };
+ 159D542A07528E85004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D53F207528C79004F8947;
+ targetProxy = 159D542907528E85004F8947;
+ };
+ 159D542B07528E85004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D53F907528C95004F8947;
+ remoteInfo = PreferencesMonitor;
+ };
+ 159D542C07528E85004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D53F907528C95004F8947;
+ targetProxy = 159D542B07528E85004F8947;
+ };
+ 159D542D07529008004F8947 = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 159D542007528E7C004F8947;
+ remoteInfo = Plugins;
+ };
+ 159D542E07529008004F8947 = {
+ isa = PBXTargetDependency;
+ target = 159D542007528E7C004F8947;
+ targetProxy = 159D542D07529008004F8947;
+ };
+ 159D549F07529FFF004F8947 = {
+ buildPhases = (
+ 159D54A307529FFF004F8947,
+ 159D54AB07529FFF004F8947,
+ 159D54CA07529FFF004F8947,
+ 159D54D407529FFF004F8947,
+ 159D54D507529FFF004F8947,
+ 159D54D707529FFF004F8947,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ CURRENT_PROJECT_VERSION = 130;
+ DEAD_CODE_STRIPPING = YES;
+ FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/sbin;
+ LIBRARY_SEARCH_PATHS = "$(SYMROOT) /usr/local/lib/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ OTHER_LDFLAGS = "-prebind_all_twolevel_modules";
+ PRODUCT_NAME = configd;
+ STRIPFLAGS = "-S";
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = configd;
+ productInstallPath = /usr/sbin;
+ productName = "configd (Tool)";
+ productReference = 159D54D907529FFF004F8947;
+ productType = "com.apple.product-type.tool";
+ };
+ 159D54A307529FFF004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D54A407529FFF004F8947,
+ 159D54A507529FFF004F8947,
+ 159D54A607529FFF004F8947,
+ 159D54A707529FFF004F8947,
+ 159D54A807529FFF004F8947,
+ 159D54A907529FFF004F8947,
+ 159D54AA07529FFF004F8947,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D54A407529FFF004F8947 = {
+ fileRef = 15CB69CF05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54A507529FFF004F8947 = {
+ fileRef = 15CB69D105C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54A607529FFF004F8947 = {
+ fileRef = 15CB69D305C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54A707529FFF004F8947 = {
+ fileRef = 15CB69D505C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54A807529FFF004F8947 = {
+ fileRef = 15CB69D705C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54A907529FFF004F8947 = {
+ fileRef = 15CB69D905C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54AA07529FFF004F8947 = {
+ fileRef = 15CB69DB05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54AB07529FFF004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D54AC07529FFF004F8947,
+ 159D54AD07529FFF004F8947,
+ 159D54AE07529FFF004F8947,
+ 159D54AF07529FFF004F8947,
+ 159D54B007529FFF004F8947,
+ 159D54B107529FFF004F8947,
+ 159D54B207529FFF004F8947,
+ 159D54B307529FFF004F8947,
+ 159D54B407529FFF004F8947,
+ 159D54B507529FFF004F8947,
+ 159D54B607529FFF004F8947,
+ 159D54B707529FFF004F8947,
+ 159D54B807529FFF004F8947,
+ 159D54B907529FFF004F8947,
+ 159D54BA07529FFF004F8947,
+ 159D54BB07529FFF004F8947,
+ 159D54BC07529FFF004F8947,
+ 159D54BD07529FFF004F8947,
+ 159D54BE07529FFF004F8947,
+ 159D54BF07529FFF004F8947,
+ 159D54C007529FFF004F8947,
+ 159D54C107529FFF004F8947,
+ 159D54C207529FFF004F8947,
+ 159D54C307529FFF004F8947,
+ 159D54C407529FFF004F8947,
+ 159D54C507529FFF004F8947,
+ 159D54C607529FFF004F8947,
+ 159D54C707529FFF004F8947,
+ 159D54C807529FFF004F8947,
+ 159D54C907529FFF004F8947,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D54AC07529FFF004F8947 = {
+ fileRef = 15CB69E005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54AD07529FFF004F8947 = {
+ fileRef = 15CB69E205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54AE07529FFF004F8947 = {
+ fileRef = 15CB69E405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54AF07529FFF004F8947 = {
+ fileRef = 15CB69E605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B007529FFF004F8947 = {
+ fileRef = 15CB69E805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B107529FFF004F8947 = {
+ fileRef = 15CB69EA05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B207529FFF004F8947 = {
+ fileRef = 15CB69EC05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B307529FFF004F8947 = {
+ fileRef = 15CB69F005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B407529FFF004F8947 = {
+ fileRef = 15CB69F205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B507529FFF004F8947 = {
+ fileRef = 15CB69F405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B607529FFF004F8947 = {
+ fileRef = 15CB69F605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B707529FFF004F8947 = {
+ fileRef = 15CB69F805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B807529FFF004F8947 = {
+ fileRef = 15CB69FA05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54B907529FFF004F8947 = {
+ fileRef = 15CB69FE05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54BA07529FFF004F8947 = {
+ fileRef = 15CB6A0005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54BB07529FFF004F8947 = {
+ fileRef = 15CB6A0205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54BC07529FFF004F8947 = {
+ fileRef = 15CB6A0405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54BD07529FFF004F8947 = {
+ fileRef = 15CB6A0605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54BE07529FFF004F8947 = {
+ fileRef = 15CB6A0805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54BF07529FFF004F8947 = {
+ fileRef = 15CB6A0A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C007529FFF004F8947 = {
+ fileRef = 15CB6A0C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C107529FFF004F8947 = {
+ fileRef = 15CB6A0E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C207529FFF004F8947 = {
+ fileRef = 15CB6A1005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C307529FFF004F8947 = {
+ fileRef = 15CB6A1205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C407529FFF004F8947 = {
+ fileRef = 15CB6A1405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C507529FFF004F8947 = {
+ fileRef = 15CB6A1605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 159D54C607529FFF004F8947 = {
+ fileRef = 15CB69BE05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Server,
+ );
+ };
+ };
+ 159D54C707529FFF004F8947 = {
+ fileRef = 15B73F0B05FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54C807529FFF004F8947 = {
+ fileRef = 15B73F0D05FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54C907529FFF004F8947 = {
+ fileRef = 15FCAAD005FD0EBF00CB79E6;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Server,
+ );
+ };
+ };
+ 159D54CA07529FFF004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ 159D54CC07529FFF004F8947,
+ 1523F6F1075A36F70066F0B2,
+ 1543636B0752D03C00A8EC6C,
+ 159D54CD07529FFF004F8947,
+ 1523F715075A376B0066F0B2,
+ 159D54CE07529FFF004F8947,
+ 159D54CF07529FFF004F8947,
+ 159D54D007529FFF004F8947,
+ 159D54D107529FFF004F8947,
+ 159D54D207529FFF004F8947,
+ 159D54D307529FFF004F8947,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D54CC07529FFF004F8947 = {
+ fileRef = 15CB6A6F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54CD07529FFF004F8947 = {
+ fileRef = 15CB6A7405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54CE07529FFF004F8947 = {
+ fileRef = 159D53D407528BDA004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54CF07529FFF004F8947 = {
+ fileRef = 159D53DE07528C2E004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D007529FFF004F8947 = {
+ fileRef = 159D53E507528C4A004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D107529FFF004F8947 = {
+ fileRef = 159D53EC07528C61004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D207529FFF004F8947 = {
+ fileRef = 159D53F307528C79004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D307529FFF004F8947 = {
+ fileRef = 159D53FA07528C95004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D407529FFF004F8947 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D54D507529FFF004F8947 = {
+ buildActionMask = 12;
+ dstPath = /usr/share/man/man8;
+ dstSubfolderSpec = 0;
+ files = (
+ 159D54D607529FFF004F8947,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D54D607529FFF004F8947 = {
+ fileRef = 15CB6A2005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D707529FFF004F8947 = {
+ buildActionMask = 2147483647;
+ dstPath = /private/etc/mach_init.d;
+ dstSubfolderSpec = 0;
+ files = (
+ 159D54D807529FFF004F8947,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 159D54D807529FFF004F8947 = {
+ fileRef = 15CB6A1F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 159D54D907529FFF004F8947 = {
+ explicitFileType = "compiled.mach-o.executable";
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = configd;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15A509A306C2518F001F0AB7 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = net.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15A509A406C2518F001F0AB7 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = net.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A380670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCNetworkConfiguration.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A390670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkConfigurationInternal.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A3A0670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCNetworkConfigurationInternal.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A3B0670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkInterface.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A3C0670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkProtocol.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A3D0670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkService.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15AD7A3E0670A85900BFE03C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkSet.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B6861D0678B61900FF4023 = {
+ children = (
+ 15B686220678B65C00FF4023,
+ 1577253606EFBF3100D7B52B,
+ 15CFC229068B222F00123568,
+ );
+ isa = PBXGroup;
+ name = "Supporting Files";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B686220678B65C00FF4023 = {
+ explicitFileType = text.xml;
+ fileEncoding = 4;
+ isa = PBXFileReference;
+ path = NetworkConfiguration.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B73F0805FD1B670096477F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = dnsinfo_copy.c;
+ path = dnsinfo/dnsinfo_copy.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B73F0905FD1B670096477F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dnsinfo.h;
+ path = dnsinfo/dnsinfo.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B73F0B05FD1B670096477F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = dnsinfo_private.c;
+ path = dnsinfo/dnsinfo_private.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B73F0C05FD1B670096477F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dnsinfo_private.h;
+ path = dnsinfo/dnsinfo_private.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B73F0D05FD1B670096477F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = dnsinfo_server.c;
+ path = dnsinfo/dnsinfo_server.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15B73F0E05FD1B670096477F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dnsinfo_server.h;
+ path = dnsinfo/dnsinfo_server.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB68FC05C072220099E85F = {
+ children = (
+ 15CB6A8605C072500099E85F,
+ 15CB6A8305C072410099E85F,
+ 1582B36B05FD1A4D009C2750,
+ 15CB690705C0722A0099E85F,
+ 15CB69C205C0722B0099E85F,
+ 15CB6A2205C0722B0099E85F,
+ 15CB6A3705C0722B0099E85F,
+ 159D53A207528B06004F8947,
+ 1514D77D05C08AB700757DC9,
+ 15CB6A6E05C0722B0099E85F,
+ 15CB690F05C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = configd;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB68FE05C072220099E85F = {
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ };
+ isa = PBXBuildStyle;
+ name = Development;
+ };
+ 15CB68FF05C072220099E85F = {
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ };
+ isa = PBXBuildStyle;
+ name = Deployment;
+ };
+ 15CB690005C0722A0099E85F = {
+ buildPhases = (
+ );
+ buildSettings = {
+ PRODUCT_NAME = "configd (Aggregate)";
+ };
+ dependencies = (
+ 157BB8C40759244B0025DA7A,
+ 159D542E07529008004F8947,
+ 1558480F07550DD00046C2E9,
+ );
+ isa = PBXAggregateTarget;
+ name = All;
+ productName = "configd (Aggregate)";
+ };
+ 15CB690505C0722A0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = preferences.xml;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB690705C0722A0099E85F = {
+ children = (
+ 15CB691205C0722B0099E85F,
+ 15CB694F05C0722B0099E85F,
+ 15B6861D0678B61900FF4023,
+ );
+ isa = PBXGroup;
+ name = SystemConfiguration;
+ path = SystemConfiguration.fproj;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB690F05C0722B0099E85F = {
+ children = (
+ 158ADBFD0754ECB100124717,
+ 158ADCA60754ECC800124717,
+ 1558476A0754FDCD0046C2E9,
+ 1558481D07550EC10046C2E9,
+ 15DAD5EE075913CE0084A6ED,
+ 15DAD6C807591A1A0084A6ED,
+ 15481BF8075A2B3900B32F56,
+ );
+ isa = PBXGroup;
+ name = Products;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691205C0722B0099E85F = {
+ children = (
+ 15CB691305C0722B0099E85F,
+ 15CB691705C0722B0099E85F,
+ 15CB691B05C0722B0099E85F,
+ 15CB691D05C0722B0099E85F,
+ 15CB691F05C0722B0099E85F,
+ 15CB692105C0722B0099E85F,
+ 15CB693F05C0722B0099E85F,
+ 15CB692305C0722B0099E85F,
+ 15CB692505C0722B0099E85F,
+ 15CB692705C0722B0099E85F,
+ 15CB692905C0722B0099E85F,
+ 15CB692B05C0722B0099E85F,
+ 15CB692D05C0722B0099E85F,
+ 15CB692F05C0722B0099E85F,
+ 151BDA2B05D9E28B00657BC7,
+ 154CF3F307E1EA4D00D8302E,
+ 15CB693105C0722B0099E85F,
+ 156BD6BB07E0DFA9008698FF,
+ 15CB691505C0722B0099E85F,
+ 15AD7A380670A85900BFE03C,
+ 15AD7A3A0670A85900BFE03C,
+ 15CB693305C0722B0099E85F,
+ 15CB693505C0722B0099E85F,
+ 15CB693705C0722B0099E85F,
+ 15CB693905C0722B0099E85F,
+ 9EE943F406AF409B00772EB5,
+ 9EE943F506AF409B00772EB5,
+ 15CB694505C0722B0099E85F,
+ 15CB693D05C0722B0099E85F,
+ 15CB694705C0722B0099E85F,
+ 15CB694B05C0722B0099E85F,
+ 15CB694D05C0722B0099E85F,
+ 15CB694905C0722B0099E85F,
+ 15CB694305C0722B0099E85F,
+ 15CB694105C0722B0099E85F,
+ 23C1E2BE062DD5DB00835B54,
+ );
+ isa = PBXGroup;
+ name = Headers;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691305C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SystemConfiguration.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691505C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691705C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDPlugin.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691B05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStoreInternal.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691D05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStore.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB691F05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStorePrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692105C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStoreKey.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692305C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStoreCopySpecific.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692505C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStoreCopySpecificPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692705C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStoreSetSpecificPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692905C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferencesInternal.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692B05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferences.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692D05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferencesPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB692F05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferencesPath.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693105C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCPreferencesSetSpecific.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693305C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCNetwork.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693505C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCNetworkConnection.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693705C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCNetworkReachability.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693905C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCValidation.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693D05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = DHCPClientPreferences.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB693F05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = SCDynamicStoreCopyDHCPInfo.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694105C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = moh_msg.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694305C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = moh.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694505C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = DeviceOnHold.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694705C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = LinkConfiguration.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694905C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = dy_framework.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694B05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = VLANConfiguration.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694D05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = VLANConfigurationPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB694F05C0722B0099E85F = {
+ children = (
+ 150607BD075A00A200B147BA,
+ 150607DE075A00A300B147BA,
+ 15CB695005C0722B0099E85F,
+ 15CB695205C0722B0099E85F,
+ 15CB695405C0722B0099E85F,
+ 15CB695605C0722B0099E85F,
+ 15CB695805C0722B0099E85F,
+ 15CB695A05C0722B0099E85F,
+ 15CB695C05C0722B0099E85F,
+ 15CB695E05C0722B0099E85F,
+ 15CB696005C0722B0099E85F,
+ 15CB696405C0722B0099E85F,
+ 15CB696605C0722B0099E85F,
+ 15CB696805C0722B0099E85F,
+ 15CB696A05C0722B0099E85F,
+ 15CB696C05C0722B0099E85F,
+ 15CB696E05C0722B0099E85F,
+ 15CB697005C0722B0099E85F,
+ 15CB697205C0722B0099E85F,
+ 15CB697405C0722B0099E85F,
+ 15CB697605C0722B0099E85F,
+ 15CB697805C0722B0099E85F,
+ 15CB697A05C0722B0099E85F,
+ 15CB697C05C0722B0099E85F,
+ 15CB697E05C0722B0099E85F,
+ 15CB698005C0722B0099E85F,
+ 15CB698205C0722B0099E85F,
+ 15CB698405C0722B0099E85F,
+ 15CB698605C0722B0099E85F,
+ 15CB698805C0722B0099E85F,
+ 15CB698A05C0722B0099E85F,
+ 15CB698C05C0722B0099E85F,
+ 15CB698E05C0722B0099E85F,
+ 15CB699005C0722B0099E85F,
+ 15CB699205C0722B0099E85F,
+ 15CB699405C0722B0099E85F,
+ 15CB699605C0722B0099E85F,
+ 15CB699805C0722B0099E85F,
+ 15CB699A05C0722B0099E85F,
+ 151BDA5D05D9E2ED00657BC7,
+ 15AD7A390670A85900BFE03C,
+ 15AD7A3B0670A85900BFE03C,
+ 15AD7A3C0670A85900BFE03C,
+ 15AD7A3D0670A85900BFE03C,
+ 15AD7A3E0670A85900BFE03C,
+ 15CB699C05C0722B0099E85F,
+ 15CB699E05C0722B0099E85F,
+ 15CB69A005C0722B0099E85F,
+ 15CB69A205C0722B0099E85F,
+ 15CB69A405C0722B0099E85F,
+ 15CB69A605C0722B0099E85F,
+ 15CB69A805C0722B0099E85F,
+ 15CB69AC05C0722B0099E85F,
+ 15CB69AE05C0722B0099E85F,
+ 15CB69B005C0722B0099E85F,
+ 15CB69B205C0722B0099E85F,
+ 15CB69B405C0722B0099E85F,
+ 9EE943F306AF409B00772EB5,
+ 15CB69B605C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = Sources;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCD.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDKeys.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDPrivate.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDPlugin.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDOpen.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDLock.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDUnlock.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB695E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDList.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDAdd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDGet.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDSet.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDRemove.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDTouch.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotify.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB696E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierSetKeys.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierAdd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierRemove.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierGetChanges.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierWait.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierInformViaCallback.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierInformViaMachPort.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierInformViaFD.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB697E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierInformViaSignal.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDNotifierCancel.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDSnapshot.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCP.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698605C0722B0099E85F = {
+ indentWidth = 8;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPOpen.c;
+ refType = 4;
+ sourceTree = "<group>";
+ tabWidth = 8;
+ };
+ 15CB698805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPLock.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPUnlock.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPList.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB698E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPGet.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPAdd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPSet.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPRemove.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPCommit.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPApply.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCPPath.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDConsoleUser.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB699E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCDHostName.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69A005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCLocation.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69A205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetwork.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69A405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkConnection.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69A605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCNetworkReachability.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69A805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = SCProxies.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69AC05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = DHCP.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69AE05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = moh.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69B005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = DeviceOnHold.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69B205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = LinkConfiguration.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69B405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = dy_framework.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69B605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = VLANConfiguration.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69BE05C0722B0099E85F = {
+ explicitFileType = sourcecode.mig;
+ isa = PBXFileReference;
+ name = config.defs;
+ path = SystemConfiguration.fproj/config.defs;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69BF05C0722B0099E85F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = genSCPreferences.c;
+ path = SystemConfiguration.fproj/genSCPreferences.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69C205C0722B0099E85F = {
+ children = (
+ 15CB69CE05C0722B0099E85F,
+ 15CB69DF05C0722B0099E85F,
+ 15CB6A1805C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = configd;
+ path = configd.tproj;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69CE05C0722B0099E85F = {
+ children = (
+ 15CB69CF05C0722B0099E85F,
+ 15CB69D105C0722B0099E85F,
+ 15CB69D305C0722B0099E85F,
+ 15CB69D505C0722B0099E85F,
+ 15CB69D705C0722B0099E85F,
+ 15CB69D905C0722B0099E85F,
+ 15CB69DB05C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = Headers;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69CF05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = configd.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69D105C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = _SCD.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69D305C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = configd_server.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69D505C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = notify_server.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69D705C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = plugin_support.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69D905C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = session.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69DB05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = pattern.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69DF05C0722B0099E85F = {
+ children = (
+ 15CB69E005C0722B0099E85F,
+ 15CB69E205C0722B0099E85F,
+ 15CB69E405C0722B0099E85F,
+ 15CB69E605C0722B0099E85F,
+ 15CB69E805C0722B0099E85F,
+ 15CB69EA05C0722B0099E85F,
+ 15CB69EC05C0722B0099E85F,
+ 15CB69F005C0722B0099E85F,
+ 15CB69F205C0722B0099E85F,
+ 15CB69F405C0722B0099E85F,
+ 15CB69F605C0722B0099E85F,
+ 15CB69F805C0722B0099E85F,
+ 15CB69FA05C0722B0099E85F,
+ 15CB69FE05C0722B0099E85F,
+ 15CB6A0005C0722B0099E85F,
+ 15CB6A0205C0722B0099E85F,
+ 15CB6A0405C0722B0099E85F,
+ 15CB6A0605C0722B0099E85F,
+ 15CB6A0805C0722B0099E85F,
+ 15CB6A0A05C0722B0099E85F,
+ 15CB6A0C05C0722B0099E85F,
+ 15CB6A0E05C0722B0099E85F,
+ 15CB6A1005C0722B0099E85F,
+ 15CB6A1205C0722B0099E85F,
+ 15CB6A1405C0722B0099E85F,
+ 15CB6A1605C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = Sources;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69E005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.objc;
+ path = configd.m;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69E205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _SCD.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69E405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = configd_server.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69E605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = notify_server.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69E805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = plugin_support.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69EA05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = session.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69EC05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = pattern.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69F005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configopen.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69F205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configclose.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69F405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configlock.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69F605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configunlock.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69F805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configlist.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69FA05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configadd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB69FE05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configget.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configset.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configremove.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _configtouch.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _confignotify.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifyadd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifyremove.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifychanges.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A0E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifyviaport.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A1005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifyviafd.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A1205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifyviasignal.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A1405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _notifycancel.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A1605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = _snapshot.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A1805C0722B0099E85F = {
+ children = (
+ 15CB6A1F05C0722B0099E85F,
+ 15CB6A2005C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = "Supporting Files";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A1F05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = configd.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A2005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ path = configd.8;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A2205C0722B0099E85F = {
+ children = (
+ 15CB6A2D05C0722B0099E85F,
+ 15CB6A3005C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = scselect;
+ path = scselect.tproj;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A2D05C0722B0099E85F = {
+ children = (
+ 15CB6A2E05C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = Sources;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A2E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = scselect.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A3005C0722B0099E85F = {
+ children = (
+ 15CB6A3605C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = "Supporting Files";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A3605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ path = scselect.8;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A3705C0722B0099E85F = {
+ children = (
+ 15CB6A4205C0722B0099E85F,
+ 15CB6A5305C0722B0099E85F,
+ 15CB6A6405C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = scutil;
+ path = scutil.tproj;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4205C0722B0099E85F = {
+ children = (
+ 15CB6A4305C0722B0099E85F,
+ 15CB6A4505C0722B0099E85F,
+ 15CB6A4705C0722B0099E85F,
+ 15CB6A4905C0722B0099E85F,
+ 15CB6A4B05C0722B0099E85F,
+ 15CB6A4D05C0722B0099E85F,
+ 15CB6A4F05C0722B0099E85F,
+ 15CB6A5105C0722B0099E85F,
+ 15A509A406C2518F001F0AB7,
+ 15DC34680711D49400A3311C,
+ 15DC346A0711D49400A3311C,
+ 15DC346C0711D49400A3311C,
+ 15DC346E0711D49400A3311C,
+ );
+ isa = PBXGroup;
+ name = Headers;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4305C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = scutil.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4505C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = commands.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4705C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = dictionary.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4905C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = session.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4B05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = cache.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4D05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = notifications.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A4F05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = tests.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5105C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = prefs.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5305C0722B0099E85F = {
+ children = (
+ 15CB6A5405C0722B0099E85F,
+ 15CB6A5605C0722B0099E85F,
+ 15CB6A5805C0722B0099E85F,
+ 15CB6A5A05C0722B0099E85F,
+ 15CB6A5C05C0722B0099E85F,
+ 15CB6A5E05C0722B0099E85F,
+ 15CB6A6005C0722B0099E85F,
+ 15CB6A6205C0722B0099E85F,
+ 15A509A306C2518F001F0AB7,
+ 15DC34670711D49400A3311C,
+ 15DC34690711D49400A3311C,
+ 15DC346B0711D49400A3311C,
+ 15DC346D0711D49400A3311C,
+ );
+ isa = PBXGroup;
+ name = Sources;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = scutil.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5605C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = commands.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5805C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = dictionary.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = session.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5C05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = cache.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A5E05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = notifications.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A6005C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = tests.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A6205C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = prefs.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A6405C0722B0099E85F = {
+ children = (
+ 15CB6A6A05C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = "Supporting Files";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A6A05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = text;
+ path = scutil.8;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A6E05C0722B0099E85F = {
+ children = (
+ 158AD9F80754EA2F00124717,
+ 15CB6A6F05C0722B0099E85F,
+ 1543636A0752D03C00A8EC6C,
+ 158ADABB0754EAAE00124717,
+ 15CB6A7405C0722B0099E85F,
+ 152CEED0070CF6640050F23C,
+ );
+ isa = PBXGroup;
+ name = "External Frameworks and Libraries";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A6F05C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = wrapper.framework;
+ name = CoreFoundation.framework;
+ path = /System/Library/Frameworks/CoreFoundation.framework;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 15CB6A7405C0722B0099E85F = {
+ isa = PBXFileReference;
+ lastKnownFileType = "compiled.mach-o.dylib";
+ name = libobjc.dylib;
+ path = /usr/lib/libobjc.A.dylib;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 15CB6A7705C0722B0099E85F = {
+ buildSettings = {
+ CURRENT_PROJECT_VERSION = 130;
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = "";
+ INSTALL_GROUP = wheel;
+ INSTALL_MODE_FLAG = "u+s,ugo-w,o+rX";
+ INSTALL_OWNER = root;
+ INSTALL_PATH = /usr/sbin;
+ LIBRARY_SEARCH_PATHS = "";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ OTHER_LDFLAGS = "-dead_strip";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = scselect;
+ REZ_EXECUTABLE = YES;
+ SECTORDER_FLAGS = "";
+ STRIPFLAGS = "-S";
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wall -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ buildStyles = (
+ 15CB68FE05C072220099E85F,
+ 15CB68FF05C072220099E85F,
+ );
+ hasScannedForEncodings = 1;
+ isa = PBXProject;
+ mainGroup = 15CB68FC05C072220099E85F;
+ productRefGroup = 15CB690F05C0722B0099E85F;
+ projectDirPath = "";
+ targets = (
+ 15CB690005C0722A0099E85F,
+ 157BB8AE075924360025DA7A,
+ 159D542007528E7C004F8947,
+ 155847FA07550D210046C2E9,
+ 15DAD5DF075913CE0084A6ED,
+ 15481BF7075A2B3900B32F56,
+ 15DAD63F07591A1A0084A6ED,
+ 159D549F07529FFF004F8947,
+ 1558481207550EC10046C2E9,
+ 155847430754FDCD0046C2E9,
+ 15FD733A0754DBDA001CC321,
+ 15FD731E0754DB9F001CC321,
+ 159D53EB07528C61004F8947,
+ 15FD72A10754DA4C001CC321,
+ 159D53E407528C4A004F8947,
+ 15FD72930754DA2B001CC321,
+ 159D53D307528BDA004F8947,
+ 15828AE60753B5F900AD4710,
+ 159D53DD07528C2E004F8947,
+ 15FD70FF0754D627001CC321,
+ 159D53F207528C79004F8947,
+ 15FD72B10754DA69001CC321,
+ 159D53F907528C95004F8947,
+ 15FD72C50754DA7E001CC321,
+ );
+ };
+ 15CB6A8305C072410099E85F = {
+ children = (
+ 15CB69BF05C0722B0099E85F,
+ );
+ isa = PBXGroup;
+ name = Schema;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CB6A8605C072500099E85F = {
+ children = (
+ 15CB69BE05C0722B0099E85F,
+ 1514D76D05C08A5F00757DC9,
+ 15FCAAD005FD0EBF00CB79E6,
+ 15FCAACF05FD0EBF00CB79E6,
+ 23C1E2B8062DD45900835B54,
+ 23C1E2B4062DD2C700835B54,
+ );
+ isa = PBXGroup;
+ name = MiG;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15CFC229068B222F00123568 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.script.sh;
+ path = "get-mobility-info";
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ 15DAD5730759115F0084A6ED = {
+ containerPortal = 15CB6A7705C0722B0099E85F;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = 15FD731E0754DB9F001CC321;
+ remoteInfo = ATconfig.bundle;
+ };
+ 15DAD5740759115F0084A6ED = {
+ isa = PBXTargetDependency;
+ target = 15FD731E0754DB9F001CC321;
+ targetProxy = 15DAD5730759115F0084A6ED;
+ };
+ 15DAD5DF075913CE0084A6ED = {
+ buildPhases = (
+ 15DAD5E0075913CE0084A6ED,
+ 15DAD5E4075913CE0084A6ED,
+ 15DAD5E9075913CE0084A6ED,
+ 15DAD5EA075913CE0084A6ED,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ INSTALLHDRS_COPY_PHASE = YES;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib;
+ LIBRARY_STYLE = STATIC;
+ PRODUCT_NAME = dnsinfo;
+ SECTORDER_FLAGS = "";
+ UNSTRIPPED_PRODUCT = YES;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = DNSConfiguration;
+ productInstallPath = /usr/local/lib;
+ productName = DNSConfiguration;
+ productReference = 15DAD5EE075913CE0084A6ED;
+ productType = "com.apple.product-type.library.static";
+ };
+ 15DAD5E0075913CE0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ 15DAD5E1075913CE0084A6ED,
+ 15DAD5E2075913CE0084A6ED,
+ 15DAD5E3075913CE0084A6ED,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD5E1075913CE0084A6ED = {
+ fileRef = 15B73F0905FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ 15DAD5E2075913CE0084A6ED = {
+ fileRef = 15B73F0C05FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD5E3075913CE0084A6ED = {
+ fileRef = 1532629006281C9D00B1C10C;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ 15DAD5E4075913CE0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ 15DAD5E5075913CE0084A6ED,
+ 15DAD5E6075913CE0084A6ED,
+ 15DAD5E7075913CE0084A6ED,
+ 15DAD5E8075913CE0084A6ED,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD5E5075913CE0084A6ED = {
+ fileRef = 15FCAAD005FD0EBF00CB79E6;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Client,
+ );
+ };
+ };
+ 15DAD5E6075913CE0084A6ED = {
+ fileRef = 15B73F0805FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD5E7075913CE0084A6ED = {
+ fileRef = 15B73F0B05FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD5E8075913CE0084A6ED = {
+ fileRef = 1521FC5C060F296A003B28F5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD5E9075913CE0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD5EA075913CE0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD5EE075913CE0084A6ED = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libdnsinfo.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15DAD63F07591A1A0084A6ED = {
+ buildPhases = (
+ 15DAD6AC07591A1A0084A6ED,
+ 15DAD64107591A1A0084A6ED,
+ 15DAD66807591A1A0084A6ED,
+ 15DAD66C07591A1A0084A6ED,
+ 15DAD6AD07591A1A0084A6ED,
+ 15DAD6AF07591A1A0084A6ED,
+ 15DAD6B007591A1A0084A6ED,
+ 15DAD6B107591A1A0084A6ED,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ CURRENT_PROJECT_VERSION = 130;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ HEADER_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INFOPLIST_FILE = SystemConfiguration.fproj/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+ LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ OTHER_LDFLAGS = "-seg_addr_table $(APPLE_INTERNAL_DEVELOPER_DIR)/seg_addr_table";
+ PRODUCT_NAME = SystemConfiguration;
+ SECTORDER_FLAGS = "-sectorder __TEXT __text $(OBJROOT)/SystemConfiguration.order";
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = framework;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = SystemConfiguration.framework;
+ productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+ productName = "SystemConfiguration (Framework)";
+ productReference = 15DAD6C807591A1A0084A6ED;
+ productType = "com.apple.product-type.framework";
+ };
+ 15DAD64107591A1A0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ 1506081A075A00A300B147BA,
+ 15DAD64307591A1A0084A6ED,
+ 15DAD64407591A1A0084A6ED,
+ 15DAD64507591A1A0084A6ED,
+ 15DAD64607591A1A0084A6ED,
+ 15DAD64707591A1A0084A6ED,
+ 15DAD64807591A1A0084A6ED,
+ 15DAD64907591A1A0084A6ED,
+ 15DAD64A07591A1A0084A6ED,
+ 15DAD64B07591A1A0084A6ED,
+ 15DAD64C07591A1A0084A6ED,
+ 15DAD64D07591A1A0084A6ED,
+ 15DAD64E07591A1A0084A6ED,
+ 15DAD64F07591A1A0084A6ED,
+ 15DAD65007591A1A0084A6ED,
+ 15DAD65107591A1A0084A6ED,
+ 15DAD65207591A1A0084A6ED,
+ 15DAD65307591A1A0084A6ED,
+ 15DAD65407591A1A0084A6ED,
+ 15DAD65507591A1A0084A6ED,
+ 15DAD65607591A1A0084A6ED,
+ 15DAD65707591A1A0084A6ED,
+ 15DAD65807591A1A0084A6ED,
+ 15DAD65907591A1A0084A6ED,
+ 15DAD65A07591A1A0084A6ED,
+ 15DAD65B07591A1A0084A6ED,
+ 15DAD65C07591A1A0084A6ED,
+ 15DAD65D07591A1A0084A6ED,
+ 15DAD65E07591A1A0084A6ED,
+ 15DAD65F07591A1A0084A6ED,
+ 15DAD66007591A1A0084A6ED,
+ 15DAD66107591A1A0084A6ED,
+ 15DAD66207591A1A0084A6ED,
+ 15DAD66307591A1A0084A6ED,
+ 15DAD66407591A1A0084A6ED,
+ 15DAD66507591A1A0084A6ED,
+ 15DAD66607591A1A0084A6ED,
+ 15DAD66707591A1A0084A6ED,
+ 156BD6BC07E0DFA9008698FF,
+ 154CF3F407E1EA4D00D8302E,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD64307591A1A0084A6ED = {
+ fileRef = 15CB691305C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD64407591A1A0084A6ED = {
+ fileRef = 15CB691505C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD64507591A1A0084A6ED = {
+ fileRef = 15CB691705C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD64607591A1A0084A6ED = {
+ fileRef = 15CB691B05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ );
+ };
+ };
+ 15DAD64707591A1A0084A6ED = {
+ fileRef = 15CB691D05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD64807591A1A0084A6ED = {
+ fileRef = 15CB691F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD64907591A1A0084A6ED = {
+ fileRef = 15CB692105C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD64A07591A1A0084A6ED = {
+ fileRef = 15CB692305C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD64B07591A1A0084A6ED = {
+ fileRef = 15CB692505C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD64C07591A1A0084A6ED = {
+ fileRef = 15CB692705C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD64D07591A1A0084A6ED = {
+ fileRef = 15CB692905C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ );
+ };
+ };
+ 15DAD64E07591A1A0084A6ED = {
+ fileRef = 15CB692B05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD64F07591A1A0084A6ED = {
+ fileRef = 15CB692D05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD65007591A1A0084A6ED = {
+ fileRef = 15CB692F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD65107591A1A0084A6ED = {
+ fileRef = 15CB693105C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD65207591A1A0084A6ED = {
+ fileRef = 15AD7A380670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ 15DAD65307591A1A0084A6ED = {
+ fileRef = 15AD7A3A0670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD65407591A1A0084A6ED = {
+ fileRef = 15CB693305C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD65507591A1A0084A6ED = {
+ fileRef = 15CB693505C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD65607591A1A0084A6ED = {
+ fileRef = 15CB693705C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ Project,
+ );
+ };
+ };
+ 15DAD65707591A1A0084A6ED = {
+ fileRef = 15CB693905C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD65807591A1A0084A6ED = {
+ fileRef = 15CB693D05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ 15DAD65907591A1A0084A6ED = {
+ fileRef = 15CB693F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Public,
+ );
+ };
+ };
+ 15DAD65A07591A1A0084A6ED = {
+ fileRef = 15CB694105C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD65B07591A1A0084A6ED = {
+ fileRef = 15CB694305C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD65C07591A1A0084A6ED = {
+ fileRef = 15CB694505C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD65D07591A1A0084A6ED = {
+ fileRef = 15CB694705C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD65E07591A1A0084A6ED = {
+ fileRef = 15CB694905C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD65F07591A1A0084A6ED = {
+ fileRef = 15CB694B05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD66007591A1A0084A6ED = {
+ fileRef = 15CB694D05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Project,
+ Private,
+ );
+ };
+ };
+ 15DAD66107591A1A0084A6ED = {
+ fileRef = 151BDA2B05D9E28B00657BC7;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD66207591A1A0084A6ED = {
+ fileRef = 15B73F0905FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66307591A1A0084A6ED = {
+ fileRef = 15B73F0C05FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66407591A1A0084A6ED = {
+ fileRef = 23C1E2B4062DD2C700835B54;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66507591A1A0084A6ED = {
+ fileRef = 23C1E2BE062DD5DB00835B54;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66607591A1A0084A6ED = {
+ fileRef = 9EE943F406AF409B00772EB5;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD66707591A1A0084A6ED = {
+ fileRef = 9EE943F506AF409B00772EB5;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Private,
+ );
+ };
+ };
+ 15DAD66807591A1A0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ 15DAD66907591A1A0084A6ED,
+ 15DAD66A07591A1A0084A6ED,
+ 15DAD66B07591A1A0084A6ED,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD66907591A1A0084A6ED = {
+ fileRef = 15B686220678B65C00FF4023;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66A07591A1A0084A6ED = {
+ fileRef = 15CFC229068B222F00123568;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66B07591A1A0084A6ED = {
+ fileRef = 1577253606EFBF3100D7B52B;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD66C07591A1A0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ 15060818075A00A300B147BA,
+ 15DAD66D07591A1A0084A6ED,
+ 15DAD66E07591A1A0084A6ED,
+ 15DAD66F07591A1A0084A6ED,
+ 15DAD67007591A1A0084A6ED,
+ 15DAD67107591A1A0084A6ED,
+ 15DAD67207591A1A0084A6ED,
+ 15DAD67307591A1A0084A6ED,
+ 15DAD67407591A1A0084A6ED,
+ 15DAD67507591A1A0084A6ED,
+ 15DAD67607591A1A0084A6ED,
+ 15DAD67707591A1A0084A6ED,
+ 15DAD67807591A1A0084A6ED,
+ 15DAD67907591A1A0084A6ED,
+ 15DAD67A07591A1A0084A6ED,
+ 15DAD67B07591A1A0084A6ED,
+ 15DAD67C07591A1A0084A6ED,
+ 15DAD67D07591A1A0084A6ED,
+ 15DAD67E07591A1A0084A6ED,
+ 15DAD67F07591A1A0084A6ED,
+ 15DAD68007591A1A0084A6ED,
+ 15DAD68107591A1A0084A6ED,
+ 15DAD68207591A1A0084A6ED,
+ 15DAD68307591A1A0084A6ED,
+ 15DAD68407591A1A0084A6ED,
+ 15DAD68507591A1A0084A6ED,
+ 15DAD68607591A1A0084A6ED,
+ 15DAD68707591A1A0084A6ED,
+ 15DAD68807591A1A0084A6ED,
+ 15DAD68907591A1A0084A6ED,
+ 15DAD68A07591A1A0084A6ED,
+ 15DAD68B07591A1A0084A6ED,
+ 15DAD68C07591A1A0084A6ED,
+ 15DAD68D07591A1A0084A6ED,
+ 15DAD68E07591A1A0084A6ED,
+ 15DAD68F07591A1A0084A6ED,
+ 15DAD69007591A1A0084A6ED,
+ 15DAD69107591A1A0084A6ED,
+ 15DAD69207591A1A0084A6ED,
+ 15DAD69307591A1A0084A6ED,
+ 15DAD69407591A1A0084A6ED,
+ 15DAD69507591A1A0084A6ED,
+ 15DAD69607591A1A0084A6ED,
+ 15DAD69707591A1A0084A6ED,
+ 15DAD69807591A1A0084A6ED,
+ 15DAD69907591A1A0084A6ED,
+ 15DAD69A07591A1A0084A6ED,
+ 15DAD69B07591A1A0084A6ED,
+ 15DAD69C07591A1A0084A6ED,
+ 15DAD69D07591A1A0084A6ED,
+ 15DAD69E07591A1A0084A6ED,
+ 15DAD69F07591A1A0084A6ED,
+ 15DAD6A007591A1A0084A6ED,
+ 15DAD6A207591A1A0084A6ED,
+ 15DAD6A307591A1A0084A6ED,
+ 15DAD6A407591A1A0084A6ED,
+ 15DAD6A507591A1A0084A6ED,
+ 15DAD6A607591A1A0084A6ED,
+ 15DAD6A707591A1A0084A6ED,
+ 15DAD6A807591A1A0084A6ED,
+ 15DAD6A907591A1A0084A6ED,
+ 15DAD6AA07591A1A0084A6ED,
+ 15DAD6AB07591A1A0084A6ED,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD66D07591A1A0084A6ED = {
+ fileRef = 15CB695005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD66E07591A1A0084A6ED = {
+ fileRef = 15CB695205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD66F07591A1A0084A6ED = {
+ fileRef = 15CB695405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67007591A1A0084A6ED = {
+ fileRef = 15CB695605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67107591A1A0084A6ED = {
+ fileRef = 15CB695805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67207591A1A0084A6ED = {
+ fileRef = 15CB695A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67307591A1A0084A6ED = {
+ fileRef = 15CB695C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67407591A1A0084A6ED = {
+ fileRef = 15CB695E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67507591A1A0084A6ED = {
+ fileRef = 15CB696005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67607591A1A0084A6ED = {
+ fileRef = 15CB696405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67707591A1A0084A6ED = {
+ fileRef = 15CB696605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67807591A1A0084A6ED = {
+ fileRef = 15CB696805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67907591A1A0084A6ED = {
+ fileRef = 15CB696A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67A07591A1A0084A6ED = {
+ fileRef = 15CB696C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67B07591A1A0084A6ED = {
+ fileRef = 15CB696E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67C07591A1A0084A6ED = {
+ fileRef = 15CB697005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67D07591A1A0084A6ED = {
+ fileRef = 15CB697205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67E07591A1A0084A6ED = {
+ fileRef = 15CB697405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD67F07591A1A0084A6ED = {
+ fileRef = 15CB697605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68007591A1A0084A6ED = {
+ fileRef = 15CB697805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68107591A1A0084A6ED = {
+ fileRef = 15CB697A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68207591A1A0084A6ED = {
+ fileRef = 15CB697C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68307591A1A0084A6ED = {
+ fileRef = 15CB697E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68407591A1A0084A6ED = {
+ fileRef = 15CB698005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68507591A1A0084A6ED = {
+ fileRef = 15CB698205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68607591A1A0084A6ED = {
+ fileRef = 15CB698405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68707591A1A0084A6ED = {
+ fileRef = 15CB698605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68807591A1A0084A6ED = {
+ fileRef = 15CB698805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68907591A1A0084A6ED = {
+ fileRef = 15CB698A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68A07591A1A0084A6ED = {
+ fileRef = 15CB698C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68B07591A1A0084A6ED = {
+ fileRef = 15CB698E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68C07591A1A0084A6ED = {
+ fileRef = 15CB699005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68D07591A1A0084A6ED = {
+ fileRef = 15CB699205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68E07591A1A0084A6ED = {
+ fileRef = 15CB699405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD68F07591A1A0084A6ED = {
+ fileRef = 15CB699605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69007591A1A0084A6ED = {
+ fileRef = 15CB699805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69107591A1A0084A6ED = {
+ fileRef = 15CB699A05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69207591A1A0084A6ED = {
+ fileRef = 15CB699C05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69307591A1A0084A6ED = {
+ fileRef = 15CB699E05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69407591A1A0084A6ED = {
+ fileRef = 15CB69A005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69507591A1A0084A6ED = {
+ fileRef = 15CB69A205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69607591A1A0084A6ED = {
+ fileRef = 23C1E2B8062DD45900835B54;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Client,
+ );
+ };
+ };
+ 15DAD69707591A1A0084A6ED = {
+ fileRef = 15CB69A405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69807591A1A0084A6ED = {
+ fileRef = 15CB69A605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69907591A1A0084A6ED = {
+ fileRef = 15CB69A805C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69A07591A1A0084A6ED = {
+ fileRef = 15CB69AC05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69B07591A1A0084A6ED = {
+ fileRef = 15CB69AE05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69C07591A1A0084A6ED = {
+ fileRef = 15CB69B005C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69D07591A1A0084A6ED = {
+ fileRef = 15CB69B205C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69E07591A1A0084A6ED = {
+ fileRef = 15CB69B405C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD69F07591A1A0084A6ED = {
+ fileRef = 15CB69B605C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ );
+ };
+ };
+ 15DAD6A007591A1A0084A6ED = {
+ fileRef = 15CB69BE05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Client,
+ );
+ };
+ };
+ 15DAD6A207591A1A0084A6ED = {
+ fileRef = 151BDA5D05D9E2ED00657BC7;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6A307591A1A0084A6ED = {
+ fileRef = 15B73F0B05FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6A407591A1A0084A6ED = {
+ fileRef = 15B73F0805FD1B670096477F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6A507591A1A0084A6ED = {
+ fileRef = 15FCAAD005FD0EBF00CB79E6;
+ isa = PBXBuildFile;
+ settings = {
+ ATTRIBUTES = (
+ Client,
+ );
+ };
+ };
+ 15DAD6A607591A1A0084A6ED = {
+ fileRef = 15AD7A390670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6A707591A1A0084A6ED = {
+ fileRef = 15AD7A3B0670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6A807591A1A0084A6ED = {
+ fileRef = 15AD7A3C0670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6A907591A1A0084A6ED = {
+ fileRef = 15AD7A3D0670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6AA07591A1A0084A6ED = {
+ fileRef = 15AD7A3E0670A85900BFE03C;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6AB07591A1A0084A6ED = {
+ fileRef = 9EE943F306AF409B00772EB5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6AC07591A1A0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ /usr/local/lib/OrderFiles/SystemConfiguration.order,
+ );
+ isa = PBXShellScriptBuildPhase;
+ name = SystemConfiguration.order;
+ outputPaths = (
+ "${OBJROOT}/SystemConfiguration.order",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "if [ -r /usr/local/lib/OrderFiles/SystemConfiguration.order ]; then\n\tcp /usr/local/lib/OrderFiles/SystemConfiguration.order ${OBJROOT}/SystemConfiguration.order\nelse\n\ttouch ${OBJROOT}/SystemConfiguration.order\nfi";
+ };
+ 15DAD6AD07591A1A0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ 15DAD6AE07591A1A0084A6ED,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD6AE07591A1A0084A6ED = {
+ fileRef = 15CB6A6F05C0722B0099E85F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15DAD6AF07591A1A0084A6ED = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15DAD6B007591A1A0084A6ED = {
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ isa = PBXShellScriptBuildPhase;
+ name = "get-mobility-info";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "mkdir -p \"${DSTROOT}/usr/local/bin\"\nln -fs \"${INSTALL_PATH}/${TARGET_NAME}/Resources/get-mobility-info\" \"${DSTROOT}/usr/local/bin/\"\n";
+ };
+ 15DAD6B107591A1A0084A6ED = {
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ preferences.xml,
+ );
+ isa = PBXShellScriptBuildPhase;
+ name = preferences.plist;
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "PREFS_DIR=\"/Library/Preferences/SystemConfiguration\"\nmkdir -p ${DSTROOT}${PREFS_DIR}\nchmod 755 ${DSTROOT}${PREFS_DIR}\ninstall -c -m 644 preferences.xml ${DSTROOT}${PREFS_DIR}/preferences.plist";
+ };
+ 15DAD6C807591A1A0084A6ED = {
+ explicitFileType = wrapper.framework;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = SystemConfiguration.framework;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15DC34670711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = net_interface.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC34680711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = net_interface.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC34690711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = net_protocol.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC346A0711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = net_protocol.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC346B0711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = net_service.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC346C0711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = net_service.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC346D0711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = net_set.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15DC346E0711D49400A3311C = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = net_set.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15FCAACF05FD0EBF00CB79E6 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = shared_dns_info_types.h;
+ path = dnsinfo/shared_dns_info_types.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ 15FCAAD005FD0EBF00CB79E6 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.mig;
+ name = shared_dns_info.defs;
+ path = dnsinfo/shared_dns_info.defs;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15FD70FF0754D627001CC321 = {
+ buildPhases = (
+ 15FD71010754D627001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/Kicker/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = Kicker;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = bundle;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = Kicker.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = Kicker.bundle;
+ productReference = 15FD71090754D628001CC321;
+ productType = "com.apple.product-type.bundle";
+ };
+ 15FD71010754D627001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ 158ADD190754F1F100124717,
+ 158ADD1B0754F1F400124717,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD71090754D628001CC321 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = Kicker.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD72930754DA2B001CC321 = {
+ buildPhases = (
+ 15FD72940754DA2B001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/InterfaceNamer/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = InterfaceNamer;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = bundle;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = InterfaceNamer.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = Kicker.bundle;
+ productReference = 15FD72970754DA2B001CC321;
+ productType = "com.apple.product-type.bundle";
+ };
+ 15FD72940754DA2B001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD72970754DA2B001CC321 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = InterfaceNamer.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD72A10754DA4C001CC321 = {
+ buildPhases = (
+ 15FD72A20754DA4C001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = IPMonitor;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = bundle;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = IPMonitor.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = Kicker.bundle;
+ productReference = 15FD72A50754DA4C001CC321;
+ productType = "com.apple.product-type.bundle";
+ };
+ 15FD72A20754DA4C001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ 158ADD0E0754F1A000124717,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD72A50754DA4C001CC321 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = IPMonitor.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD72B10754DA69001CC321 = {
+ buildPhases = (
+ 15FD72B20754DA69001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/LinkConfiguration/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = LinkConfiguration;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = bundle;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = LinkConfiguration.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = Kicker.bundle;
+ productReference = 15FD72B50754DA69001CC321;
+ productType = "com.apple.product-type.bundle";
+ };
+ 15FD72B20754DA69001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD72B50754DA69001CC321 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = LinkConfiguration.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD72C50754DA7E001CC321 = {
+ buildPhases = (
+ 15FD72C60754DA7E001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INFOPLIST_FILE = Plugins/PreferencesMonitor/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = PreferencesMonitor;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = bundle;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = PreferencesMonitor.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = Kicker.bundle;
+ productReference = 15FD72C90754DA7E001CC321;
+ productType = "com.apple.product-type.bundle";
+ };
+ 15FD72C60754DA7E001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD72C90754DA7E001CC321 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = PreferencesMonitor.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD731E0754DB9F001CC321 = {
+ buildPhases = (
+ 15FD731F0754DB9F001CC321,
+ 15FD73200754DB9F001CC321,
+ 15FD73210754DB9F001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ CURRENT_PROJECT_VERSION = 130;
+ HEADER_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+ INFOPLIST_FILE = Plugins/ATconfig/Info.plist;
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = ATconfig;
+ VALID_ARCHS = ppc;
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = bundle;
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = ATconfig.bundle;
+ productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+ productName = Kicker.bundle;
+ productReference = 15FD73220754DB9F001CC321;
+ productType = "com.apple.product-type.bundle";
+ };
+ 15FD731F0754DB9F001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD73200754DB9F001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ 15FD73480754DC2A001CC321,
+ 15FD735C0754DC3F001CC321,
+ 15FD735E0754DC43001CC321,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD73210754DB9F001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ 158ADA3D0754EA5A00124717,
+ 1523F6EE075A36210066F0B2,
+ 158ADA160754EA2F00124717,
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD73220754DB9F001CC321 = {
+ explicitFileType = wrapper.cfbundle;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = ATconfig.bundle;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD733A0754DBDA001CC321 = {
+ buildPhases = (
+ 15FD733C0754DBDA001CC321,
+ 15FD733D0754DBDA001CC321,
+ 15FD733F0754DBDA001CC321,
+ );
+ buildRules = (
+ );
+ buildSettings = {
+ INSTALL_MODE_FLAG = "a-w,a+rX";
+ INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "-fconstant-cfstrings";
+ PRODUCT_NAME = ATconfig;
+ WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = ATconfig;
+ productName = InterfaceNamer;
+ productReference = 15FD73400754DBDA001CC321;
+ productType = "com.apple.product-type.library.static";
+ };
+ 15FD733C0754DBDA001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD733D0754DBDA001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ 1508E39F07552B6A0062B350,
+ 1508E3A007552B6B0062B350,
+ 1508E3A107552B720062B350,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD733F0754DBDA001CC321 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 15FD73400754DBDA001CC321 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libATconfig.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 15FD73480754DC2A001CC321 = {
+ fileRef = 159D53C707528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15FD735C0754DC3F001CC321 = {
+ fileRef = 159D53CA07528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15FD735E0754DC43001CC321 = {
+ fileRef = 159D53C507528B36004F8947;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 15FD73970754DE49001CC321 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15FD73EE0754DE62001CC321 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 15FD743E0754DE7A001CC321 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.xml;
+ path = Info.plist;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+//150
+//151
+//152
+//153
+//154
+//230
+//231
+//232
+//233
+//234
+ 23C1E2B4062DD2C700835B54 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = pppcontroller_types.h;
+ path = /usr/local/include/ppp/pppcontroller_types.h;
+ refType = 0;
+ sourceTree = "<absolute>";
+ };
+ 23C1E2B8062DD45900835B54 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.mig;
+ name = pppcontroller.defs;
+ path = SystemConfiguration.fproj/pppcontroller.defs;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 23C1E2BE062DD5DB00835B54 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = pppcontroller.h;
+ path = configd.build/SystemConfiguration.framework.build/DerivedSources/pppcontroller.h;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+//230
+//231
+//232
+//233
+//234
+//9E0
+//9E1
+//9E2
+//9E3
+//9E4
+ 9EE943F306AF409B00772EB5 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ path = BondConfiguration.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 9EE943F406AF409B00772EB5 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = BondConfiguration.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 9EE943F506AF409B00772EB5 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = BondConfigurationPrivate.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ };
+ rootObject = 15CB6A7705C0722B0099E85F;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef __DNSINFO_H__
+#define __DNSINFO_H__
+
+
+/*
+ * These routines provide access to the systems DNS configuration
+ */
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/cdefs.h>
+
+
+#define DEFAULT_SEARCH_ORDER 200000 /* search order for the "default" resolver domain name */
+
+
+typedef struct {
+ struct in_addr address;
+ struct in_addr mask;
+} dns_sortaddr_t;
+
+
+typedef struct {
+ char *domain; /* domain */
+ int32_t n_nameserver; /* # nameserver */
+ struct sockaddr **nameserver;
+ uint16_t port; /* port (in host byte order) */
+ int32_t n_search; /* # search */
+ char **search;
+ int32_t n_sortaddr; /* # sortaddr */
+ dns_sortaddr_t **sortaddr;
+ char *options; /* options */
+ uint32_t timeout; /* timeout */
+ uint32_t search_order; /* search_order */
+ void *reserved[8];
+} dns_resolver_t;
+
+
+typedef struct {
+ int32_t n_resolver; /* resolver configurations */
+ dns_resolver_t **resolver;
+ void *reserved[8];
+} dns_config_t;
+
+
+__BEGIN_DECLS
+
+/*
+ * DNS configuration access APIs
+ */
+const char * dns_configuration_notify_key ();
+dns_config_t * dns_configuration_copy ();
+void dns_configuration_free (dns_config_t *config);
+
+__END_DECLS
+
+#endif __DNSINFO_H__
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * March 9, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdlib.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "dnsinfo.h"
+#include "dnsinfo_private.h"
+#include "shared_dns_info.h"
+
+
+static boolean_t
+add_list(void **padding, uint32_t *n_padding, int32_t count, int32_t size, void **list)
+{
+ int32_t need;
+
+ need = count * size;
+ if (need > *n_padding) {
+ return FALSE;
+ }
+
+ *list = (need == 0) ? NULL : *padding;
+ *padding += need;
+ *n_padding -= need;
+ return TRUE;
+}
+
+
+static _dns_config_buf_t *
+copy_dns_info()
+{
+ uint8_t *buf = NULL;
+ dnsDataOut_t dataRef = NULL;
+ mach_msg_type_number_t dataLen = 0;
+ mach_port_t server;
+ kern_return_t status;
+
+ server = _dns_configuration_server_port();
+ if (server == MACH_PORT_NULL) {
+ return NULL;
+ }
+
+ status = shared_dns_infoGet(server, &dataRef, &dataLen);
+ (void)mach_port_deallocate(mach_task_self(), server);
+ if (status != KERN_SUCCESS) {
+ mach_error("shared_dns_infoGet():", status);
+ return NULL;
+ }
+
+ if (dataRef != NULL) {
+ if (dataLen >= sizeof(_dns_config_buf_t)) {
+ _dns_config_buf_t *config = (_dns_config_buf_t *)dataRef;
+ uint32_t len;
+ uint32_t n_padding = ntohl(config->n_padding);
+
+ len = dataLen + n_padding;
+ buf = malloc(len);
+ bcopy((void *)dataRef, buf, dataLen);
+ bzero(&buf[dataLen], n_padding);
+ }
+
+ status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
+ if (status != KERN_SUCCESS) {
+ mach_error("vm_deallocate():", status);
+ free(buf);
+ return NULL;
+ }
+ }
+
+ return (_dns_config_buf_t *)buf;
+}
+
+
+static dns_resolver_t *
+expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32_t *n_padding)
+{
+ dns_attribute_t *attribute;
+ uint32_t n_attribute;
+ int32_t n_nameserver = 0;
+ int32_t n_search = 0;
+ int32_t n_sortaddr = 0;
+ dns_resolver_t *resolver = (dns_resolver_t *)&buf->resolver;
+
+ if (n_buf < sizeof(_dns_resolver_buf_t)) {
+ goto error;
+ }
+
+ // initialize domain
+
+ resolver->domain = NULL;
+
+ // initialize nameserver list
+
+ resolver->n_nameserver = ntohl(resolver->n_nameserver);
+ if (!add_list(padding,
+ n_padding,
+ resolver->n_nameserver,
+ sizeof(struct sockaddr *),
+ (void **)&resolver->nameserver)) {
+ goto error;
+ }
+
+ // initialize port
+
+ resolver->port = ntohs(resolver->port);
+
+ // initialize search list
+
+ resolver->n_search = ntohl(resolver->n_search);
+ if (!add_list(padding,
+ n_padding,
+ resolver->n_search,
+ sizeof(char *),
+ (void **)&resolver->search)) {
+ goto error;
+ }
+
+ // initialize sortaddr list
+
+ resolver->n_sortaddr = ntohl(resolver->n_sortaddr);
+ if (!add_list(padding,
+ n_padding,
+ resolver->n_sortaddr,
+ sizeof(dns_sortaddr_t *),
+ (void **)&resolver->sortaddr)) {
+ goto error;
+ }
+
+ // initialize options
+
+ resolver->options = NULL;
+
+ // initialize timeout
+
+ resolver->timeout = ntohl(resolver->timeout);
+
+ // initialize search_order
+
+ resolver->search_order = ntohl(resolver->search_order);
+
+ // process resolver buffer "attribute" data
+
+ n_attribute = n_buf - sizeof(_dns_resolver_buf_t);
+ attribute = (dns_attribute_t *)&buf->attribute[0];
+ if (n_attribute != ntohl(buf->n_attribute)) {
+ goto error;
+ }
+
+ while (n_attribute >= sizeof(dns_attribute_t)) {
+ int32_t attribute_length = ntohl(attribute->length);
+
+ switch (ntohl(attribute->type)) {
+ case RESOLVER_ATTRIBUTE_DOMAIN :
+ resolver->domain = (char *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_ADDRESS :
+ resolver->nameserver[n_nameserver++] = (struct sockaddr *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_SEARCH :
+ resolver->search[n_search++] = (char *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_SORTADDR :
+ resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_OPTIONS :
+ resolver->options = (char *)&attribute->attribute[0];
+ break;
+
+ default :
+ break;
+ }
+
+ attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
+ n_attribute -= attribute_length;
+ }
+
+ if ((n_nameserver != resolver->n_nameserver) ||
+ (n_search != resolver->n_search ) ||
+ (n_sortaddr != resolver->n_sortaddr )) {
+ goto error;
+ }
+
+ return resolver;
+
+ error :
+
+ return NULL;
+}
+
+
+static dns_config_t *
+expand_config(_dns_config_buf_t *buf)
+{
+ dns_attribute_t *attribute;
+ dns_config_t *config = (dns_config_t *)buf;
+ uint32_t n_attribute;
+ uint32_t n_padding;
+ int32_t n_resolver = 0;
+ void *padding;
+
+ // establish padding
+
+ padding = &buf->attribute[ntohl(buf->n_attribute)];
+ n_padding = ntohl(buf->n_padding);
+
+ // initialize resolver list
+
+ config->n_resolver = ntohl(config->n_resolver);
+ if (!add_list(&padding,
+ &n_padding,
+ config->n_resolver,
+ sizeof(dns_resolver_t *),
+ (void **)&config->resolver)) {
+ goto error;
+ }
+
+ // process configuration buffer "attribute" data
+
+ n_attribute = ntohl(buf->n_attribute);
+ attribute = (dns_attribute_t *)&buf->attribute[0];
+
+ while (n_attribute >= sizeof(dns_attribute_t)) {
+ int32_t attribute_length = ntohl(attribute->length);
+
+ switch (ntohl(attribute->type)) {
+ case CONFIG_ATTRIBUTE_RESOLVER : {
+ dns_resolver_t *resolver;
+
+ // expand resolver buffer
+
+ resolver = expand_resolver((_dns_resolver_buf_t *)&attribute->attribute[0],
+ attribute_length - sizeof(dns_attribute_t),
+ &padding,
+ &n_padding);
+ if (resolver == NULL) {
+ goto error;
+ }
+
+ // add resolver to config list
+
+ config->resolver[n_resolver++] = resolver;
+
+ break;
+ }
+
+ default :
+ break;
+ }
+
+ attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
+ n_attribute -= attribute_length;
+ }
+
+ if (n_resolver != config->n_resolver) {
+ goto error;
+ }
+
+ return config;
+
+ error :
+
+ return NULL;
+}
+
+
+__private_extern__
+const char *
+dns_configuration_notify_key()
+{
+ return _dns_configuration_notify_key();
+}
+
+
+__private_extern__
+dns_config_t *
+dns_configuration_copy()
+{
+ _dns_config_buf_t *buf;
+ dns_config_t *config;
+
+ buf = copy_dns_info();
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ config = expand_config(buf);
+ if (config == NULL) {
+ free(buf);
+ return NULL;
+ }
+
+ return config;
+}
+
+
+__private_extern__
+void
+dns_configuration_free(dns_config_t *config)
+{
+ if (config == NULL) {
+ return;
+ }
+
+ free((void *)config);
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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 <stdlib.h>
+#include <strings.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "dnsinfo_create.h"
+#include "dnsinfo_private.h"
+#include "shared_dns_info.h"
+
+
+#define ROUNDUP(a, size) \
+ (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
+
+
+/*
+ * to avoid extra calls to realloc() we want to pre-allocate the initial
+ * resolver and configuration buffers of a sufficient size that they would
+ * not normally need to be expanded.
+ */
+#define INITIAL_CONFIGURATION_BUF_SIZE 8192
+#define INITIAL_RESOLVER_BUF_SIZE 1024
+
+
+/*
+ * DNS [configuration] buffer functions
+ */
+
+
+__private_extern__
+dns_create_config_t
+_dns_configuration_create()
+{
+ _dns_config_buf_t *config;
+
+ config = calloc(1, INITIAL_CONFIGURATION_BUF_SIZE);
+// config->n_attribute = 0;
+// config->n_padding = 0;
+ return (dns_create_config_t)config;
+}
+
+
+static void
+config_add_attribute(dns_create_config_t *_config,
+ uint32_t attribute_type,
+ uint32_t attribute_length,
+ void *attribute,
+ uint32_t extra_padding)
+{
+ _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
+ dns_attribute_t *header;
+ int i;
+ uint32_t newLen;
+ uint32_t newSize;
+ uint32_t oldLen;
+ uint32_t rounded_length;
+
+ // add space
+
+ oldLen = ntohl(config->n_attribute);
+ rounded_length = ROUNDUP(attribute_length, sizeof(uint32_t));
+ newLen = sizeof(dns_attribute_t) + rounded_length;
+ newSize = sizeof(_dns_config_buf_t) + oldLen + newLen;
+ if (newSize > INITIAL_CONFIGURATION_BUF_SIZE) {
+ config = realloc(config, newSize);
+ }
+ config->n_attribute = htonl(ntohl(config->n_attribute) + newLen);
+
+ // increment additional padding that will be needed (later)
+ config->n_padding = htonl(ntohl(config->n_padding) + extra_padding);
+
+ // add attribute [header]
+
+ header = (dns_attribute_t *)&config->attribute[oldLen];
+ header->type = htonl(attribute_type);
+ header->length = htonl(newLen);
+
+ // add attribute [data]
+
+ bcopy(attribute, &header->attribute[0], attribute_length);
+ for (i = attribute_length; i < rounded_length; i++) {
+ header->attribute[i] = 0;
+ }
+
+ *_config = (dns_create_config_t)config;
+ return;
+}
+
+
+__private_extern__
+void
+_dns_configuration_add_resolver(dns_create_config_t *_config,
+ dns_create_resolver_t _resolver)
+{
+ _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
+ uint32_t padding = 0;
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)_resolver;
+
+ /*
+ * compute the amount of space that will be needed for
+ * pointers to the resolver, the nameservers, the search
+ * list, and the sortaddr list.
+ */
+ padding += sizeof(dns_resolver_t *);
+ if (resolver->resolver.n_nameserver != 0) {
+ padding += ntohl(resolver->resolver.n_nameserver) * sizeof(struct sockaddr *);
+ }
+ if (resolver->resolver.n_search != 0) {
+ padding += ntohl(resolver->resolver.n_search) * sizeof(char *);
+ }
+ if (resolver->resolver.n_sortaddr != 0) {
+ padding += ntohl(resolver->resolver.n_sortaddr) * sizeof(dns_sortaddr_t *);
+ }
+
+ config->config.n_resolver = htonl(ntohl(config->config.n_resolver) + 1);
+
+ config_add_attribute(_config,
+ CONFIG_ATTRIBUTE_RESOLVER,
+ sizeof(_dns_resolver_buf_t) + ntohl(resolver->n_attribute),
+ (void *)resolver,
+ padding);
+
+ return;
+}
+
+
+__private_extern__
+_Bool
+_dns_configuration_store(dns_create_config_t *_config)
+{
+ dnsDataOut_t dataRef = NULL;
+ mach_msg_type_number_t dataLen = 0;
+ mach_port_t server;
+ kern_return_t status;
+
+ server = _dns_configuration_server_port();
+ if (server == MACH_PORT_NULL) {
+ return FALSE;
+ }
+
+ if (_config != NULL) {
+ _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
+
+ if (config != NULL) {
+ dataRef = (dnsDataOut_t)config;
+ dataLen = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
+ }
+ }
+
+ status = shared_dns_infoSet(server, dataRef, dataLen);
+ (void)mach_port_deallocate(mach_task_self(), server);
+ if (status != KERN_SUCCESS) {
+ mach_error("shared_dns_infoSet():", status);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+__private_extern__
+void
+_dns_configuration_free(dns_create_config_t *_config)
+{
+ _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
+
+ free(config);
+ *_config = NULL;
+ return;
+}
+
+
+/*
+ * DNS resolver configuration functions
+ */
+
+__private_extern__
+dns_create_resolver_t
+_dns_resolver_create()
+{
+ _dns_resolver_buf_t *buf;
+
+ buf = calloc(1, INITIAL_RESOLVER_BUF_SIZE);
+// buf->n_attribute = 0;
+ return (dns_create_resolver_t)buf;
+}
+
+
+static void
+_dns_resolver_add_attribute(dns_create_resolver_t *_resolver,
+ uint32_t attribute_type,
+ uint32_t attribute_length,
+ void *attribute)
+{
+ dns_attribute_t *header;
+ int i;
+ uint32_t newLen;
+ uint32_t newSize;
+ uint32_t oldLen;
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+ uint32_t rounded_length;
+
+ // add space
+
+ oldLen = ntohl(resolver->n_attribute);
+ rounded_length = ROUNDUP(attribute_length, sizeof(uint32_t));
+ newLen = sizeof(dns_attribute_t) + rounded_length;
+ newSize = sizeof(_dns_resolver_buf_t) + oldLen + newLen;
+ if (newSize > INITIAL_RESOLVER_BUF_SIZE) {
+ resolver = realloc(resolver, newSize);
+ }
+ resolver->n_attribute = htonl(ntohl(resolver->n_attribute) + newLen);
+
+ // add attribute [header]
+
+ header = (dns_attribute_t *)&resolver->attribute[oldLen];
+ header->type = htonl(attribute_type);
+ header->length = htonl(newLen);
+
+ // add attribute [data]
+
+ bcopy(attribute, &header->attribute[0], attribute_length);
+ for (i = attribute_length; i < rounded_length; i++) {
+ header->attribute[i] = 0;
+ }
+
+ *_resolver = (dns_create_resolver_t)resolver;
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
+{
+ _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_DOMAIN, strlen(domain) + 1, (void *)domain);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_add_nameserver(dns_create_resolver_t *_resolver, struct sockaddr *nameserver)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.n_nameserver = htonl(ntohl(resolver->resolver.n_nameserver) + 1);
+ _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_ADDRESS, nameserver->sa_len, (void *)nameserver);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_port(dns_create_resolver_t *_resolver, uint32_t port)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.port = htons(port);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.n_search = htonl(ntohl(resolver->resolver.n_search) + 1);
+ _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SEARCH, strlen(search) + 1, (void *)search);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.n_sortaddr = htonl(ntohl(resolver->resolver.n_sortaddr) + 1);
+ _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SORTADDR, sizeof(dns_sortaddr_t), (void *)sortaddr);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
+{
+ _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_OPTIONS, strlen(options) + 1, (void *)options);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.timeout = htonl(timeout);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ resolver->resolver.search_order = htonl(order);
+ return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_free(dns_create_resolver_t *_resolver)
+{
+ _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
+
+ free(resolver);
+ *_resolver = NULL;
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef __DNSINFO_CREATE_H__
+#define __DNSINFO_CREATE_H__
+
+
+/*
+ * These routines provide access to the systems DNS configuration
+ */
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/cdefs.h>
+
+
+#include <dnsinfo.h>
+
+
+typedef const struct __dns_create_config * dns_create_config_t;
+typedef const struct __dns_create_resolver * dns_create_resolver_t;
+
+
+__BEGIN_DECLS
+
+/*
+ * DNS configuration creation APIs
+ */
+dns_create_config_t _dns_configuration_create ();
+void _dns_configuration_add_resolver (dns_create_config_t *_config, dns_create_resolver_t _resolver);
+_Bool _dns_configuration_store (dns_create_config_t *_config);
+void _dns_configuration_free (dns_create_config_t *_config);
+
+/*
+ * DNS [resolver] configuration creation APIs
+ */
+dns_create_resolver_t _dns_resolver_create();
+void _dns_resolver_set_domain (dns_create_resolver_t *_resolver, const char *domain);
+void _dns_resolver_add_nameserver (dns_create_resolver_t *_resolver, struct sockaddr *nameserver);
+void _dns_resolver_set_port (dns_create_resolver_t *_resolver, uint32_t port); // host byte order
+void _dns_resolver_add_search (dns_create_resolver_t *_resolver, const char *search);
+void _dns_resolver_add_sortaddr (dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr);
+void _dns_resolver_set_options (dns_create_resolver_t *_resolver, const char *options);
+void _dns_resolver_set_timeout (dns_create_resolver_t *_resolver, uint32_t timeout);
+void _dns_resolver_set_order (dns_create_resolver_t *_resolver, uint32_t order);
+void _dns_resolver_free (dns_create_resolver_t *_resolver);
+
+__END_DECLS
+
+#endif __DNSINFO_CREATE_H__
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * March 9, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdlib.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+
+#include "dnsinfo_private.h"
+#include "shared_dns_info_types.h"
+
+
+__private_extern__
+const char *
+_dns_configuration_notify_key()
+{
+ return "com.apple.SystemConfiguration.dns_configuration";
+}
+
+
+__private_extern__
+mach_port_t
+_dns_configuration_server_port()
+{
+ mach_port_t server = MACH_PORT_NULL;
+ char *server_name;
+ kern_return_t status;
+
+ server_name = getenv("DNS_SERVER");
+ if (!server_name) {
+ server_name = DNS_SERVER;
+ }
+
+ status = bootstrap_look_up(bootstrap_port, server_name, &server);
+ switch (status) {
+ case BOOTSTRAP_SUCCESS :
+ /* service currently registered, "a good thing" (tm) */
+ break;
+ case BOOTSTRAP_UNKNOWN_SERVICE :
+ /* service not currently registered, try again later */
+ return MACH_PORT_NULL;
+ default :
+ mach_error("could not lookup DNS configuration info service:", status);
+ return MACH_PORT_NULL;
+ }
+
+ return server;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef __DNSINFO_PRIVATE_H__
+#define __DNSINFO_PRIVATE_H__
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <mach/mach.h>
+
+#include "dnsinfo.h"
+
+
+/*
+ * What's all of this stuff about???
+ *
+ * In order to minimize the amount of data conversions associated with
+ * storing, retrieving, and accessing the systems DNS configuration I
+ * have opted to create a memory image filled with the actual data
+ * types / structures that would be used by those applications which
+ * make use of these APIS. The implication here is that we use
+ * sockaddr's for addresses, char *'s for strings, etc.
+ *
+ * To achieve this goal the APIs which are used to store and access the
+ * configuration data build and use a single buffer of the relevant
+ * bits. When multiple instances of a given type / structure are needed
+ * we maintain a count, the actual data, and when the configuration has
+ * been unpacked, arrays of pointers to the data.
+ *
+ * In memory, the data looks as follows:
+ *
+ * +-------------------------------------------------------------------+
+ * | struct _dns_config_buf_t |
+ * +-+-------------+---------------------------------------------------+
+ * | | config | struct dns_config_t |
+ * | | +-+--------------+----------------------------------+
+ * | | | | n_resolver | int32_t | <- # of name resolvers
+ * | | | +--------------+----------------------------------+
+ * | | | | resolver | dns_resolver_t ** | <- not used during creation, filled
+ * | | | | | | in with pointer to a list of
+ * | | | | | | resolver configurations which be
+ * | | | | | | established in the "padding"
+ * | | | +--------------+----------------------------------+
+ * | | | | ... | ... |
+ * | +-------------+-+--------------+----------------------------------+
+ * | | n_attribute | uint32_t | <- how many bytes of "attribute"
+ * | | | | data is associated with the
+ * | | | | configuration
+ * |-+-------------+---------------------------------------------------+
+ * | | n_padding | uint32_t | <- how many additional bytes
+ * | | | | for arrays (of pointers), ...
+ * +-+-------------+---------------------------------------------------+
+ * | struct dns_attribute_t |
+ * |-+-------------+---------------------------------------------------+
+ * | | type | uint32_t | <- type of attribute (e.g. CONFIG_ATTRIBUTE_RESOLVER)
+ * | +-------------+---------------------------------------------------+
+ * | | length | uint32_t | <- length of the attribute
+ * | +-------------+---------------------------------------------------+
+ * | | attribute | struct _dns_resolver_buf_t | <- the attribute data (resolver configuration #1)
+ * | | +-+-------------+-----------------------------------+
+ * | | | | resolver | struct dns_resolver_t |
+ * | | | | +--------------+--------------------+
+ * | | | | | domain | char * | <- not used during creation,
+ * | | | | | | | filled in with pointer to
+ * | | | | | | | domain name in the "padding"
+ * | | | | +--------------+--------------------+
+ * | | | | | n_nameserver | int32_t | <- # of name server addresses
+ * | | | | +--------------+--------------------+
+ * | | | | | nameserver | struct sockaddr ** | <- not used during creation,
+ * | | | | | | | filled in with pointer to
+ * | | | | | | | a list of addresses which
+ * | | | | | | | will be established in the
+ * | | | | | | | "padding"
+ * | | | | +--------------+--------------------+
+ * | | | | | ... |
+ * | | +-+-------------+--------------+--------------------+
+ * | | | | n_attribute | uint32_t |
+ * | | +-+-------------+-----------------------------------+
+ * | | | | attribute | struct dns_attribute_t |
+ * | | | | +-+-----------+---------------------+
+ * | | | | | | type | uint32_t | <- type of attribute (e.g. RESOLVER_ATTRIBUTE_DOMAIN)
+ * | | | | | +-----------+---------------------+
+ * | | | | | | length | uint32_t | <- length of the attribute
+ * | | | | | +-----------+---------------------+
+ * | | | | | | attribute | | <- the attribute data ("apple.com")
+ * | | +-+-------------+-------------+---------------------+
+ * | | | | attribute | struct dns_attribute_t |
+ * | | | | +-+-----------+---------------------+
+ * | | | | | | type | uint32_t | <- type of attribute (e.g. RESOLVER_ATTRIBUTE_ADDRESS)
+ * | | | | | +-----------+---------------------+
+ * | | | | | | length | uint32_t | <- length of the attribute
+ * | | | | | +-----------+---------------------+
+ * | | | | | | attribute | | <- the attribute data ("struct sockaddr_in" #1)
+ * | | +---------------+-----------------------------------+
+ * | | | | attribute | struct dns_attribute_t |
+ * | | | | +-+-----------+---------------------+
+ * | | | | | | type | uint32_t | <- type of attribute (e.g. RESOLVER_ATTRIBUTE_ADDRESS)
+ * | | | | | +-----------+---------------------+
+ * | | | | | | length | uint32_t | <- length of the attribute
+ * | | | | | +-----------+---------------------+
+ * | | | | | | attribute | | <- the attribute data ("struct sockaddr_in" #2)
+ * | | +---------------+-----------------------------------+
+ * | | | ... |
+ * +-+-------------+---------------------------------------------------+
+ * | | attribute | struct _dns_resolver_buf_t | <- the attribute data (resolver configuration #2)
+ * | | +---------------+-----------------------------------+
+ * | | | ... |
+ * +---------------+---------------------------------------------------+
+ * | | ... |
+ * +---------------+---------------------------------------------------+
+ *
+ * When the data is unpacked the "n_padding" additional bytes
+ * specified in configuration buffer will be allocated at the
+ * end of this buffer. Arrays of pointers will be allocated
+ * within the extra space array element (an "attribute") is
+ * encountered the pointer reference will be filled in.
+ */
+
+
+// configuration buffer attributes
+enum {
+ CONFIG_ATTRIBUTE_RESOLVER = 1
+};
+
+
+// resolver buffer attributes
+enum {
+ RESOLVER_ATTRIBUTE_DOMAIN = 10,
+ RESOLVER_ATTRIBUTE_ADDRESS,
+ RESOLVER_ATTRIBUTE_SEARCH,
+ RESOLVER_ATTRIBUTE_SORTADDR,
+ RESOLVER_ATTRIBUTE_OPTIONS
+};
+
+
+typedef struct {
+ uint32_t type;
+ uint32_t length;
+ uint8_t attribute[0];
+} dns_attribute_t;
+
+
+typedef struct {
+ dns_config_t config;
+ uint32_t n_attribute;
+ uint32_t n_padding;
+ uint8_t attribute[0];
+} _dns_config_buf_t;
+
+
+typedef struct {
+ dns_resolver_t resolver;
+ uint32_t n_attribute;
+ uint8_t attribute[0];
+} _dns_resolver_buf_t;
+
+
+const char * _dns_configuration_notify_key();
+mach_port_t _dns_configuration_server_port();
+
+#endif __DNSINFO_PRIVATE_H__
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * March 9, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <notify.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <servers/bootstrap.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "dnsinfo_server.h"
+#include "dnsinfo_private.h"
+
+#include "session.h"
+
+static CFDataRef shared_dns_info = NULL;
+
+__private_extern__
+kern_return_t
+_shared_dns_infoGet(mach_port_t server, dnsDataOut_t *dataRef, mach_msg_type_number_t *dataLen)
+{
+ *dataRef = NULL;
+ *dataLen = 0;
+
+ if (shared_dns_info != NULL) {
+ if (!_SCSerializeData(shared_dns_info, (void **)dataRef, (CFIndex *)dataLen)) {
+ return KERN_FAILURE;
+ }
+ }
+
+ return KERN_SUCCESS;
+}
+
+
+__private_extern__
+kern_return_t
+_shared_dns_infoSet(mach_port_t server, dnsData_t dataRef, mach_msg_type_number_t dataLen)
+{
+ CFDataRef new_dns_info = NULL;
+ const char *notify_key;
+ serverSessionRef mySession = getSession(server);
+
+ if ((dataRef != NULL) && (dataLen > 0)) {
+ if (!_SCUnserializeData(&new_dns_info, (void *)dataRef, dataLen)) {
+ goto error;
+ }
+ }
+
+ if (mySession->callerEUID != 0) {
+ goto error;
+ }
+
+ if (shared_dns_info != NULL) CFRelease(shared_dns_info);
+ shared_dns_info = new_dns_info;
+
+ notify_key = _dns_configuration_notify_key();
+ if (notify_key != NULL) {
+ uint32_t status;
+
+ status = notify_post(notify_key);
+ if (status != NOTIFY_STATUS_OK) {
+ SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: %d"), status);
+ // notification posting failures are non-fatal
+ }
+ }
+
+ return KERN_SUCCESS;
+
+ error :
+
+ if (new_dns_info != NULL) CFRelease(new_dns_info);
+ return KERN_FAILURE;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef _S_DNSINFO_SERVER_H
+#define _S_DNSINFO_SERVER_H
+
+#include <sys/cdefs.h>
+#include <mach/mach.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "shared_dns_info_types.h"
+
+__BEGIN_DECLS
+
+kern_return_t _shared_dns_infoGet (mach_port_t server,
+ dnsDataOut_t *dataRef,
+ mach_msg_type_number_t *dataLen);
+
+kern_return_t _shared_dns_infoSet (mach_port_t server,
+ dnsData_t dataRef,
+ mach_msg_type_number_t dataLen);
+
+__END_DECLS
+
+#endif /* !_S_DNSINFO_SERVER_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * February 9, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+subsystem shared_dns_info 21000;
+serverprefix _;
+
+import "shared_dns_info_types.h";
+
+/*
+ * DNS configuration (client->server)
+ */
+type dnsData = ^ array [] of MACH_MSG_TYPE_BYTE
+ ctype : dnsData_t;
+
+/*
+ * DNS configuration (server->client)
+ */
+type dnsDataOut = ^ array [] of MACH_MSG_TYPE_BYTE
+ ctype : dnsDataOut_t;
+
+/*
+ * DNS configuration API's
+ */
+
+routine shared_dns_infoGet ( server : mach_port_t;
+ out data : dnsDataOut, dealloc);
+
+routine shared_dns_infoSet ( server : mach_port_t;
+ data : dnsData);
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+#ifndef _SHARED_DNS_INFO_TYPES_H
+#define _SHARED_DNS_INFO_TYPES_H
+
+/*
+ * Keep IPC functions private to the framework
+ */
+#ifdef mig_external
+#undef mig_external
+#endif
+#define mig_external __private_extern__
+
+/*
+ * Mach server port name
+ */
+#define DNS_SERVER "com.apple.SystemConfiguration.configd"
+
+/*
+ * Input arguments: DNS configuration
+ * (sent as out-of-line data in a message)
+ */
+typedef const char * dnsData_t;
+
+/* Output arguments: DNS configuration
+ * (sent as out-of-line data in a message)
+ */
+typedef char * dnsDataOut_t;
+
+#endif /* !_SHARED_DNS_INFO_TYPES_H */
--- /dev/null
+#!/bin/sh
+# get-mobility-info
+#
+# Collect system & network configuration information.
+#
+
+OUT=mobility-config-$$
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+
+PRIV=""
+if [ ${EUID} -ne 0 ]; then
+ PRIV="sudo"
+fi
+
+cd /tmp
+mkdir ${OUT}
+
+#
+# processes
+#
+ps axlww > ${OUT}/ps 2>&1
+
+#
+# network interface configuration
+#
+ifconfig -a -b > ${OUT}/ifconfig 2>&1
+
+#
+# network route configuration
+#
+netstat -n -r >> ${OUT}/netstat 2>&1
+
+#
+# DHCP configuration
+#
+for if in `ifconfig -l`
+do
+ case ${if} in
+ lo* ) ;;
+ en* ) ipconfig getpacket ${if} > ${OUT}/ipconfig-${if} 2>&1
+ ;;
+ esac
+done
+
+#
+# OS info
+#
+if [ -e /System/Library/CoreServices/SystemVersion.plist ]; then
+ cat /System/Library/CoreServices/SystemVersion.plist \
+ > ${OUT}/SystemVersion.plist 2>&1
+fi
+if [ -e /System/Library/CoreServices/ServerVersion.plist ]; then
+ cat /System/Library/CoreServices/ServerVersion.plist \
+ > ${OUT}/ServerVersion.plist 2>&1
+fi
+
+#
+# IOKit info
+#
+ioreg -l > ${OUT}/ioreg 2>&1
+
+#
+# Host configuration
+#
+hostinfo > ${OUT}/hostinfo 2>&1
+if [ -e /etc/hostconfig ]; then
+ cat /etc/hostconfig > ${OUT}/etc.hostconfig 2>&1
+fi
+
+#
+# DNS configuration
+#
+scutil --dns > ${OUT}/dns-configuration 2>&1
+if [ -e /etc/resolv.conf ]; then
+ cat /etc/resolv.conf > ${OUT}/etc.resolv.conf 2>&1
+fi
+if [ -e /var/run/resolv.conf ]; then
+ cat /var/run/resolv.conf > ${OUT}/var.run.resolv.conf 2>&1
+fi
+
+#
+# NetInfo configuration
+#
+niutil -statistics . > ${OUT}/netinfo-statistics 2>&1
+if [ -f /var/run/niconfig_local.xml ]; then
+ cat /var/run/niconfig_local.xml > ${OUT}/niconfig_local.xml 2>&1
+fi
+
+#
+# System / network preferences
+#
+for f in \
+ /Library/Preferences/SystemConfiguration/NetworkInterfaces.plist \
+ /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist \
+ /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist \
+ /Library/Preferences/SystemConfiguration/com.apple.nat.plist \
+ /Library/Preferences/SystemConfiguration/preferences.plist \
+ /Library/Preferences/com.apple.sharing.firewall.plist \
+
+do
+ if [ -e ${f} ]; then
+ b=`basename $f`
+ cat ${f} > ${OUT}/${b} 2>&1
+ fi
+done
+
+#
+# configd's cache
+#
+${PRIV} scutil -p <<_END_OF_INPUT
+open
+snapshot
+quit
+_END_OF_INPUT
+if [ -f /var/tmp/configd-store.xml ]; then
+ cp /var/tmp/configd-store.xml ${OUT}/configd-store.xml
+fi
+if [ -f /var/tmp/configd-pattern.xml ]; then
+ cp /var/tmp/configd-pattern.xml ${OUT}/configd-pattern.xml
+fi
+if [ -f /var/tmp/configd-session.xml ]; then
+ cp /var/tmp/configd-session.xml ${OUT}/configd-session.xml
+fi
+
+#
+# network reachability
+#
+scutil -d -v -r www.apple.com > ${OUT}/reachability-info 2>&1
+if [ -f /usr/bin/dig ]; then
+ dig -t any -c any www.apple.com > ${OUT}/dig-results 2>&1
+fi
+
+#
+# mounted filesystems
+#
+mount > ${OUT}/mounted-filesystems 2>&1
+
+#
+# system log
+#
+tail -1000 /var/log/system.log > ${OUT}/system.log
+
+#
+# ppp log
+#
+if [ -f /var/log/ppp.log ]; then
+ cp /var/log/ppp.log ${OUT}/ppp.log
+fi
+
+#
+# kernel extensions statistic
+#
+if [ -f /usr/sbin/kextstat ]; then
+ kextstat > ${OUT}/kextstat 2>&1
+elif [ -f /usr/sbin/kmodstat ]; then
+ kmodstat > ${OUT}/kmodstat 2>&1
+fi
+
+#
+# network statistics
+#
+echo "#" >> ${OUT}/network-statistics
+echo "# netstat -n -a -A -f inet" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+netstat -n -a -A -f inet >> ${OUT}/network-statistics 2>&1
+echo "#" >> ${OUT}/network-statistics
+echo "# lsof -n -i -P" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+lsof -n -i -P >> ${OUT}/network-statistics 2>&1
+echo "#" >> ${OUT}/network-statistics
+echo "# netstat -s" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+netstat -s >> ${OUT}/network-statistics 2>&1
+echo "#" >> ${OUT}/network-statistics
+echo "# netstat -m" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+netstat -m >> ${OUT}/network-statistics 2>&1
+echo "#" >> ${OUT}/network-statistics
+echo "# netstat -i -n -d" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+netstat -i -n -d >> ${OUT}/network-statistics 2>&1
+echo "#" >> ${OUT}/network-statistics
+echo "# ipfw -at show" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+ipfw -at show >> ${OUT}/network-statistics 2>&1
+echo "#" >> ${OUT}/network-statistics
+echo "# appletalk -s" >> ${OUT}/network-statistics
+echo "#" >> ${OUT}/network-statistics
+appletalk -s >> ${OUT}/network-statistics 2>&1
+
+#
+# system usage statistics
+#
+echo "#" > ${OUT}/system-statistics
+echo "# uptime" >> ${OUT}/system-statistics
+echo "#" >> ${OUT}/system-statistics
+uptime >> ${OUT}/system-statistics 2>&1
+echo "#" >> ${OUT}/system-statistics
+echo "# pstat -t" >> ${OUT}/system-statistics
+echo "#" >> ${OUT}/system-statistics
+pstat -t >> ${OUT}/system-statistics 2>&1
+echo "#" >> ${OUT}/system-statistics
+echo "# sysctl -a" >> ${OUT}/system-statistics
+echo "#" >> ${OUT}/system-statistics
+sysctl -a >> ${OUT}/system-statistics 2>&1
+echo "#" >> ${OUT}/system-statistics
+echo "# zprint" >> ${OUT}/system-statistics
+echo "#" >> ${OUT}/system-statistics
+zprint >> ${OUT}/system-statistics 2>&1
+echo "#" >> ${OUT}/system-statistics
+echo "# top -l5 -s2" >> ${OUT}/system-statistics
+echo "#" >> ${OUT}/system-statistics
+ echo ""
+ echo "Please wait, collecting statistics"
+ echo ""
+top -s 2 -l 5 >> ${OUT}/system-statistics 2>&1
+
+#
+# collect crash reports
+#
+for daemon in bootpd configd pppd
+do
+ LOG=${daemon}.crash.log
+ if [ -e /Library/Logs/CrashReporter/${LOG} ]; then
+ cat /Library/Logs/CrashReporter/${LOG} > ${OUT}/${LOG} 2>&1
+ fi
+done
+
+#
+# collect everything into a single archive
+#
+tar cfz ${OUT}.tar.gz ${OUT}
+rm -rf ${OUT}
+
+echo "Network data collected to /tmp/${OUT}.tar.gz"
<key>LCPEchoInterval</key>
<integer>10</integer>
<key>Logfile</key>
- <string>/tmp/ppp.log</string>
+ <string>/var/log/ppp.log</string>
<key>VerboseLogging</key>
<integer>0</integer>
<key>__INACTIVE__</key>
+++ /dev/null
-#
-# 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 = scselect
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = scselect.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
- h.template
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS =
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration
-
-
-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 $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
+++ /dev/null
-###############################################################################
-# Makefile.postamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile, which is imported after all other makefiles, to
-# override attributes for a project's Makefile environment. This allows you
-# to take advantage of the environment set up by the other Makefiles.
-# You can also define custom rules at the end of this file.
-#
-###############################################################################
-#
-# These variables are exported by the standard makefiles and can be
-# used in any customizations you make. They are *outputs* of
-# the Makefiles and should be used, not set.
-#
-# PRODUCTS: products to install. All of these products will be placed in
-# the directory $(DSTROOT)$(INSTALLDIR)
-# GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-# OFILE_DIR: Directory into which .o object files are generated.
-# DERIVED_SRC_DIR: Directory used for all other derived files
-#
-# ALL_CFLAGS: flags to pass when compiling .c files
-# ALL_MFLAGS: flags to pass when compiling .m files
-# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files
-# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files
-# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files
-# ALL_LDFLAGS: flags to pass when linking object files
-# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files
-# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files
-# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files
-# ALL_YFLAGS: flags to pass when processing .y (yacc) files
-# ALL_LFLAGS: flags to pass when processing .l (lex) files
-#
-# NAME: name of application, bundle, subproject, palette, etc.
-# LANGUAGES: langages in which the project is written (default "English")
-# English_RESOURCES: localized resources (e.g. nib's, images) of project
-# GLOBAL_RESOURCES: non-localized resources of project
-#
-# SRCROOT: base directory in which to place the new source files
-# SRCPATH: relative path from SRCROOT to present subdirectory
-#
-# INSTALLDIR: Directory the product will be installed into by 'install' target
-# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-#
-# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost)
-# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults
-# to -g)
-# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG)
-# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults
-# to -O)
-# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults
-# to -pg -DPROFILE)
-# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to
-# the include path (defaults to -I.)
-# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-# passed to ld/libtool (defaults to nothing)
-WARNING_CFLAGS=-Wall
-
-
-# Library and Framework projects only:
-# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked
-# against the framework will run against the correct version even if
-# the current version of the framework changes. You may override this
-# to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-# development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
- # User/group ownership
-#INSTALL_AS_GROUP = wheel
- # (probably want to set both of these)
-INSTALL_PERMISSIONS = 4555
- # If set, 'install' chmod's executable to this
-
-
-# Options to strip. Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here. Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where
-# derived files should go.
-#
+++ /dev/null
-###############################################################################
-# Makefile.preamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile for configuring the standard application makefiles
-# associated with ProjectBuilder. It is included before the main makefile.
-# In Makefile.preamble you set attributes for a project, so they are available
-# to the project's makefiles. In contrast, you typically write additional rules or
-# override built-in behavior in the Makefile.postamble.
-#
-# Each directory in a project tree (main project plus subprojects) should
-# have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-# MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults: The OTHER_* variables will be
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible. To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler
-# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-# .cc, .cxx, .C, and .M files. There is no need to respecify the
-# flags in OTHER_MFLAGS, etc.
-# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files
-# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files
-# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files
-# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when
-# precompiling header files
-# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool
-# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap
-# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen
-# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc
-# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every
-# stage of the make:
-#
-# BEFORE_PREBUILD: targets to build before installing headers for a subproject
-# AFTER_PREBUILD: targets to build after installing headers for a subproject
-# BEFORE_BUILD_RECURSION: targets to make before building subprojects
-# BEFORE_BUILD: targets to make before a build, but after subprojects
-# AFTER_BUILD: targets to make after a build
-#
-# BEFORE_INSTALL: targets to build before installing the product
-# AFTER_INSTALL: targets to build after installing the product
-# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-# AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-# BEFORE_INSTALLHDRS: targets to build before installing headers for a
-# subproject
-# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-# BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-# AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-# BEFORE_DEPEND: targets to build before building dependencies for a
-# subproject
-# AFTER_DEPEND: targets to build after building dependencies for a
-# subproject
-#
-# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-# updated every time the project is built. If NO, the dependency
-# file is only built when the depend target is invoked.
-
-# Framework-related variables:
-# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the framework's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-# PUBLIC_HEADER_DIR: Determines where public exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically. For library projects you should
-# set this to something like /Developer/Headers/$(NAME). Do not set
-# this variable for framework projects unless you do not want the
-# header files included in the framework.
-# PRIVATE_HEADER_DIR: Determines where private exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically.
-# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines
-# whether the libraries produced are statically linked when they
-# are used or if they are dynamically loadable. This defaults to
-# DYNAMIC.
-# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the library's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-#
-# INSTALL_AS_USER: owner of the intalled products (default root)
-# INSTALL_AS_GROUP: group of the installed products (default wheel)
-# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-# passed on the command line to recursive invocations of make. Note that
-# the values in OTHER_*FLAGS are inherited by subprojects automatically --
-# you do not have to (and shouldn't) add OTHER_*FLAGS to
-# OTHER_RECURSIVE_VARIABLES.
-
-# Additional headers to export beyond those in the PB.project:
-# OTHER_PUBLIC_HEADERS
-# OTHER_PROJECT_HEADERS
-# OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-# OTHER_RESOURCES: (non-localized) resources for this project
-# OTHER_OFILES: relocatables to be linked into this project
-# OTHER_LIBS: more libraries to link against
-# OTHER_PRODUCT_DEPENDS: other dependencies of this project
-# OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-# OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-# BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed. By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object). Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
+++ /dev/null
-{
- DYNAMIC_CODE_GEN = YES;
- FILESTABLE = {
- FRAMEWORKS = ("CoreFoundation.framework", "SystemConfiguration.framework");
- "H_FILES" = ();
- "OTHER_LINKED" = ("scselect.c");
- "OTHER_SOURCES" = (
- "Makefile.preamble",
- Makefile,
- "Makefile.postamble",
- "m.template",
- "h.template"
- );
- "PRECOMPILED_HEADERS" = ();
- "PROJECT_HEADERS" = ();
- "PUBLIC_HEADERS" = ();
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
- NEXTSTEP_BUILDTOOL = /usr/bin/gnumake;
- NEXTSTEP_INSTALLDIR = /usr/sbin;
- NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
- NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
- PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make;
- PDO_UNIX_INSTALLDIR = /bin;
- PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac";
- PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = scselect;
- PROJECTTYPE = Tool;
- PROJECTVERSION = 2.8;
- WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make;
- WINDOWS_INSTALLDIR = /Library/Executables;
- WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
- WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
-}
+++ /dev/null
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
+++ /dev/null
-$$ Lines starting with $$ are not inserted into newly created files
-$$ The following substitutions are made:
-$$
-$$ $FILENAME$ e.g. foo.m
-$$ $FILENAMESANSEXTENSION$ e.g. foo
-$$ $DIRECTORY$ e.g. /tmp/MyNewApp
-$$ $PROJECTNAME$ e.g. MyNewApp
-$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj
-$$ $USERNAME$ e.g. mwagner
-$$ $DATE$ e.g. Jan-1-1994
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import "$FILENAMESANSEXTENSION$.h"
-
-@implementation $FILENAMESANSEXTENSION$
-
-@end
--- /dev/null
+.\"
+.\" @(#)scselect.8
+.\"
+.Dd November 4, 2003
+.Dt SCSELECT 8
+.Os Mac OS X
+.Sh NAME
+.Nm scselect
+.Nd Select system configuration
+.Qq location
+.Sh SYNOPSIS
+.Nm
+.Op Fl n
+.Op Ar new-location-name
+.Sh DESCRIPTION
+.Nm
+provides access to the system configuration sets, commonly referred to as
+.Qq locations .
+When invoked with no arguments,
+.Nm
+displays the names and associated identifiers for each defined
+.Qq location
+and indicates which is currently active.
+.Nm
+also allows the user to select or change the active
+.Qq location
+by specifying its name or identifier.
+Changing the
+.Qq location
+causes an immediate system re-configuration, unless the
+.Fl n
+option is supplied.
+.Pp
+At present, the majority of preferences associated with a
+.Qq location
+relate to the system's network configuration.
+.Pp
+The command line options are as follows:
+.Bl -tag -width xx
+.It Fl n
+Delay changing the system's
+.Qq location
+until the next system boot (or the next time that the system configuration
+preferences are changed).
+.It Ar new-location-name
+If not specified, a list of the available
+.Qq location
+names and associated identifiers will be reported on standard output.
+If specified, this argument is matched with the
+.Qq location
+names and identifiers and the matching set is activated.
+.El
+.Sh SEE ALSO
+.Xr configd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in Mac OS X Public Beta.
#include <Security/AuthSession.h>
-Boolean apply = TRUE;
+static Boolean apply = TRUE;
-static struct option longopts[] = {
+static const struct option longopts[] = {
// { "debug", no_argument, 0, 'd' },
// { "verbose", no_argument, 0, 'v' },
// { "do-not-apply", no_argument, 0, 'n' },
static Boolean
isAdmin()
{
- gid_t groups[NGROUPS_MAX];
- int ngroups;
-
- if (getuid() == 0) {
- return TRUE; // if "root"
- }
-
- ngroups = getgroups(NGROUPS_MAX, groups);
- if(ngroups > 0) {
- struct group *adminGroup;
-
- adminGroup = getgrnam("admin");
- if (adminGroup != NULL) {
- gid_t adminGid = adminGroup->gr_gid;
- int i;
-
- for (i = 0; i < ngroups; i++) {
- if (groups[i] == adminGid) {
- return TRUE; // if a member of group "admin"
- }
- }
- }
- }
-
- return FALSE;
+ gid_t groups[NGROUPS_MAX];
+ int ngroups;
+
+ if (getuid() == 0) {
+ return TRUE; // if "root"
+ }
+
+ ngroups = getgroups(NGROUPS_MAX, groups);
+ if(ngroups > 0) {
+ struct group *adminGroup;
+
+ adminGroup = getgrnam("admin");
+ if (adminGroup != NULL) {
+ gid_t adminGid = adminGroup->gr_gid;
+ int i;
+
+ for (i = 0; i < ngroups; i++) {
+ if (groups[i] == adminGid) {
+ return TRUE; // if a member of group "admin"
+ }
+ }
+ }
+ }
+
+ return FALSE;
}
static Boolean
hasLocalConsoleAccess()
{
- OSStatus error;
- SecuritySessionId sessionID = 0;
- SessionAttributeBits attributeBits = 0;
-
- error = SessionGetInfo(callerSecuritySession, &sessionID, &attributeBits);
- if (error != noErr) {
- /* Security check failed, must not permit access */
- return FALSE;
- }
+ OSStatus error;
+ SecuritySessionId sessionID = 0;
+ SessionAttributeBits attributeBits = 0;
+
+ error = SessionGetInfo(callerSecuritySession, &sessionID, &attributeBits);
+ if (error != noErr) {
+ /* Security check failed, must not permit access */
+ return FALSE;
+ }
- return (attributeBits & (sessionHasGraphicAccess|sessionIsRemote)) == sessionHasGraphicAccess;
+ return (attributeBits & (sessionHasGraphicAccess|sessionIsRemote)) == sessionHasGraphicAccess;
}
CFStringRef newSet = NULL; /* set key */
CFStringRef newSetUDN = NULL; /* user defined name */
CFStringRef prefix;
- SCPreferencesRef session;
+ SCPreferencesRef prefs;
CFDictionaryRef sets;
CFIndex nSets;
const void **setKeys = NULL;
? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman)
: CFSTR("");
- session = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
- if (!session) {
+ prefs = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
+ if (prefs == NULL) {
SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
exit (1);
}
newSet = str;
}
- sets = SCPreferencesGetValue(session, kSCPrefSets);
- if (!sets) {
- SCPrint(TRUE, stderr, CFSTR("SCPreferencesGetValue(...,%s,...) failed\n"));
+ sets = SCPreferencesGetValue(prefs, kSCPrefSets);
+ if (sets == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("No network sets defined.\n"));
exit (1);
}
- current = SCPreferencesGetValue(session, kSCPrefCurrentSet);
- if (current) {
+ current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+ if (current != NULL) {
if (CFStringHasPrefix(current, prefix)) {
CFMutableStringRef tmp;
if (CFEqual(newSet, key)) {
newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName);
- if (newSetUDN) CFRetain(newSetUDN);
+ if (newSetUDN != NULL) CFRetain(newSetUDN);
current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet);
goto found;
}
found :
if (!(isAdmin() || hasLocalConsoleAccess())) {
- SCPrint(TRUE, stderr,
- CFSTR("Only local console users and administrators can change locations\n"));
- exit (EX_NOPERM);
+ SCPrint(TRUE, stderr,
+ CFSTR("Only local console users and administrators can change locations\n"));
+ exit (EX_NOPERM);
}
-
- if (!SCPreferencesSetValue(session, kSCPrefCurrentSet, current)) {
+
+ if (!SCPreferencesSetValue(prefs, kSCPrefCurrentSet, current)) {
SCPrint(TRUE, stderr,
CFSTR("SCPreferencesSetValue(...,%@,%@) failed\n"),
kSCPrefCurrentSet,
exit (1);
}
- if (!SCPreferencesCommitChanges(session)) {
+ if (!SCPreferencesCommitChanges(prefs)) {
SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed\n"));
exit (1);
}
if (apply) {
- if (!SCPreferencesApplyChanges(session)) {
+ if (!SCPreferencesApplyChanges(prefs)) {
SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed\n"));
exit (1);
}
}
- CFRelease(session);
+ CFRelease(prefs);
SCPrint(TRUE, stdout,
CFSTR("%@ updated to %@ (%@)\n"),
+++ /dev/null
-#
-# 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 = scutil
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-HFILES = scutil.h commands.h dictionary.h session.h cache.h notify.h\
- tests.h prefs.h
-
-CFILES = scutil.c commands.c dictionary.c session.c cache.c notify.c\
- tests.c prefs.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
- h.template
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS =
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-NEXTSTEP_PB_LDFLAGS = -ledit
-FRAMEWORKS = -framework CoreFoundation -framework SystemConfiguration
-
-
-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 $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
+++ /dev/null
-###############################################################################
-# Makefile.postamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile, which is imported after all other makefiles, to
-# override attributes for a project's Makefile environment. This allows you
-# to take advantage of the environment set up by the other Makefiles.
-# You can also define custom rules at the end of this file.
-#
-###############################################################################
-#
-# These variables are exported by the standard makefiles and can be
-# used in any customizations you make. They are *outputs* of
-# the Makefiles and should be used, not set.
-#
-# PRODUCTS: products to install. All of these products will be placed in
-# the directory $(DSTROOT)$(INSTALLDIR)
-# GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-# OFILE_DIR: Directory into which .o object files are generated.
-# DERIVED_SRC_DIR: Directory used for all other derived files
-#
-# ALL_CFLAGS: flags to pass when compiling .c files
-# ALL_MFLAGS: flags to pass when compiling .m files
-# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files
-# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files
-# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files
-# ALL_LDFLAGS: flags to pass when linking object files
-# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files
-# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files
-# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files
-# ALL_YFLAGS: flags to pass when processing .y (yacc) files
-# ALL_LFLAGS: flags to pass when processing .l (lex) files
-#
-# NAME: name of application, bundle, subproject, palette, etc.
-# LANGUAGES: langages in which the project is written (default "English")
-# English_RESOURCES: localized resources (e.g. nib's, images) of project
-# GLOBAL_RESOURCES: non-localized resources of project
-#
-# SRCROOT: base directory in which to place the new source files
-# SRCPATH: relative path from SRCROOT to present subdirectory
-#
-# INSTALLDIR: Directory the product will be installed into by 'install' target
-# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget
-# to prefix this with DSTROOT when you use it.
-#
-# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost)
-# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults
-# to -g)
-# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG)
-# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults
-# to -O)
-# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults
-# to -pg -DPROFILE)
-# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to
-# the include path (defaults to -I.)
-# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-# passed to ld/libtool (defaults to nothing)
-WARNING_CFLAGS=-Wall
-
-
-# Library and Framework projects only:
-# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked
-# against the framework will run against the correct version even if
-# the current version of the framework changes. You may override this
-# to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-# development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
- # User/group ownership
-#INSTALL_AS_GROUP = wheel
- # (probably want to set both of these)
-#INSTALL_PERMISSIONS =
- # If set, 'install' chmod's executable to this
-
-
-# Options to strip. Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here. Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where
-# derived files should go.
-#
+++ /dev/null
-###############################################################################
-# Makefile.preamble
-# Copyright 1997, Apple Computer, Inc.
-#
-# Use this makefile for configuring the standard application makefiles
-# associated with ProjectBuilder. It is included before the main makefile.
-# In Makefile.preamble you set attributes for a project, so they are available
-# to the project's makefiles. In contrast, you typically write additional rules or
-# override built-in behavior in the Makefile.postamble.
-#
-# Each directory in a project tree (main project plus subprojects) should
-# have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-# MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults: The OTHER_* variables will be
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible. To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler
-# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-# .cc, .cxx, .C, and .M files. There is no need to respecify the
-# flags in OTHER_MFLAGS, etc.
-# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files
-# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files
-# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files
-# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when
-# precompiling header files
-# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool
-# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap
-# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen
-# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc
-# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every
-# stage of the make:
-#
-# BEFORE_PREBUILD: targets to build before installing headers for a subproject
-# AFTER_PREBUILD: targets to build after installing headers for a subproject
-# BEFORE_BUILD_RECURSION: targets to make before building subprojects
-# BEFORE_BUILD: targets to make before a build, but after subprojects
-# AFTER_BUILD: targets to make after a build
-#
-# BEFORE_INSTALL: targets to build before installing the product
-# AFTER_INSTALL: targets to build after installing the product
-# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-# AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-# BEFORE_INSTALLHDRS: targets to build before installing headers for a
-# subproject
-# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-# BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-# AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-# BEFORE_DEPEND: targets to build before building dependencies for a
-# subproject
-# AFTER_DEPEND: targets to build after building dependencies for a
-# subproject
-#
-# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-# updated every time the project is built. If NO, the dependency
-# file is only built when the depend target is invoked.
-
-# Framework-related variables:
-# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the framework's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-# PUBLIC_HEADER_DIR: Determines where public exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically. For library projects you should
-# set this to something like /Developer/Headers/$(NAME). Do not set
-# this variable for framework projects unless you do not want the
-# header files included in the framework.
-# PRIVATE_HEADER_DIR: Determines where private exported header files
-# should be installed. Do not include $(DSTROOT) in this value --
-# it is prefixed automatically.
-# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines
-# whether the libraries produced are statically linked when they
-# are used or if they are dynamically loadable. This defaults to
-# DYNAMIC.
-# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates
-# where to put the library's DLL. This variable defaults to
-# $(INSTALLDIR)/../Executables
-#
-# INSTALL_AS_USER: owner of the intalled products (default root)
-# INSTALL_AS_GROUP: group of the installed products (default wheel)
-# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-# passed on the command line to recursive invocations of make. Note that
-# the values in OTHER_*FLAGS are inherited by subprojects automatically --
-# you do not have to (and shouldn't) add OTHER_*FLAGS to
-# OTHER_RECURSIVE_VARIABLES.
-
-# Additional headers to export beyond those in the PB.project:
-# OTHER_PUBLIC_HEADERS
-# OTHER_PROJECT_HEADERS
-# OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-# OTHER_RESOURCES: (non-localized) resources for this project
-# OTHER_OFILES: relocatables to be linked into this project
-# OTHER_LIBS: more libraries to link against
-# OTHER_PRODUCT_DEPENDS: other dependencies of this project
-# OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-# OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-# BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed. By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object). Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-# DSTROOT = $(HOME)
+++ /dev/null
-{
- "DYNAMIC_CODE_GEN" = YES;
- FILESTABLE = {
- FRAMEWORKS = ("CoreFoundation.framework", "SystemConfiguration.framework");
- FRAMEWORKSEARCH = ();
- "H_FILES" = (
- "scutil.h",
- "commands.h",
- "dictionary.h",
- "session.h",
- "cache.h",
- "notify.h",
- "tests.h",
- "prefs.h"
- );
- "OTHER_LINKED" = (
- "scutil.c",
- "commands.c",
- "dictionary.c",
- "session.c",
- "cache.c",
- "notify.c",
- "tests.c",
- "prefs.c"
- );
- "OTHER_SOURCES" = (
- "Makefile.preamble",
- Makefile,
- "Makefile.postamble",
- "m.template",
- "h.template"
- );
- "PRECOMPILED_HEADERS" = ();
- "PROJECT_HEADERS" = ();
- "PUBLIC_HEADERS" = ();
- SUBPROJECTS = ();
- };
- LANGUAGE = English;
- MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
- "NEXTSTEP_BUILDTOOL" = "/usr/bin/gnumake";
- "NEXTSTEP_INSTALLDIR" = "/usr/sbin";
- "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac";
- "NEXTSTEP_LINKEROPTIONS" = "-ledit";
- "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc";
- "PDO_UNIX_BUILDTOOL" = "$NEXT_ROOT/Developer/bin/make";
- "PDO_UNIX_INSTALLDIR" = "/bin";
- "PDO_UNIX_JAVA_COMPILER" = "$(JDKBINDIR)/javac";
- "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc";
- PROJECTNAME = scutil;
- PROJECTTYPE = Tool;
- PROJECTVERSION = "2.8";
- "WINDOWS_BUILDTOOL" = "$NEXT_ROOT/Developer/Executables/make";
- "WINDOWS_INSTALLDIR" = "/Library/Executables";
- "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe";
- "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc";
-}
}
+__private_extern__
void
do_list(int argc, char **argv)
{
pattern = CFStringCreateWithCString(NULL,
(argc >= 1) ? argv[0] : ".*",
- kCFStringEncodingMacRoman);
+ kCFStringEncodingUTF8);
list = SCDynamicStoreCopyKeyList(store, pattern);
CFRelease(pattern);
}
+__private_extern__
void
do_add(int argc, char **argv)
{
CFStringRef key;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (argc < 2) {
if (!SCDynamicStoreAddValue(store, key, value)) {
}
+__private_extern__
void
do_get(int argc, char **argv)
{
CFStringRef key;
CFPropertyListRef newValue;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
newValue = SCDynamicStoreCopyValue(store, key);
CFRelease(key);
if (!newValue) {
}
+__private_extern__
void
do_set(int argc, char **argv)
{
CFStringRef key;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (!SCDynamicStoreSetValue(store, key, value)) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
}
}
+__private_extern__
void
do_show(int argc, char **argv)
{
CFStringRef key;
CFPropertyListRef newValue;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (argc == 1) {
newValue = SCDynamicStoreCopyValue(store, key);
}
+__private_extern__
void
do_remove(int argc, char **argv)
{
CFStringRef key;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (!SCDynamicStoreRemoveValue(store, key)) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
}
}
+__private_extern__
void
do_notify(int argc, char **argv)
{
CFStringRef key;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (!SCDynamicStoreNotifyValue(store, key)) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
}
}
+__private_extern__
void
do_touch(int argc, char **argv)
{
CFStringRef key;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
if (!SCDynamicStoreTouchValue(store, key)) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
}
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "dictionary.h"
#include "session.h"
#include "cache.h"
-#include "notify.h"
+#include "notifications.h"
#include "tests.h"
+#include "net.h"
#include "SCDynamicStoreInternal.h"
-const cmdInfo commands[] = {
+__private_extern__
+const cmdInfo commands_store[] = {
/* cmd minArgs maxArgs func group ctype */
/* usage */
{ "f.read", 1, 1, do_readFile, 0, 0,
" f.read file : process commands from file" },
+ { "quit", 0, 0, do_quit, 0, 0,
+ " quit : quit" },
+
+ { "q", 0, 0, do_quit, 0, -1,
+ NULL },
+
+ { "exit", 0, 0, do_quit, 0, -1,
+ NULL },
+
/* local dictionary manipulation commands */
{ "d.init", 0, 0, do_dictInit, 1, 0,
{ "d.add", 2, 101, do_dictSetKey, 1, 0,
" d.add key [*#?] val [v2 ...] : add information to dictionary\n"
- " (*=array, #=number, ?=boolean)" },
+ " (*=array, #=number, ?=boolean)" },
{ "d.remove", 1, 1, do_dictRemoveKey, 1, 0,
" d.remove key : remove key from dictionary" },
/* data store manipulation commands */
- { "open", 0, 0, do_open, 2, 0,
- " open : open a session with \"configd\"" },
+ { "open", 0, 1, do_open, 2, 1,
+ " open [\"temporary\"] : open a session with \"configd\"" },
- { "close", 0, 0, do_close, 2, 0,
+ { "close", 0, 0, do_close, 2, 1,
" close : close current \"configd\" session" },
{ "lock", 0, 0, do_lock, 3, 1,
" list [pattern] : list keys in data store" },
{ "add", 1, 2, do_add, 4, 0,
- " add key [\"temporary\"] : add key in data store w/current dict" },
+ " add key [\"temporary\"] : add key in data store w/current dict" },
{ "get", 1, 1, do_get, 4, 0,
" get key : get dict from data store w/key" },
{ "set", 1, 1, do_set, 4, 0,
- " set key : set key in data store w/current dict" },
+ " set key : set key in data store w/current dict" },
{ "show", 1, 2, do_show, 4, 0,
" show key [\"pattern\"] : show values in data store w/key" },
" n.list [\"pattern\"] : list notification keys" },
{ "n.add", 1, 2, do_notify_add, 5, 0,
- " n.add key [\"pattern\"] : add notification key" },
+ " n.add key [\"pattern\"] : add notification key" },
{ "n.remove", 1, 2, do_notify_remove, 5, 0,
" n.remove key [\"pattern\"] : remove notification key" },
{ "n.cancel", 0, 1, do_notify_cancel, 5, 0,
" n.cancel : cancel notification requests" },
- { "snapshot", 0, 0, do_snapshot, 9, 2,
- " snapshot : save snapshot of store and session data" },
+ { "snapshot", 0, 0, do_snapshot, 99, 2,
+ " snapshot : save snapshot of store and session data" }
};
+__private_extern__
+const int nCommands_store = (sizeof(commands_store)/sizeof(cmdInfo));
+
+
+__private_extern__
+const cmdInfo commands_prefs[] = {
+ /* cmd minArgs maxArgs func group ctype */
+ /* usage */
+
+ { "help", 0, 0, do_help, 0, 0,
+ " help : list available commands" },
+
+ { "f.read", 1, 1, do_readFile, 0, 0,
+ " f.read file : process commands from file" },
+
+ { "quit", 0, 1, do_net_quit, 0, 0,
+ " quit [!] : quit" },
+
+ { "q", 0, 1, do_net_quit, 0, -1,
+ NULL },
+
+ { "exit", 0, 1, do_net_quit, 0, -1,
+ NULL },
+
+ /* network configuration manipulation commands */
+
+ { "open", 0, 1, do_net_open, 2, 1,
+ " open : open the network configuration" },
+
+ { "commit", 0, 0, do_net_commit, 2, 0,
+ " commit : commit any changes" },
+
+ { "apply", 0, 0, do_net_apply, 2, 0,
+ " apply : apply any changes" },
-const int nCommands = (sizeof(commands)/sizeof(cmdInfo));
+ { "close", 0, 1, do_net_close, 2, 1,
+ " close [!] : close the network configuration" },
-Boolean enablePrivateAPI = FALSE;
+ { "create", 1, 3, do_net_create, 3, 0,
+ " create interface <interfaceType> [ <interfaceName> | <interface#> ]\n"
+ " create protocol <protocolType>\n"
+ " create service [ <interfaceName> | <interface#> [ <serviceName> ]]\n"
+ " create set [setName]" },
+ { "disable", 1, 2, do_net_disable, 5, 0,
+ " disable protocol [ <protocolType> ]\n"
+ " disable service [ <serviceName> | <service#> ]" },
+ { "enable", 1, 2, do_net_enable, 4, 0,
+ " enable protocol [ <protocolType> ]\n"
+ " enable service [ <serviceName> | <service#> ]" },
+
+ { "remove", 1, 2, do_net_remove, 6, 0,
+ " remove protocol [ <protocolType> ]\n"
+ " remove service [ <serviceName> | <service#> ]\n"
+ " remove set [ <setName> | <set#> ]" },
+
+ { "select", 2, 2, do_net_select, 7, 0,
+ " select interface <interfaceName> | <interface#> | $child | $service\n"
+ " select protocol <protocolType>\n"
+ " select service <serviceName> | <service#>\n"
+ " select set <setName> | <set#>" },
+
+ { "set", 2, 101, do_net_set, 8, 0,
+ " set interface context-sensitive-arguments (or ? for help)\n"
+ " set protocol context-sensitive-arguments (or ? for help)\n"
+ " set service [ name <serviceName> ] [ order new-order ]\n"
+ " set set [ name setName ]" },
+
+ { "show", 1, 2, do_net_show, 9, 0,
+ " show interfaces\n"
+ " show interface [ <interfaceName> | <interface#> ]\n"
+ " show protocols\n"
+ " show protocol [ <protocolType> ]\n"
+ " show services [ all ]\n"
+ " show service [ <serviceName> | <service#> ]\n"
+ " show sets\n\n"
+ " show set [ <setName> | <set#> ]" },
+
+ { "snapshot", 0, 0, do_net_snapshot, 99, 2,
+ " snapshot" }
+
+};
+__private_extern__
+const int nCommands_prefs = (sizeof(commands_prefs)/sizeof(cmdInfo));
+
+
+__private_extern__ cmdInfo *commands = NULL;
+__private_extern__ int nCommands = 0;
+__private_extern__ Boolean enablePrivateAPI = FALSE;
+__private_extern__ Boolean termRequested = FALSE;
+
+
+__private_extern__
void
do_command(int argc, char **argv)
{
SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
return;
}
- commands[i].func(argc, argv);
+ (*commands[i].func)(argc, argv);
return;
}
}
}
+__private_extern__
void
do_help(int argc, char **argv)
{
SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n"));
for (i = 0; i < nCommands; i++) {
+ if (commands[i].ctype < 0) {
+ continue; /* if "hidden" */
+ }
+
if ((commands[i].ctype > 0) && !enablePrivateAPI) {
continue; /* if "private" API and access has not been enabled */
}
}
+__private_extern__
void
do_readFile(int argc, char **argv)
{
return;
}
+
+
+__private_extern__
+void
+do_quit(int argc, char **argv)
+{
+ termRequested = TRUE;
+ return;
+}
int maxArgs;
void (*func)();
int group;
- int ctype; /* 0==normal, 1==limited, 2==private */
+ int ctype; /* -1==normal/hidden, 0==normal, 1==limited, 2==private */
char *usage;
} cmdInfo;
-extern const cmdInfo commands[];
-extern const int nCommands;
+extern const cmdInfo commands_store[];
+extern const int nCommands_store;
+
+extern const cmdInfo commands_prefs[];
+extern const int nCommands_prefs;
+
+extern cmdInfo *commands;
+extern int nCommands;
extern Boolean enablePrivateAPI;
+extern Boolean termRequested;
__BEGIN_DECLS
void do_command (int argc, char **argv);
void do_help (int argc, char **argv);
+void do_quit (int argc, char **argv);
void do_readFile (int argc, char **argv);
__END_DECLS
//#include <limits.h>
+__private_extern__
void
do_dictInit(int argc, char **argv)
{
}
+__private_extern__
void
do_dictShow(int argc, char **argv)
{
}
+__private_extern__
void
do_dictSetKey(int argc, char **argv)
{
CFRelease(value);
value = val;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
argv++; argc--;
while (argc > 0) {
return;
}
} else {
- val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
}
if (doArray) {
}
+__private_extern__
void
do_dictRemoveKey(int argc, char **argv)
{
CFRelease(value);
value = val;
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key);
CFRelease(key);
+++ /dev/null
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
+++ /dev/null
-$$ Lines starting with $$ are not inserted into newly created files
-$$ The following substitutions are made:
-$$
-$$ $FILENAME$ e.g. foo.m
-$$ $FILENAMESANSEXTENSION$ e.g. foo
-$$ $DIRECTORY$ e.g. /tmp/MyNewApp
-$$ $PROJECTNAME$ e.g. MyNewApp
-$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj
-$$ $USERNAME$ e.g. mwagner
-$$ $DATE$ e.g. Jan-1-1994
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import "$FILENAMESANSEXTENSION$.h"
-
-@implementation $FILENAMESANSEXTENSION$
-
-@end
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "commands.h"
+#include "net.h"
+#include "net_interface.h"
+#include "net_protocol.h"
+#include "net_service.h"
+#include "net_set.h"
+
+#include <unistd.h>
+
+
+__private_extern__ Boolean net_changed = FALSE;
+
+__private_extern__ CFMutableArrayRef new_interfaces = NULL;
+
+__private_extern__ CFArrayRef interfaces = NULL;
+__private_extern__ CFArrayRef services = NULL;
+__private_extern__ CFArrayRef protocols = NULL;
+__private_extern__ CFArrayRef sets = NULL;
+
+__private_extern__ SCNetworkInterfaceRef net_interface = NULL;
+__private_extern__ SCNetworkServiceRef net_service = NULL;
+__private_extern__ SCNetworkProtocolRef net_protocol = NULL;
+__private_extern__ SCNetworkSetRef net_set = NULL;
+
+__private_extern__ CFNumberRef CFNumberRef_0 = NULL;
+__private_extern__ CFNumberRef CFNumberRef_1 = NULL;
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFNumberRef
+_copy_number(const char *arg)
+{
+ int val;
+
+ if (sscanf(arg, "%d", &val) != 1) {
+ return NULL;
+ }
+
+ return CFNumberCreate(NULL, kCFNumberIntType, &val);
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFIndex
+_find_option(const char *option, optionsRef options, const int nOptions)
+{
+ CFIndex i;
+
+ for (i = 0; i < nOptions; i++) {
+ if (strcasecmp(option, options[i].option) == 0) {
+ return i;
+ }
+ }
+
+ return kCFNotFound;
+}
+
+
+__private_extern__
+CFIndex
+_find_selection(CFStringRef choice, selections choices[], unsigned int *flags)
+{
+ CFIndex i;
+
+ i = 0;
+ while (choices[i].selection != NULL) {
+ if (CFStringCompare(choice,
+ choices[i].selection,
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ if (flags != NULL) {
+ *flags = choices[i].flags;
+ }
+ return i;
+ }
+ i++;
+ }
+
+ return kCFNotFound;
+}
+
+
+__private_extern__
+Boolean
+_process_options(optionsRef options, int nOptions, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ while (argc > 0) {
+ CFIndex optionIndex = kCFNotFound;
+
+ optionIndex = _find_option(argv[0], options, nOptions);
+ if (optionIndex == kCFNotFound) {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return FALSE;
+ }
+ argv++;
+ argc--;
+
+ switch (options[optionIndex].type) {
+ case isOther :
+ // all option processing is managed by the "handler"
+ break;
+ case isHelp :
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), options[optionIndex].info);
+ return FALSE;
+ case isChooseOne : {
+ CFStringRef choice;
+ selections *choices = (selections *)options[optionIndex].info;
+ unsigned int flags;
+ CFIndex i;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s not specified\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+ return FALSE;
+ }
+
+ choice = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ i = _find_selection(choice, choices, &flags);
+ CFRelease(choice);
+
+ if (i != kCFNotFound) {
+ if (choices[i].flags & selectionNotAvailable) {
+ SCPrint(TRUE, stdout,
+ CFSTR("cannot select %s\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+ return FALSE;
+ }
+
+ CFDictionarySetValue(newConfiguration,
+ *(options[optionIndex].key),
+ *(choices[i].key));
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("invalid %s\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+ return FALSE;
+ }
+
+ argv++;
+ argc--;
+ break;
+ }
+ case isChooseMultiple :
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s(s) not specified\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+ return FALSE;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFIndex i;
+ CFIndex n;
+ CFMutableArrayRef chosen;
+ CFStringRef str;
+ CFArrayRef str_array;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+ CFRelease(str);
+
+ chosen = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ n = CFArrayGetCount(str_array);
+ for (i = 0; i < n; i++) {
+ CFStringRef choice;
+ selections *choices = (selections *)options[optionIndex].info;
+ unsigned int flags;
+ CFIndex j;
+
+ choice = CFArrayGetValueAtIndex(str_array, i);
+ j = _find_selection(choice, choices, &flags);
+
+ if (j != kCFNotFound) {
+ if (choices[j].flags & selectionNotAvailable) {
+ SCPrint(TRUE, stdout,
+ CFSTR("cannot select %s\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+ CFArrayRemoveAllValues(chosen);
+ break;
+ }
+
+ CFArrayAppendValue(chosen, *(choices[j].key));
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("invalid %s\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+ CFArrayRemoveAllValues(chosen);
+ break;
+ }
+ }
+ CFRelease(str_array);
+
+ if (CFArrayGetCount(chosen) > 0) {
+ CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), chosen);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+ }
+ CFRelease(chosen);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+ }
+
+ argv++;
+ argc--;
+ break;
+ case isBoolean :
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s not specified\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "enable/disable");
+ return FALSE;
+ }
+
+ if ((strcasecmp(argv[0], "disable") == 0) ||
+ (strcasecmp(argv[0], "0" ) == 0)) {
+ CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_0);
+ } else if ((strcasecmp(argv[0], "enable") == 0) ||
+ (strcasecmp(argv[0], "1" ) == 0)) {
+ CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_1);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
+ return FALSE;
+ }
+
+ argv++;
+ argc--;
+ break;
+ case isNumber :
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s not specified\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "value");
+ return FALSE;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFNumberRef num;
+
+ num = _copy_number(argv[0]);
+ if (num != NULL) {
+ CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), num);
+ CFRelease(num);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
+ return FALSE;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+ }
+
+ argv++;
+ argc--;
+ break;
+ case isString :
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s not specified\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "value");
+ return FALSE;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str);
+ CFRelease(str);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+ }
+
+ argv++;
+ argc--;
+ break;
+ case isStringArray :
+ if (argc < 1) {
+ SCPrint(TRUE, stdout,
+ CFSTR("%s(s) not specified\n"),
+ options[optionIndex].description != NULL ? options[optionIndex].description : "value");
+ return FALSE;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef str;
+ CFArrayRef str_array;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+ CFRelease(str);
+
+ CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str_array);
+ CFRelease(str_array);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+ }
+
+ argv++;
+ argc--;
+ break;
+ }
+
+ if (options[optionIndex].handler != NULL) {
+ CFStringRef key;
+ int nArgs;
+
+ key = options[optionIndex].key != NULL ? *(options[optionIndex].key) : NULL;
+ nArgs = (*options[optionIndex].handler)(key,
+ options[optionIndex].description,
+ options[optionIndex].info,
+ argc,
+ argv,
+ newConfiguration);
+ if (nArgs < 0) {
+ return FALSE;
+ }
+
+ argv += nArgs;
+ argc -= nArgs;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/* -------------------- */
+
+
+#define N_QUICK 32
+
+__private_extern__
+void
+_show_entity(CFDictionaryRef entity, CFStringRef prefix)
+{
+ CFArrayRef array;
+ const void * keys_q[N_QUICK];
+ const void ** keys = keys_q;
+ CFIndex i;
+ CFIndex n;
+ CFMutableArrayRef sorted;
+
+ n = CFDictionaryGetCount(entity);
+ if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+ keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+ }
+ CFDictionaryGetKeysAndValues(entity, keys, NULL);
+
+ array = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
+ sorted = CFArrayCreateMutableCopy(NULL, n, array);
+ if (n > 1) {
+ CFArraySortValues(sorted,
+ CFRangeMake(0, n),
+ (CFComparatorFunction)CFStringCompare,
+ NULL);
+ }
+
+ for (i = 0; i < n; i++) {
+ CFStringRef key;
+ CFTypeRef value;
+
+ key = CFArrayGetValueAtIndex(sorted, i);
+ value = CFDictionaryGetValue(entity, key);
+ if (isA_CFArray(value)) {
+ CFStringRef str;
+
+ str = CFStringCreateByCombiningStrings(NULL, value, CFSTR(", "));
+ SCPrint(TRUE, stdout, CFSTR("%@ %@ = (%@)\n"), prefix, key, str);
+ CFRelease(str);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("%@ %@ = %@\n"), prefix, key, value);
+ }
+ }
+
+ CFRelease(sorted);
+ CFRelease(array);
+ if (keys != keys_q) {
+ CFAllocatorDeallocate(NULL, keys);
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+commitRequired(int argc, char **argv, const char *command)
+{
+ if (net_changed) {
+ if ((currentInput != NULL) &&
+ isatty(fileno(currentInput->fp)) &&
+ ((argc < 1) || (strcmp(argv[0], "!") != 0))
+ ) {
+ SCPrint(TRUE, stdout,
+ CFSTR("configuration changes have not been committed\n"
+ "use \"commit\" to save changes"));
+ if (command != NULL) {
+ SCPrint(TRUE, stdout,
+ CFSTR(" or \"%s !\" to abandon changes"),
+ command);
+ }
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ return TRUE;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("configuration changes abandoned\n"));
+ }
+
+ return FALSE;
+}
+
+
+__private_extern__
+void
+do_net_init()
+{
+ int one = 1;
+ int zero = 0;
+
+ CFNumberRef_0 = CFNumberCreate(NULL, kCFNumberIntType, &zero);
+ CFNumberRef_1 = CFNumberCreate(NULL, kCFNumberIntType, &one);
+
+ return;
+}
+
+
+__private_extern__
+void
+do_net_open(int argc, char **argv)
+{
+ CFStringRef prefsID = NULL;
+
+ if (prefs != NULL) {
+ if (commitRequired(argc, argv, "close")) {
+ return;
+ }
+ do_net_close(0, NULL);
+ }
+
+ if (argc > 0) {
+ prefsID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ }
+
+ prefs = SCPreferencesCreate(NULL, CFSTR("scutil --net"), prefsID);
+ if (prefsID != NULL) CFRelease(prefsID);
+
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = FALSE;
+
+ net_set = SCNetworkSetCopyCurrent(prefs);
+ if (net_set != NULL) {
+ CFStringRef setName;
+
+ setName = SCNetworkSetGetName(net_set);
+ if (setName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName);
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("set ID \"%@\" selected\n"),
+ SCNetworkSetGetSetID(net_set));
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_net_commit(int argc, char **argv)
+{
+ if (!SCPreferencesCommitChanges(prefs)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = FALSE;
+
+ return;
+}
+
+
+__private_extern__
+void
+do_net_apply(int argc, char **argv)
+{
+ if (!SCPreferencesApplyChanges(prefs)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ }
+ return;
+}
+
+
+__private_extern__
+void
+do_net_close(int argc, char **argv)
+{
+ if (commitRequired(argc, argv, "close")) {
+ return;
+ }
+
+ if (net_interface != NULL) {
+ CFRelease(net_interface);
+ net_interface = NULL;
+ }
+
+ if (net_service != NULL) {
+ CFRelease(net_service);
+ net_service = NULL;
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ }
+
+ if (net_set != NULL) {
+ CFRelease(net_set);
+ net_set = NULL;
+ }
+
+ if (interfaces != NULL) {
+ CFRelease(interfaces);
+ interfaces = NULL;
+ }
+
+ if (services != NULL) {
+ CFRelease(services);
+ services = NULL;
+ }
+
+ if (protocols != NULL) {
+ CFRelease(protocols);
+ protocols = NULL;
+ }
+
+ if (sets != NULL) {
+ CFRelease(sets);
+ sets = NULL;
+ }
+
+ if (new_interfaces != NULL) {
+ CFRelease(new_interfaces);
+ new_interfaces = NULL;
+ }
+
+ if (prefs != NULL) {
+ CFRelease(prefs);
+ prefs = NULL;
+ }
+
+ net_changed = FALSE;
+
+ return;
+}
+
+
+__private_extern__
+void
+do_net_quit(int argc, char **argv)
+{
+ if (commitRequired(argc, argv, "quit")) {
+ return;
+ }
+
+ termRequested = TRUE;
+ return;
+}
+
+
+/* -------------------- */
+
+
+typedef void (*net_func) (int argc, char **argv);
+
+static const struct {
+ char *key;
+ net_func create;
+ net_func disable;
+ net_func enable;
+ net_func select;
+ net_func set;
+ net_func show;
+ net_func remove;
+} net_keys[] = {
+
+ { "interfaces", NULL , NULL , NULL ,
+ NULL , NULL , show_interfaces ,
+ NULL },
+
+ { "interface", create_interface, NULL , NULL ,
+ select_interface, set_interface , show_interface ,
+ NULL },
+
+ { "services", NULL , NULL , NULL ,
+ NULL , NULL , show_services ,
+ NULL },
+
+ { "service", create_service , disable_service , enable_service ,
+ select_service , set_service , show_service ,
+ remove_service },
+
+ { "protocols", NULL , NULL , NULL ,
+ NULL , NULL , show_protocols ,
+ NULL },
+
+ { "protocol", create_protocol , disable_protocol, enable_protocol ,
+ select_protocol , set_protocol , show_protocol ,
+ remove_protocol },
+
+ { "sets", NULL , NULL , NULL ,
+ NULL , NULL , show_sets ,
+ NULL },
+
+ { "set", create_set , NULL , NULL ,
+ select_set , set_set , show_set ,
+ remove_set }
+
+};
+#define N_NET_KEYS (sizeof(net_keys) / sizeof(net_keys[0]))
+
+
+static int
+findNetKey(char *key)
+{
+ int i;
+
+ for (i = 0; i < (int)N_NET_KEYS; i++) {
+ if (strcmp(key, net_keys[i].key) == 0) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+do_net_create(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("create what?\n"));
+ return;
+ }
+
+ if (*net_keys[i].create == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("create what?\n"));
+ }
+
+ (*net_keys[i].create)(argc, argv);
+ return;
+}
+
+
+__private_extern__
+void
+do_net_disable(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
+ return;
+ }
+
+ if (*net_keys[i].disable == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
+ }
+
+ (*net_keys[i].disable)(argc, argv);
+ return;
+}
+
+
+__private_extern__
+void
+do_net_enable(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
+ return;
+ }
+
+ if (*net_keys[i].enable == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
+ }
+
+ (*net_keys[i].enable)(argc, argv);
+ return;
+}
+
+
+__private_extern__
+void
+do_net_remove(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
+ return;
+ }
+
+ if (*net_keys[i].remove == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
+ }
+
+ (*net_keys[i].remove)(argc, argv);
+ return;
+}
+
+
+__private_extern__
+void
+do_net_select(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("select what?\n"));
+ return;
+ }
+
+ if (*net_keys[i].select == NULL) {
+ SCPrint(TRUE, stderr, CFSTR("select what?\n"));
+ }
+
+ (*net_keys[i].select)(argc, argv);
+ return;
+}
+
+
+__private_extern__
+void
+do_net_set(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("set what?\n"));
+ return;
+ }
+
+ (*net_keys[i].set)(argc, argv);
+ return;
+}
+
+
+__private_extern__
+void
+do_net_show(int argc, char **argv)
+{
+ char *key;
+ int i;
+
+ key = argv[0];
+ argv++;
+ argc--;
+
+ i = findNetKey(key);
+ if (i < 0) {
+ SCPrint(TRUE, stderr, CFSTR("show what?\n"));
+ return;
+ }
+
+ (*net_keys[i].show)(argc, argv);
+ return;
+}
+
+
+#include "SCPreferencesInternal.h"
+#include <fcntl.h>
+#include <unistd.h>
+__private_extern__
+void
+do_net_snapshot(int argc, char **argv)
+{
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return;
+ }
+
+ if (prefs != NULL) {
+ SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+ if (prefsPrivate->prefs != NULL) {
+ int fd;
+ static int n_snapshot = 0;
+ char *path;
+ CFDataRef xmlData;
+
+ asprintf(&path, "/tmp/prefs_snapshot_%d", n_snapshot++);
+ fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ free(path);
+
+ xmlData = CFPropertyListCreateXMLData(NULL, prefsPrivate->prefs);
+ if (xmlData != NULL) {
+ (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
+ CFRelease(xmlData);
+ } else {
+ SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+ }
+
+ (void) close(fd);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("prefs have not been accessed\n"));
+ }
+ }
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_H
+#define _NET_H
+
+#include <sys/cdefs.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+
+typedef int (*optionHandler) (CFStringRef key,
+ const char *description,
+ void *info,
+ int argc,
+ char **argv,
+ CFMutableDictionaryRef newConfiguration);
+
+typedef enum {
+ isOther, // use "only" handler function for processing
+ isHelp,
+ isChooseOne,
+ isChooseMultiple,
+ isBoolean,
+ isNumber,
+ isString,
+ isStringArray
+} optionType;
+
+typedef const struct {
+ const CFStringRef selection;
+ const CFStringRef *key;
+ const unsigned int flags;
+} selections;
+#define selectionNotAvailable 1<<0 // if you can't "choose" this selection
+
+typedef const struct {
+ const char *option;
+ const char *description;
+ optionType type;
+ const CFStringRef *key;
+ optionHandler handler;
+ void *info;
+} options, *optionsRef;
+
+
+extern Boolean net_changed;
+
+extern CFMutableArrayRef new_interfaces;
+
+extern CFArrayRef interfaces;
+extern CFArrayRef services;
+extern CFArrayRef protocols;
+extern CFArrayRef sets;
+
+extern SCNetworkInterfaceRef net_interface;
+extern SCNetworkServiceRef net_service;
+extern SCNetworkProtocolRef net_protocol;
+extern SCNetworkSetRef net_set;
+
+extern CFNumberRef CFNumberRef_0;
+extern CFNumberRef CFNumberRef_1;
+
+
+__BEGIN_DECLS
+
+Boolean _process_options(optionsRef options,
+ int nOptions,
+ int argc,
+ char **argv,
+ CFMutableDictionaryRef newConfiguration);
+
+CFNumberRef _copy_number (const char *arg);
+
+CFIndex _find_option (const char *option,
+ optionsRef options,
+ const int nOptions);
+
+CFIndex _find_selection (CFStringRef choice,
+ selections choises[],
+ unsigned int *flags);
+
+void _show_entity (CFDictionaryRef entity, CFStringRef prefix);
+
+void do_net_init ();
+void do_net_quit ();
+
+void do_net_open (int argc, char **argv);
+void do_net_commit (int argc, char **argv);
+void do_net_apply (int argc, char **argv);
+void do_net_close (int argc, char **argv);
+
+void do_net_create (int argc, char **argv);
+void do_net_disable (int argc, char **argv);
+void do_net_enable (int argc, char **argv);
+void do_net_remove (int argc, char **argv);
+void do_net_select (int argc, char **argv);
+void do_net_set (int argc, char **argv);
+void do_net_show (int argc, char **argv);
+
+void do_net_snapshot (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+
+#include <SystemConfiguration/LinkConfiguration.h>
+
+
+/* -------------------- */
+
+
+static CFArrayRef
+_copy_interfaces()
+{
+ CFMutableArrayRef interfaces;
+ CFArrayRef real_interfaces;
+
+ real_interfaces = SCNetworkInterfaceCopyAll();
+ if (real_interfaces == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return NULL;
+ }
+
+ interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ // include real interfaces
+ CFArrayAppendArray(interfaces,
+ real_interfaces,
+ CFRangeMake(0, CFArrayGetCount(real_interfaces)));
+ CFRelease(real_interfaces);
+
+ // include pseudo interfaces
+ CFArrayAppendValue(interfaces, kSCNetworkInterfaceIPv4);
+
+ // include interfaces that we have created
+ if (new_interfaces != NULL) {
+ CFArrayAppendArray(interfaces,
+ new_interfaces,
+ CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+ }
+
+ return (CFArrayRef)interfaces;
+}
+
+
+__private_extern__
+SCNetworkInterfaceRef
+_find_interface(char *match)
+{
+ Boolean allowIndex = TRUE;
+ CFIndex i;
+ CFIndex n;
+ CFStringRef select_name = NULL;
+ SCNetworkInterfaceRef selected = NULL;
+
+ if (strcasecmp(match, "$child") == 0) {
+ if (net_interface == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
+ goto done;
+ }
+
+ selected = SCNetworkInterfaceGetInterface(net_interface);
+ if(selected == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no child interface\n"));
+ }
+
+ goto done;
+ } else if (strcasecmp(match, "$service") == 0) {
+ if (net_service == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+ goto done;
+ }
+
+ selected = SCNetworkServiceGetInterface(net_service);
+ if(selected == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no interface for service\n"));
+ }
+
+ goto done;
+ }
+
+ if (interfaces == NULL) {
+ interfaces = _copy_interfaces();
+ if (interfaces == NULL) {
+ return NULL;
+ }
+ allowIndex = FALSE;
+ }
+
+ // try to select the interface by its display name
+
+ select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+ n = CFArrayGetCount(interfaces);
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ CFStringRef interfaceName;
+
+ interface = CFArrayGetValueAtIndex(interfaces, i);
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if ((interfaceName != NULL) && CFEqual(select_name, interfaceName)) {
+ if (selected == NULL) {
+ selected = interface;
+ } else {
+ // if multiple interfaces match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the interface by its BSD name
+
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ CFStringRef bsd_name = NULL;
+
+ interface = CFArrayGetValueAtIndex(interfaces, i);
+ while ((interface != NULL) && (bsd_name == NULL)) {
+ bsd_name = SCNetworkInterfaceGetBSDName(interface);
+ if (bsd_name == NULL) {
+ interface = SCNetworkInterfaceGetInterface(interface);
+ }
+ }
+
+ if ((bsd_name != NULL) && CFEqual(select_name, bsd_name)) {
+ if (selected == NULL) {
+ selected = interface;
+ } else {
+ // if multiple interfaces match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the interface by its interface type
+
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ CFStringRef interfaceType;
+
+ interface = CFArrayGetValueAtIndex(interfaces, i);
+ interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+ if (CFEqual(select_name, interfaceType)) {
+ if (selected == NULL) {
+ selected = interface;
+ } else {
+ // if multiple interfaces match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ if (allowIndex) {
+ char *end;
+ char *str = match;
+ long val;
+
+ // try to select the interface by its index
+
+ errno = 0;
+ val = strtol(str, &end, 10);
+ if ((*str != '\0') &&
+ ((*end == '\0') || (*end == '.')) &&
+ (errno == 0)) {
+ if ((val > 0) && (val <= n)) {
+ selected = CFArrayGetValueAtIndex(interfaces, val - 1);
+
+ if (*end == '.') {
+ str = end + 1;
+ val = strtol(str, &end, 10);
+ if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+ while (val-- > 0) {
+ selected = SCNetworkInterfaceGetInterface(selected);
+ if (selected == NULL) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("no match\n"));
+
+ done :
+
+ if (select_name != NULL) CFRelease(select_name);
+ return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_interface(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+ CFStringRef interfaceName;
+ CFStringRef interfaceType;
+ SCNetworkInterfaceRef new_interface;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("what interface type?\n"));
+ return;
+ }
+
+ interfaceType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+ if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
+// xxxxx
+SCPrint(TRUE, stdout, CFSTR("vlan creation not yet supported\n"));
+goto done;
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
+// xxxxx
+SCPrint(TRUE, stdout, CFSTR("bond creation not yet supported\n"));
+goto done;
+ } else {
+ if (argc < 2) {
+ if (net_interface == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
+ goto done;
+ }
+
+ interface = net_interface;
+ } else {
+ interface = _find_interface(argv[1]);
+ }
+
+ if (interface == NULL) {
+ return;
+ }
+
+ new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType);
+ if (new_interface == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+ }
+
+ if (new_interfaces == NULL) {
+ new_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
+ CFArrayAppendValue(new_interfaces, new_interface);
+
+ if (net_interface != NULL) CFRelease(net_interface);
+ net_interface = new_interface;
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(net_interface);
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+ }
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetInterfaceType(net_interface);
+ }
+ SCPrint(TRUE, stdout, CFSTR("interface \"%@\" created and selected\n"), interfaceName);
+
+ done :
+
+ CFRelease(interfaceType);
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+select_interface(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+
+ interface = _find_interface(argv[0]);
+
+ if (interface != NULL) {
+ CFStringRef interfaceName;
+
+ if (net_interface != NULL) CFRelease(net_interface);
+ net_interface = CFRetain(interface);
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetBSDName(interface);
+ }
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("interface \"%@\" selected\n"), interfaceName);
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+_show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean showChild)
+{
+ CFDictionaryRef configuration;
+ CFStringRef if_bsd_name;
+ CFStringRef if_localized_name;
+ CFStringRef if_mac_address;
+ CFStringRef if_type;
+ CFArrayRef supported;
+
+ if_localized_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (if_localized_name != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%@ name = %@\n"), prefix, if_localized_name);
+ }
+
+ if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
+ if (if_bsd_name != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%@ interface name = %@\n"), prefix, if_bsd_name);
+ }
+
+ if_type = SCNetworkInterfaceGetInterfaceType(interface);
+ SCPrint(TRUE, stdout, CFSTR("%@ type = %@\n"), prefix, if_type);
+
+ if_mac_address = SCNetworkInterfaceGetHardwareAddressString(interface);
+ if (if_mac_address != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%@ address = %@\n"), prefix, if_mac_address);
+ }
+
+ configuration = SCNetworkInterfaceGetConfiguration(interface);
+ if ((configuration != NULL) &&
+ CFDictionaryContainsKey(configuration, kSCResvInactive)) {
+ configuration = NULL;
+ }
+
+ if (if_bsd_name != NULL) {
+ CFArrayRef available;
+ CFDictionaryRef active;
+ int mtu_cur;
+ int mtu_min;
+ int mtu_max;
+
+ if (NetworkInterfaceCopyMTU(if_bsd_name, &mtu_cur, &mtu_min, &mtu_max)) {
+ char isCurrent = '*';
+
+ if (configuration != NULL) {
+ int mtu_req;
+ CFNumberRef num;
+
+ num = CFDictionaryGetValue(configuration, kSCPropNetEthernetMTU);
+ if (isA_CFNumber(num)) {
+ CFNumberGetValue(num, kCFNumberIntType, &mtu_req);
+ if (mtu_cur != mtu_req) {
+ mtu_cur = mtu_req;
+ isCurrent = ' ';
+ }
+ }
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("%@ mtu %c = %ld (%ld < n < %ld)\n"),
+ prefix,
+ isCurrent,
+ mtu_cur,
+ mtu_min,
+ mtu_max);
+ }
+
+ if (NetworkInterfaceCopyMediaOptions(if_bsd_name, NULL, &active, &available, TRUE)) {
+ char isCurrent = ' ';
+ CFArrayRef options = NULL;
+ CFArrayRef options_req = NULL;
+ CFStringRef subtype = NULL;
+ CFStringRef subtype_req = NULL;
+
+ if (configuration != NULL) {
+ subtype_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaSubType);
+ options_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaOptions);
+ }
+
+ if (subtype_req == NULL) {
+ subtype_req = CFSTR("autoselect");
+ }
+
+ if (active != NULL) {
+ subtype = CFDictionaryGetValue(active, kSCPropNetEthernetMediaSubType);
+ options = CFDictionaryGetValue(active, kSCPropNetEthernetMediaOptions);
+ }
+
+ if (subtype != NULL) {
+ if (((subtype_req != NULL) &&
+ CFEqual(subtype, subtype_req)) &&
+ ((options == options_req) ||
+ ((options != NULL) &&
+ (options_req != NULL) &&
+ CFEqual(options, options_req)))
+ ) {
+ isCurrent = '*';
+ } else if ((subtype_req == NULL) ||
+ ((subtype_req != NULL) &&
+ CFEqual(subtype_req, CFSTR("autoselect")))) {
+ // if requested subtype not specified or "autoselect"
+ isCurrent = '*';
+ }
+ }
+
+ if (subtype_req != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%@ media %c = %@"),
+ prefix,
+ isCurrent,
+ subtype_req);
+
+ if ((options_req != NULL) &&
+ (CFArrayGetCount(options_req) > 0)) {
+ CFStringRef options_str;
+
+ options_str = CFStringCreateByCombiningStrings(NULL, options_req, CFSTR(","));
+ SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
+ CFRelease(options_str);
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ if (available != NULL) {
+ CFIndex i;
+ CFIndex n_subtypes;
+ CFArrayRef subtypes;
+
+ subtypes = NetworkInterfaceCopyMediaSubTypes(available);
+ n_subtypes = (subtypes != NULL) ? CFArrayGetCount(subtypes) : 0;
+ for (i = 0; i < n_subtypes; i++) {
+ CFIndex j;
+ CFIndex n_subtype_options;
+ CFStringRef subtype;
+ CFArrayRef subtype_options;
+
+ subtype = CFArrayGetValueAtIndex(subtypes, i);
+ subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
+ n_subtype_options = (subtype_options != NULL) ? CFArrayGetCount(subtype_options) : 0;
+ for (j = 0; j < n_subtype_options; j++) {
+ char isCurrent = ' ';
+ CFArrayRef options;
+
+ options = CFArrayGetValueAtIndex(subtype_options, j);
+
+ if (((subtype_req != NULL) &&
+ CFEqual(subtype, subtype_req)) &&
+ ((options == options_req) ||
+ ((options != NULL) &&
+ (options_req != NULL) &&
+ CFEqual(options, options_req)))
+ ) {
+ isCurrent = '*';
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("%@ %s %c = %@"),
+ prefix,
+ ((i == 0) && (j == 0)) ? "supported media" : " ",
+ isCurrent,
+ subtype);
+
+ if ((options != NULL) &&
+ (CFArrayGetCount(options) > 0)) {
+ CFStringRef options_str;
+
+ options_str = CFStringCreateByCombiningStrings(NULL, options, CFSTR(","));
+ SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
+ CFRelease(options_str);
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ }
+ CFRelease(subtype_options);
+ }
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ }
+ }
+
+ supported = SCNetworkInterfaceGetSupportedInterfaceTypes(interface);
+ SCPrint(TRUE, stdout, CFSTR("%@ supported interfaces = "), prefix);
+ if (supported != NULL) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(supported);
+
+ for (i = 0; i < n; i++) {
+ SCPrint(TRUE, stdout, CFSTR("%s%@"),
+ (i == 0) ? "" : ", ",
+ CFArrayGetValueAtIndex(supported, i));
+ }
+ }
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
+ SCPrint(TRUE, stdout, CFSTR("%@ supported protocols = "), prefix);
+ if (supported != NULL) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(supported);
+
+ for (i = 0; i < n; i++) {
+ SCPrint(TRUE, stdout, CFSTR("%s%@"),
+ (i == 0) ? "" : ", ",
+ CFArrayGetValueAtIndex(supported, i));
+ }
+ }
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ if (configuration != NULL) {
+ CFMutableDictionaryRef effective;
+
+ effective = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
+
+ // remove known (and already reported) interface configuration keys
+ if (CFDictionaryContainsKey(effective, kSCResvInactive)) {
+ CFDictionaryRemoveAllValues(effective);
+ }
+ CFDictionaryRemoveValue(effective, kSCPropNetEthernetMTU);
+ CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaSubType);
+ CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaOptions);
+
+ if (CFDictionaryGetCount(effective) > 0) {
+ SCPrint(TRUE, stdout, CFSTR("\n%@ per-interface configuration\n"), prefix);
+ _show_entity(configuration, prefix);
+ }
+
+ CFRelease(effective);
+ }
+
+ if (_sc_debug) {
+ SCPrint(TRUE, stdout, CFSTR("\n%@\n"), interface);
+ }
+
+ interface = SCNetworkInterfaceGetInterface(interface);
+ if (interface != NULL) {
+ CFStringRef newPrefix;
+
+ newPrefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ "), prefix);
+ SCPrint(TRUE, stdout, CFSTR("\n%@child interface\n"), newPrefix);
+ _show_interface(interface, newPrefix, showChild);
+ CFRelease(newPrefix);
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_interfaces(int argc, char **argv)
+{
+ CFIndex i;
+ CFIndex n;
+
+ if (interfaces != NULL) CFRelease(interfaces);
+ interfaces = _copy_interfaces();
+ if (interfaces == NULL) {
+ return;
+ }
+
+ n = CFArrayGetCount(interfaces);
+ for (i = 0; i < n; i++) {
+ CFIndex childIndex = 0;
+ SCNetworkInterfaceRef interface;
+
+ interface = CFArrayGetValueAtIndex(interfaces, i);
+ do {
+ CFStringRef interfaceName;
+ char isSelected;
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetBSDName(interface);
+ }
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+ }
+
+ isSelected = ' ';
+ if ((net_interface != NULL) && CFEqual(interface, net_interface)) {
+ isSelected = '>';
+ }
+
+ if (childIndex == 0) {
+ SCPrint(TRUE, stdout, CFSTR("%c%2d: %@\n"),
+ isSelected,
+ i + 1,
+ interfaceName);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("%c%2d.%d: %@\n"),
+ isSelected,
+ i + 1,
+ childIndex,
+ interfaceName);
+ }
+
+ interface = SCNetworkInterfaceGetInterface(interface);
+ childIndex++;
+ } while (interface != NULL);
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+// xxxxx ("+device", "-device")
+SCPrint(TRUE, stdout, CFSTR("bond interface management not yet supported\n"));
+ return FALSE;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+SCPrint(TRUE, stdout, CFSTR("airport interface management not yet supported\n"));
+ return FALSE;
+}
+
+
+/* -------------------- */
+
+
+static options ethernetOptions[] = {
+ { "mtu" , NULL, isNumber , &kSCPropNetEthernetMTU , NULL, NULL },
+ { "media" , NULL, isString , &kSCPropNetEthernetMediaSubType, NULL, NULL },
+ { "mediaopt" , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nEthernet configuration commands\n\n"
+ " set interface [mtu n] [media type] [mediaopts opts]\n"
+ }
+};
+#define N_ETHERNET_OPTIONS (sizeof(ethernetOptions) / sizeof(ethernetOptions[0]))
+
+
+static Boolean
+set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFStringRef interfaceName;
+ Boolean ok;
+
+ interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+ if (interfaceName == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
+ return FALSE;
+ }
+
+ ok = _process_options(ethernetOptions, N_ETHERNET_OPTIONS, argc, argv, newConfiguration);
+ if (ok) {
+ CFNumberRef mtu;
+ CFArrayRef options;
+ CFStringRef subtype;
+
+ // validate configuration
+
+ mtu = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMTU);
+ if (isA_CFNumber(mtu)) {
+ int mtu_max;
+ int mtu_min;
+ int mtu_val;
+
+ if (!NetworkInterfaceCopyMTU(interfaceName, NULL, &mtu_min, &mtu_max)) {
+ SCPrint(TRUE, stdout, CFSTR("cannot set MTU\n"));
+ return FALSE;
+ }
+
+ if (!CFNumberGetValue(mtu, kCFNumberIntType, &mtu_val) ||
+ (mtu_val < mtu_min) ||
+ (mtu_val > mtu_max)) {
+ SCPrint(TRUE, stdout, CFSTR("mtu out of range\n"));
+ return FALSE;
+ }
+ }
+
+ subtype = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaSubType);
+ options = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaOptions);
+
+ if (subtype != NULL) {
+ CFArrayRef available = NULL;
+ CFArrayRef config_options = options;
+ CFArrayRef subtypes = NULL;
+ CFArrayRef subtype_options = NULL;
+
+ ok = FALSE;
+
+ if (options == NULL) {
+ config_options = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ if (interfaceName == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("media type / options not available\n"));
+ goto checked;
+ }
+
+ if (!NetworkInterfaceCopyMediaOptions(interfaceName, NULL, NULL, &available, FALSE)) {
+ SCPrint(TRUE, stdout, CFSTR("media type / options not available\n"));
+ goto checked;
+ }
+
+ if (available == NULL) {
+ goto checked;
+ }
+
+ subtypes = NetworkInterfaceCopyMediaSubTypes(available);
+ if ((subtypes == NULL) ||
+ !CFArrayContainsValue(subtypes,
+ CFRangeMake(0, CFArrayGetCount(subtypes)),
+ subtype)) {
+ SCPrint(TRUE, stdout, CFSTR("media type not valid\n"));
+ goto checked;
+ }
+
+ subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
+ if ((subtype_options == NULL) ||
+ !CFArrayContainsValue(subtype_options,
+ CFRangeMake(0, CFArrayGetCount(subtype_options)),
+ config_options)) {
+ SCPrint(TRUE, stdout, CFSTR("media options not valid for \"%@\"\n"), subtype);
+ goto checked;
+ }
+
+ if (options == NULL) {
+ CFDictionarySetValue(newConfiguration, kSCPropNetEthernetMediaOptions, config_options);
+ }
+
+ ok = TRUE;
+
+ checked :
+
+ if (available != NULL) CFRelease(available);
+ if (subtypes != NULL) CFRelease(subtypes);
+ if (subtype_options != NULL) CFRelease(subtype_options);
+ if (options == NULL) CFRelease(config_options);
+ } else {
+ if (options != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("media type and options must both be specified\n"));
+ return FALSE;
+ }
+ }
+ }
+
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+static selections modemDialSelections[] = {
+ { CFSTR("ignore"), &kSCValNetModemDialModeIgnoreDialTone , 0 },
+ { CFSTR("manual"), &kSCValNetModemDialModeManual , 0 },
+ { CFSTR("wait") , &kSCValNetModemDialModeWaitForDialTone, 0 },
+ { NULL , NULL , 0 }
+};
+
+static options modemOptions[] = {
+ { "ConnectionScript" , "script", isString , &kSCPropNetModemConnectionScript , NULL, NULL },
+ { "DialMode" , "mode" , isChooseOne, &kSCPropNetModemDialMode , NULL, (void *)modemDialSelections },
+ { "CallWaiting" , NULL , isBoolean , &kSCPropNetModemHoldEnabled , NULL, NULL },
+ { "CallWaitingAlert" , NULL , isBoolean , &kSCPropNetModemHoldCallWaitingAudibleAlert, NULL, NULL },
+ { "CallWaitingDisconnectOnAnswer", NULL , isBoolean , &kSCPropNetModemHoldDisconnectOnAnswer , NULL, NULL },
+ { "DataCompression" , NULL , isBoolean , &kSCPropNetModemDataCompression , NULL, NULL },
+ { "ErrorCorrection" , NULL , isBoolean , &kSCPropNetModemErrorCorrection , NULL, NULL },
+ { "HoldReminder" , NULL , isBoolean , &kSCPropNetModemHoldReminder , NULL, NULL },
+ { "HoldReminderTime" , "time" , isNumber , &kSCPropNetModemHoldReminderTime , NULL, NULL },
+ { "PulseDial" , NULL , isBoolean , &kSCPropNetModemPulseDial , NULL, NULL },
+ { "Speaker" , NULL , isBoolean , &kSCPropNetModemSpeaker , NULL, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nModem configuration commands\n\n"
+ " set interface [ConnectionScript connection-script]\n"
+ " set interface [CallWaiting {enable|disable}]\n"
+ " set interface [CallWaitingAlert {enable|disable}]\n"
+ " set interface [CallWaitingDisconnectOnAnswer {enable|disable}]\n"
+ " set interface [DialMode {ignore|wait}]\n"
+ " set interface [DataCompression {enable|disable}]\n"
+ " set interface [ErrorCorrection {enable|disable}]\n"
+ " set interface [HoldReminder {enable|disable}]\n"
+ " set interface [HoldReminderTime n]\n"
+ " set interface [PulseDial {enable|disable}]\n"
+ " set interface [Speaker {enable|disable}]"
+ }
+};
+#define N_MODEM_OPTIONS (sizeof(modemOptions) / sizeof(modemOptions[0]))
+
+
+static Boolean
+set_interface_modem(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(modemOptions, N_MODEM_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+static int
+__doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("PPP password not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef encryptionType;
+
+ encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
+ if (encryptionType == NULL) {
+ CFIndex n;
+ CFMutableDataRef pw;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ n = CFStringGetLength(str);
+ pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
+ CFDataSetLength(pw, n * sizeof(UniChar));
+ CFStringGetCharacters(str,
+ CFRangeMake(0, n),
+ (UniChar *)CFDataGetMutableBytePtr(pw));
+ CFRelease(str);
+
+ CFDictionarySetValue(newConfiguration, key, pw);
+ CFRelease(pw);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType);
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static int
+__doPPPAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("PPP password type mode not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ if (strcasecmp(argv[0], "keychain") == 0) {
+ CFDictionarySetValue(newConfiguration, key, kSCValNetPPPAuthPasswordEncryptionKeychain);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid password type\n"));
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ // encryption type changed, reset password
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetPPPAuthPassword);
+
+ return 1;
+}
+
+
+static selections authPromptSelections[] = {
+ { CFSTR("before"), &kSCValNetPPPAuthPromptBefore, 0 },
+ { CFSTR("after") , &kSCValNetPPPAuthPromptAfter , 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static selections authProtocolSelections[] = {
+ { CFSTR("CHAP") , &kSCValNetPPPAuthProtocolCHAP , 0 },
+ { CFSTR("EAP") , &kSCValNetPPPAuthProtocolEAP , 0 },
+ { CFSTR("MSCHAP1"), &kSCValNetPPPAuthProtocolMSCHAP1, 0 },
+ { CFSTR("MSCHAP2"), &kSCValNetPPPAuthProtocolMSCHAP2, 0 },
+ { CFSTR("PAP") , &kSCValNetPPPAuthProtocolPAP , 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static options pppOptions[] = {
+ { "ACSP" , NULL , isBoolean , &kSCPropNetPPPACSPEnabled , NULL , NULL },
+ { "ConnectTime" , "?time" , isNumber , &kSCPropNetPPPConnectTime , NULL , NULL },
+ { "DialOnDemand" , NULL , isBoolean , &kSCPropNetPPPDialOnDemand , NULL , NULL },
+ { "DisconnectOnFastUserSwitch", NULL , isBoolean , &kSCPropNetPPPDisconnectOnFastUserSwitch, NULL , NULL },
+ { "DisconnectOnIdle" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnIdle , NULL , NULL },
+ { "DisconnectOnIdleTimer" , "timeout" , isNumber , &kSCPropNetPPPDisconnectOnIdleTimer , NULL , NULL },
+ { "DisconnectOnLogout" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnLogout , NULL , NULL },
+ { "DisconnectOnSleep" , NULL , isBoolean , &kSCPropNetPPPDisconnectOnSleep , NULL , NULL },
+ { "DisconnectTime" , "?time" , isNumber , &kSCPropNetPPPDisconnectTime , NULL , NULL },
+ { "IdleReminder" , NULL , isBoolean , &kSCPropNetPPPIdleReminder , NULL , NULL },
+ { "IdleReminderTimer" , "time" , isNumber , &kSCPropNetPPPIdleReminderTimer , NULL , NULL },
+ { "Logfile" , "path" , isString , &kSCPropNetPPPLogfile , NULL , NULL },
+ { "Plugins" , "plugin" , isStringArray , &kSCPropNetPPPPlugins , NULL , NULL },
+ { "RetryConnectTime" , "time" , isNumber , &kSCPropNetPPPRetryConnectTime , NULL , NULL },
+ { "SessionTimer" , "time" , isNumber , &kSCPropNetPPPSessionTimer , NULL , NULL },
+ { "UseSessionTimer" , NULL , isBoolean , &kSCPropNetPPPUseSessionTimer , NULL , NULL },
+ { "VerboseLogging" , NULL , isBoolean , &kSCPropNetPPPVerboseLogging , NULL , NULL },
+
+ // --- Auth: ---
+ { "AuthEAPPlugins" , "plugin" , isStringArray , &kSCPropNetPPPAuthEAPPlugins , NULL , NULL },
+ { "AuthName" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL },
+ { "Account" , "account" , isString , &kSCPropNetPPPAuthName , NULL , NULL },
+ { "AuthPassword" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL },
+ { "Password" , "password" , isOther , &kSCPropNetPPPAuthPassword , __doPPPAuthPW , NULL },
+ { "AuthPasswordEncryption" , "type" , isOther , &kSCPropNetPPPAuthPasswordEncryption , __doPPPAuthPWType, NULL },
+ { "AuthPrompt" , "before/after", isChooseOne , &kSCPropNetPPPAuthPrompt , NULL , (void *)authPromptSelections },
+ { "AuthProtocol" , "protocol" , isChooseMultiple , &kSCPropNetPPPAuthProtocol , NULL , (void *)authProtocolSelections },
+
+ // --- Comm: ---
+ { "CommRemoteAddress" , "phone#" , isString , &kSCPropNetPPPCommRemoteAddress , NULL , NULL },
+ { "CommAlternateRemoteAddress", "phone#" , isString , &kSCPropNetPPPCommAlternateRemoteAddress, NULL , NULL },
+ { "CommConnectDelay" , "time" , isNumber , &kSCPropNetPPPCommConnectDelay , NULL , NULL },
+ { "CommDisplayTerminalWindow" , NULL , isBoolean , &kSCPropNetPPPCommDisplayTerminalWindow , NULL , NULL },
+ { "CommRedialCount" , "retry count" , isNumber , &kSCPropNetPPPCommRedialCount , NULL , NULL },
+ { "CommRedialEnabled" , NULL , isBoolean , &kSCPropNetPPPCommRedialEnabled , NULL , NULL },
+ { "CommRedialInterval" , "retry delay" , isNumber , &kSCPropNetPPPCommRedialInterval , NULL , NULL },
+ { "CommTerminalScript" , "script" , isString , &kSCPropNetPPPCommTerminalScript , NULL , NULL },
+ { "CommUseTerminalScript" , NULL , isBoolean , &kSCPropNetPPPCommUseTerminalScript , NULL , NULL },
+
+ // --- CCP: ---
+ { "CCPEnabled" , NULL , isBoolean , &kSCPropNetPPPCCPEnabled , NULL , NULL },
+ { "CCPMPPE40Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE40Enabled , NULL , NULL },
+ { "CCPMPPE128Enabled" , NULL , isBoolean , &kSCPropNetPPPCCPMPPE128Enabled , NULL , NULL },
+
+ // --- IPCP: ---
+ { "IPCPCompressionVJ" , NULL , isBoolean , &kSCPropNetPPPIPCPCompressionVJ , NULL , NULL },
+ { "IPCPUsePeerDNS" , NULL , isBoolean , &kSCPropNetPPPIPCPUsePeerDNS , NULL , NULL },
+
+ // --- LCP: ---
+ { "LCPEchoEnabled" , NULL , isBoolean , &kSCPropNetPPPLCPEchoEnabled , NULL , NULL },
+ { "LCPEchoFailure" , NULL , isNumber , &kSCPropNetPPPLCPEchoFailure , NULL , NULL },
+ { "LCPEchoInterval" , NULL , isNumber , &kSCPropNetPPPLCPEchoInterval , NULL , NULL },
+ { "LCPCompressionACField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionACField , NULL , NULL },
+ { "LCPCompressionPField" , NULL , isBoolean , &kSCPropNetPPPLCPCompressionPField , NULL , NULL },
+ { "LCPMRU" , NULL , isNumber , &kSCPropNetPPPLCPMRU , NULL , NULL },
+ { "LCPMTU" , NULL , isNumber , &kSCPropNetPPPLCPMTU , NULL , NULL },
+ { "LCPReceiveACCM" , NULL , isNumber , &kSCPropNetPPPLCPReceiveACCM , NULL , NULL },
+ { "LCPTransmitACCM" , NULL , isNumber , &kSCPropNetPPPLCPTransmitACCM , NULL , NULL },
+
+ // --- Help ---
+ { "?" , NULL , isHelp , NULL , NULL ,
+ "\nPPP configuration commands\n\n"
+ " set interface [Account account]\n"
+ " set interface [Password password]\n"
+ " set interface [Number telephone-number]\n"
+ " set interface [AlternateNumber telephone-number]\n"
+ " set interface [IdleReminder {enable|disable}]\n"
+ " set interface [IdleReminderTimer time-in-seconds]\n"
+ " set interface [DisconnectOnIdle {enable|disable}]\n"
+ " set interface [DisconnectOnIdleTimer time-in-seconds]\n"
+ " set interface [DisconnectOnLogout {enable|disable}]"
+ }
+};
+#define N_PPP_OPTIONS (sizeof(pppOptions) / sizeof(pppOptions[0]))
+
+
+static Boolean
+set_interface_ppp(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(pppOptions, N_PPP_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+set_interface_vlan(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+// xxxxx ("device", "tag")
+SCPrint(TRUE, stdout, CFSTR("vlan interface management not yet supported\n"));
+ return FALSE;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+set_interface(int argc, char **argv)
+{
+ CFDictionaryRef configuration;
+ CFStringRef interfaceType;
+ CFMutableDictionaryRef newConfiguration = NULL;
+ Boolean ok = FALSE;
+
+ if (net_interface == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
+ return;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return;
+ }
+
+ configuration = SCNetworkInterfaceGetConfiguration(net_interface);
+ if (configuration == NULL) {
+ newConfiguration = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ } else {
+ newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
+ CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
+ }
+
+ interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
+
+ if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
+ ok = set_interface_bond(argc, argv, newConfiguration);
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet)) {
+ ok = set_interface_ethernet(argc, argv, newConfiguration);
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeModem)) {
+ ok = set_interface_modem(argc, argv, newConfiguration);
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIEEE80211)) {
+ ok = set_interface_airport(argc, argv, newConfiguration);
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
+ ok = set_interface_ppp(argc, argv, newConfiguration);
+ } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
+ ok = set_interface_vlan(argc, argv, newConfiguration);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n"));
+ }
+
+ if (!ok) {
+ goto done;
+ }
+
+ if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
+ ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
+ if (!SCNetworkInterfaceSetConfiguration(net_interface, newConfiguration)) {
+ if (SCError() == kSCStatusNoKey) {
+ SCPrint(TRUE, stdout, CFSTR("could not update per-service interface configuration\n"));
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ }
+ goto done;
+ }
+
+ net_changed = TRUE;
+ }
+
+ done :
+
+ if (newConfiguration != NULL) CFRelease(newConfiguration);
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_interface(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+
+ if (argc == 1) {
+ interface = _find_interface(argv[0]);
+ } else {
+ if (net_interface != NULL) {
+ interface = net_interface;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
+ return;
+ }
+ }
+
+ if (interface != NULL) {
+ _show_interface(interface, CFSTR(""), TRUE);
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFStringRef
+_interface_description(SCNetworkInterfaceRef interface)
+{
+ CFMutableStringRef description;
+ CFStringRef if_bsd_name;
+ CFStringRef if_type;
+
+ description = CFStringCreateMutable(NULL, 0);
+
+ if_type = SCNetworkInterfaceGetInterfaceType(interface);
+ CFStringAppend(description, if_type);
+
+ if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
+ if (if_bsd_name != NULL) {
+ CFStringAppendFormat(description, NULL, CFSTR(" (%@)"), if_bsd_name);
+ }
+
+ interface = SCNetworkInterfaceGetInterface(interface);
+ while ((interface != NULL) &&
+ !CFEqual(interface, kSCNetworkInterfaceIPv4)) {
+ CFStringRef childDescription;
+
+ childDescription = _interface_description(interface);
+ CFStringAppendFormat(description, NULL, CFSTR(" / %@"), childDescription);
+ CFRelease(childDescription);
+
+ interface = SCNetworkInterfaceGetInterface(interface);
+ }
+
+ return description;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_INTERFACE_H
+#define _NET_INTERFACE_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+CFStringRef _interface_description (SCNetworkInterfaceRef interface);
+SCNetworkInterfaceRef _find_interface (char *match);
+
+void create_interface (int argc, char **argv);
+void select_interface (int argc, char **argv);
+void set_interface (int argc, char **argv);
+void show_interface (int argc, char **argv);
+void show_interfaces (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_INTERFACE_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+#include "net_protocol.h"
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFComparisonResult
+_compare_protocols(const void *val1, const void *val2, void *context)
+{
+ SCNetworkProtocolRef p1 = (SCNetworkProtocolRef)val1;
+ SCNetworkProtocolRef p2 = (SCNetworkProtocolRef)val2;
+ CFStringRef type1;
+ CFStringRef type2;
+
+ type1 = SCNetworkProtocolGetProtocolType(p1);
+ type2 = SCNetworkProtocolGetProtocolType(p2);
+
+ return CFStringCompare(type1, type2, 0);
+}
+
+
+static CFStringRef
+__copyIPv4Address(const char *arg)
+{
+ char buf[128];
+ struct sockaddr_in sin;
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ if (inet_aton(arg, &sin.sin_addr) != 1) {
+ return NULL;
+ }
+
+ _SC_sockaddr_to_string((struct sockaddr *)&sin, buf, sizeof(buf));
+ return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
+}
+
+
+static CFStringRef
+__copyIPv6Address(const char *arg)
+{
+ char buf[128];
+ char *p;
+ struct sockaddr_in6 sin6;
+
+ bzero(&sin6, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ if (inet_pton(AF_INET6, arg, &sin6.sin6_addr) != 1) {
+ return NULL;
+ }
+
+ p = strchr(arg, '%');
+ if (p != NULL) {
+ sin6.sin6_scope_id = if_nametoindex(p+1);
+ }
+
+ _SC_sockaddr_to_string((struct sockaddr *)&sin6, buf, sizeof(buf));
+ return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
+}
+
+
+/* -------------------- */
+
+
+static SCNetworkProtocolRef
+_find_protocol(char *match)
+{
+ Boolean allowIndex = TRUE;
+ CFIndex i;
+ CFIndex n;
+ CFStringRef select_name = NULL;
+ SCNetworkProtocolRef selected = NULL;
+
+ if (protocols == NULL) {
+ if (net_service == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network service not selected\n"));
+ return NULL;
+ }
+
+ protocols = SCNetworkServiceCopyProtocols(net_service);
+ if (protocols == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return NULL;
+ }
+
+ n = CFArrayGetCount(protocols);
+ if (n > 1) {
+ CFMutableArrayRef sorted;
+
+ sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, n),
+ _compare_protocols,
+ NULL);
+ CFRelease(protocols);
+ protocols = sorted;
+ }
+
+ allowIndex = FALSE;
+ }
+
+ // try to select the protocol by its protocol type
+
+ select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+ n = CFArrayGetCount(protocols);
+ for (i = 0; i < n; i++) {
+ SCNetworkProtocolRef protocol;
+ CFStringRef type;
+
+ protocol = CFArrayGetValueAtIndex(protocols, i);
+ type = SCNetworkProtocolGetProtocolType(protocol);
+ if (CFStringCompare(select_name, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ selected = protocol;
+ goto done;
+ }
+ }
+
+ if (allowIndex) {
+ char *end;
+ char *str = match;
+ long val;
+
+ // try to select the protocol by its index
+
+ errno = 0;
+ val = strtol(str, &end, 10);
+ if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+ if ((val > 0) && (val <= n)) {
+ selected = CFArrayGetValueAtIndex(protocols, val - 1);
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("no match, which protocol?\n"));
+
+ done :
+
+ if (select_name != NULL) CFRelease(select_name);
+ return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_protocol(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+ CFStringRef protocolType;
+
+ if ((argc < 1) || (strlen(argv[0]) == 0)) {
+ SCPrint(TRUE, stdout, CFSTR("what protocol type?\n"));
+ return;
+ }
+
+ if (net_service == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network service not selected\n"));
+ return;
+ }
+
+ protocolType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+ interface = SCNetworkServiceGetInterface(net_service);
+ if (interface != NULL) {
+ CFArrayRef supported;
+ CFIndex i;
+ CFIndex n;
+
+ supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
+ n = (supported != NULL) ? CFArrayGetCount(supported) : 0;
+ for (i = 0; i < n; i++) {
+ CFStringRef supportedType;
+
+ supportedType = CFArrayGetValueAtIndex(supported, i);
+ if (CFStringCompare(protocolType,
+ supportedType,
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ CFRelease(protocolType);
+ protocolType = CFRetain(supportedType);
+ break;
+ }
+ }
+ }
+
+ if (!SCNetworkServiceAddProtocolType(net_service, protocolType)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ net_changed = TRUE;
+
+ if (protocols != NULL) {
+ CFRelease(protocols);
+ protocols = NULL;
+ }
+
+ if (net_protocol != NULL) CFRelease(net_protocol);
+// net_protocol = NULL;
+
+ net_protocol = SCNetworkServiceCopyProtocol(net_service, protocolType);
+ if (net_protocol == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ SCPrint(TRUE, stdout,
+ CFSTR("protocol \"%@\" selected\n"),
+ protocolType);
+
+ done :
+
+ CFRelease(protocolType);
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+disable_protocol(int argc, char **argv)
+{
+ SCNetworkProtocolRef protocol = NULL;
+
+ if (argc > 0) {
+ protocol = _find_protocol(argv[0]);
+ } else {
+ if (net_protocol != NULL) {
+ protocol = net_protocol;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+ return;
+ }
+ }
+
+ if (protocol == NULL) {
+ return;
+ }
+
+ if (!SCNetworkProtocolSetEnabled(protocol, FALSE)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+enable_protocol(int argc, char **argv)
+{
+ SCNetworkProtocolRef protocol = NULL;
+
+ if (argc > 0) {
+ protocol = _find_protocol(argv[0]);
+ } else {
+ if (net_protocol != NULL) {
+ protocol = net_protocol;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+ return;
+ }
+ }
+
+ if (protocol == NULL) {
+ return;
+ }
+
+ if (!SCNetworkProtocolSetEnabled(protocol, TRUE)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+remove_protocol(int argc, char **argv)
+{
+ SCNetworkProtocolRef protocol = NULL;
+ CFStringRef protocolType;
+
+ if (argc > 0) {
+ protocol = _find_protocol(argv[0]);
+ } else {
+ if (net_protocol != NULL) {
+ protocol = net_protocol;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+ return;
+ }
+ }
+
+ if (protocol == NULL) {
+ return;
+ }
+
+ CFRetain(protocol);
+
+ protocolType = SCNetworkProtocolGetProtocolType(protocol);
+ if (!SCNetworkServiceRemoveProtocolType(net_service, protocolType)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ net_changed = TRUE;
+
+ SCPrint(TRUE, stdout,
+ CFSTR("protocol \"%@\" removed\n"),
+ protocolType);
+
+ if ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ if (protocols != NULL) {
+ CFRelease(protocols);
+ protocols = NULL;
+ }
+
+ done :
+
+ CFRelease(protocol);
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+select_protocol(int argc, char **argv)
+{
+ SCNetworkProtocolRef protocol;
+
+ protocol = _find_protocol(argv[0]);
+
+ if (protocol == NULL) {
+ return;
+ }
+
+ if (net_protocol != NULL) CFRelease(net_protocol);
+ net_protocol = CFRetain(protocol);
+
+ SCPrint(TRUE, stdout,
+ CFSTR("protocol \"%@\" selected\n"),
+ SCNetworkProtocolGetProtocolType(protocol));
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+static selections appletalkConfigMethods[] = {
+ { CFSTR("node") , &kSCValNetAppleTalkConfigMethodNode , 0 },
+ { CFSTR("router") , &kSCValNetAppleTalkConfigMethodRouter , 0 },
+ { CFSTR("seedrouter"), &kSCValNetAppleTalkConfigMethodSeedRouter, 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static int
+__doAppleTalkConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFStringRef configMethod;
+
+ configMethod = CFDictionaryGetValue(newConfiguration, key);
+ if (!CFEqual(key, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetAppleTalkSeedZones);
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetAppleTalkSeedNetworkRange);
+ }
+
+ return 0;
+}
+
+
+static int
+__doAppleTalkNetworkRange(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("network range not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFArrayRef array;
+ char *cp;
+ CFNumberRef range[2];
+
+ range[0] = _copy_number(argv[0]);
+ if (range[0] == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("invalid start of range\n"));
+ return -1;
+ }
+
+ cp = strchr(argv[0], '-');
+ if (cp == NULL) {
+ range[1] = _copy_number(cp);
+ if (range[1] == NULL) {
+ CFRelease(range[0]);
+ SCPrint(TRUE, stdout, CFSTR("invalid end of range\n"));
+ return -1;
+ }
+ } else {
+ range[1] = CFRetain(range[0]);
+ }
+
+ array = CFArrayCreate(NULL,
+ (const void **)range,
+ sizeof(range)/sizeof(range[0]),
+ &kCFTypeArrayCallBacks);
+ CFRelease(range[0]);
+ CFRelease(range[1]);
+
+ CFDictionarySetValue(newConfiguration, key, array);
+ CFRelease(array);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static options appletalkOptions[] = {
+ { "ConfigMethod" , "configuration method"
+ , isChooseOne , &kSCPropNetAppleTalkConfigMethod , __doAppleTalkConfigMethod, (void *)appletalkConfigMethods },
+ { "config" , "configuration method"
+ , isChooseOne , &kSCPropNetAppleTalkConfigMethod , __doAppleTalkConfigMethod, (void *)appletalkConfigMethods },
+ { "DefaultZone" , "zone" , isString , &kSCPropNetAppleTalkDefaultZone , NULL , NULL },
+ { "NodeID" , "node" , isNumber , &kSCPropNetAppleTalkNodeID , NULL , NULL },
+ { "NetworkID" , "network", isNumber , &kSCPropNetAppleTalkNetworkID , NULL , NULL },
+ { "SeedNetworkRange", "range" , isOther , &kSCPropNetAppleTalkSeedNetworkRange, __doAppleTalkNetworkRange, NULL },
+ { "SeedZones" , "zone" , isStringArray, &kSCPropNetAppleTalkSeedZones , NULL , NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL ,
+ "\nAppleTalk configuration commands\n\n"
+ " set protocol config {Node|Router|SeedRouter}\n"
+ " set protocol defaultzone zone\n"
+ " set protocol node id\n"
+ " set protocol network id\n"
+ "\n w/config=Node\n"
+ " None\n"
+ "\n w/config=Router\n"
+ " None\n"
+ "\n w/config=SeedRouter\n"
+ " set protocol seednetworkrange low[-high]\n"
+ " set protocol seedzones zone[,zone-2]\n"
+ }
+};
+#define N_APPLETALK_OPTIONS (sizeof(appletalkOptions) / sizeof(appletalkOptions[0]))
+
+
+static Boolean
+set_protocol_appletalk(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(appletalkOptions, N_APPLETALK_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+static CFStringRef
+__cleanupDomainName(CFStringRef domain)
+{
+ CFMutableStringRef newDomain;
+
+ newDomain = CFStringCreateMutableCopy(NULL, 0, domain);
+ CFStringTrimWhitespace(newDomain);
+ CFStringTrim(newDomain, CFSTR("."));
+ if (CFStringGetLength(newDomain) == 0) {
+ CFRelease(newDomain);
+ newDomain = NULL;
+ }
+
+ return newDomain;
+}
+
+
+static int
+__doDNSDomain(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("DNS domain name not specified\n"));
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef domain;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ domain = __cleanupDomainName(str);
+ CFRelease(str);
+
+ if (domain != NULL) {
+ CFDictionarySetValue(newConfiguration, key, domain);
+ CFRelease(domain);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("invalid DNS domain name\n"));
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static int
+__doDNSDomainArray(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFMutableArrayRef domains;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
+ return -1;
+ }
+
+ domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if (strlen(argv[0]) > 0) {
+ CFArrayRef array;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+ CFRelease(str);
+
+ if (array != NULL) {
+ CFIndex i;
+ CFIndex n = CFArrayGetCount(array);
+
+ for (i = 0; i < n; i++) {
+ CFStringRef domain;
+
+ domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i));
+ if (domain != NULL) {
+ CFArrayAppendValue(domains, domain);
+ CFRelease(domain);
+ } else {
+ CFRelease(array);
+ CFRelease(domains);
+ SCPrint(TRUE, stdout, CFSTR("invalid DNS search domain name\n"));
+ return -1;
+ }
+ }
+ CFRelease(array);
+ }
+ }
+
+ if (CFArrayGetCount(domains) > 0) {
+ CFDictionarySetValue(newConfiguration, key, domains);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ CFRelease(domains);
+ return 1;
+}
+
+
+static int
+__doDNSServerAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFMutableArrayRef servers;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
+ return -1;
+ }
+
+ servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if (strlen(argv[0]) > 0) {
+ CFArrayRef array;
+ CFIndex i;
+ CFIndex n;
+ CFStringRef str;
+
+ str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+ CFRelease(str);
+
+ n = (array != NULL) ? CFArrayGetCount(array) : 0;
+ for (i = 0; i < n; i++) {
+ char str[32];
+
+ if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
+ str,
+ sizeof(str),
+ kCFStringEncodingUTF8) != NULL) {
+ CFStringRef server;
+
+ server = __copyIPv4Address(str);
+ if (server == NULL) {
+ server = __copyIPv6Address(str);
+ }
+ if (server != NULL) {
+ CFArrayAppendValue(servers, server);
+ CFRelease(server);
+ continue;
+ }
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("invalid DNS name server address\n"));
+ CFRelease(array);
+ CFRelease(servers);
+ return -1;
+ }
+ if (array != NULL) CFRelease(array);
+ }
+
+ if (CFArrayGetCount(servers) > 0) {
+ CFDictionarySetValue(newConfiguration, key, servers);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ CFRelease(servers);
+ return 1;
+}
+
+
+static options dnsOptions[] = {
+ { "DomainName" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL },
+ { "domain" , "domain" , isOther, &kSCPropNetDNSDomainName , __doDNSDomain , NULL },
+ { "SearchDomains" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL },
+ { "search" , "search" , isOther, &kSCPropNetDNSSearchDomains , __doDNSDomainArray , NULL },
+ { "ServerAddresses", "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
+ { "nameserver" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
+ { "nameservers" , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL,
+ "\nDNS configuration commands\n\n"
+ " set protocol search domain-name[,domain-name-2]\n"
+ " set protocol nameserver x1.x1.x1.x1[,x2.x2.x2.x2]"
+ }
+};
+#define N_DNS_OPTIONS (sizeof(dnsOptions) / sizeof(dnsOptions[0]))
+
+
+static Boolean
+set_protocol_dns(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(dnsOptions, N_DNS_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+#define allowIPv4Address 1<<1 // allow address
+#define allowIPv4Netmask 1<<2 // allow subnet mask
+#define allowIPv4Router 1<<3 // allow router
+#define allowIPv4DHCPClientID 1<<4 // allow DCHP Client ID
+
+static selections ipv4ConfigMethods[] = {
+ { CFSTR("BOOTP") , &kSCValNetIPv4ConfigMethodBOOTP , 0 },
+ { CFSTR("DHCP") , &kSCValNetIPv4ConfigMethodDHCP , allowIPv4DHCPClientID },
+ { CFSTR("INFORM") , &kSCValNetIPv4ConfigMethodINFORM , allowIPv4Address },
+ { CFSTR("LinkLocal"), &kSCValNetIPv4ConfigMethodLinkLocal, 0 },
+ { CFSTR("Manual") , &kSCValNetIPv4ConfigMethodManual , allowIPv4Address|allowIPv4Netmask|allowIPv4Router },
+ { CFSTR("PPP") , &kSCValNetIPv4ConfigMethodPPP , allowIPv4Address|selectionNotAvailable },
+ { NULL , NULL , 0 }
+};
+
+
+static int
+__doIPv4ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ unsigned int flags;
+ CFStringRef method;
+ CFIndex methodIndex;
+
+ method = CFDictionaryGetValue(newConfiguration, key);
+ methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
+ if (methodIndex != kCFNotFound) {
+ if (!(flags & allowIPv4Address)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Addresses);
+ }
+ if (!(flags & allowIPv4Netmask)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4SubnetMasks);
+ }
+ if (!(flags & allowIPv4Router)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Router);
+ }
+ if (!(flags & allowIPv4DHCPClientID)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4DHCPClientID);
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+__doIPv4Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE;
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef address;
+
+ address = __copyIPv4Address(argv[0]);
+ if (address != NULL) {
+ if (useArray) {
+ CFArrayRef addresses;
+
+ addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
+ CFDictionarySetValue(newConfiguration, key, addresses);
+ CFRelease(addresses);
+ } else {
+ CFDictionarySetValue(newConfiguration, key, address);
+ }
+ CFRelease(address);
+ } else {
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static options ipv4Options[] = {
+ { "ConfigMethod", "configuration method"
+ , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
+ { "config" , "configuration method"
+ , isChooseOne , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
+ { "Addresses" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE },
+ { "address" , "address" , isOther , &kSCPropNetIPv4Addresses , __doIPv4Addresses , (void *)TRUE },
+ { "SubnetMasks" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE },
+ { "netmask" , "netmask" , isOther , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses , (void *)TRUE },
+ { "Router" , "address" , isOther , &kSCPropNetIPv4Router , __doIPv4Addresses , (void *)FALSE },
+ { "DHCPClientID", "client ID", isString , &kSCPropNetIPv4DHCPClientID, NULL , NULL },
+
+ { "?" , NULL , isHelp , NULL , NULL ,
+ "\nIPv4 configuration commands\n\n"
+ " set protocol config {BOOTP|DHCP|INFORM|MANUAL}\n"
+ "\n w/config=BOOTP\n"
+ " None\n"
+ "\n w/config=DHCP\n"
+ " set protocol dhcpclientid identifier\n"
+ "\n w/config=INFORM\n"
+ " set protocol address x.x.x.x\n"
+ "\n w/config=MANUAL\n"
+ " set protocol address x.x.x.x\n"
+ " set protocol netmask x.x.x.x\n"
+ " set protocol router x.x.x.x\n"
+ }
+};
+#define N_IPV4_OPTIONS (sizeof(ipv4Options) / sizeof(ipv4Options[0]))
+
+
+static Boolean
+set_protocol_ipv4(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(ipv4Options, N_IPV4_OPTIONS, argc, argv, newConfiguration);
+ if (ok) {
+ unsigned int flags;
+ CFStringRef method;
+ CFIndex methodIndex;
+
+ // validate configuration
+ method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv4ConfigMethod);
+ methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
+ if (methodIndex == kCFNotFound) {
+ SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv4Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Addresses)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("IP address not allowed with %@ configuration\n"),
+ ipv4ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv4Netmask) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4SubnetMasks)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("Subnet mask not allowed with %@ configuration\n"),
+ ipv4ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv4Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Router)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("Default route not allowed with %@ configuration\n"),
+ ipv4ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv4DHCPClientID) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4DHCPClientID)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("DHCP client ID not allowed with %@ configuration\n"),
+ ipv4ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+ }
+
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+#define allowIPv6Address 1<<1 // allow address
+#define allowIPv6PrefixLength 1<<2 // allow prefix length
+#define allowIPv6Router 1<<3 // allow router
+
+static selections ipv6ConfigMethods[] = {
+ { CFSTR("Automatic") , & kSCValNetIPv6ConfigMethodAutomatic , 0 },
+ { CFSTR("Manual") , & kSCValNetIPv6ConfigMethodManual , allowIPv6Address|allowIPv6PrefixLength|allowIPv6Router },
+ { CFSTR("RouterAdvertisement"), & kSCValNetIPv6ConfigMethodRouterAdvertisement, allowIPv6Address },
+ { CFSTR("6to4") , & kSCValNetIPv6ConfigMethod6to4 , 0 },
+ { NULL , NULL , 0 }
+};
+
+
+static int
+__doIPv6ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ unsigned int flags;
+ CFStringRef method;
+ CFIndex methodIndex;
+
+ method = CFDictionaryGetValue(newConfiguration, key);
+ methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
+ if (methodIndex != kCFNotFound) {
+ if (!(flags & allowIPv6Address)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Addresses);
+ }
+ if (!(flags & allowIPv6PrefixLength)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6PrefixLength);
+ }
+ if (!(flags & allowIPv6Router)) {
+ CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Router);
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+__doIPv6Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean useArray = (info == (void *)FALSE) ? FALSE : TRUE;
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef address;
+
+ address = __copyIPv6Address(argv[0]);
+ if (address != NULL) {
+ if (useArray) {
+ CFArrayRef addresses;
+
+ addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
+ CFDictionarySetValue(newConfiguration, key, addresses);
+ CFRelease(addresses);
+ } else {
+ CFDictionarySetValue(newConfiguration, key, address);
+ }
+ CFRelease(address);
+ } else {
+ return -1;
+ }
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, key);
+ }
+
+ return 1;
+}
+
+
+static int
+__doIPv6PrefixLength(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFNumberRef num;
+ int prefixLength;
+
+ num = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
+ if (isA_CFNumber(num) &&
+ CFNumberGetValue(num, kCFNumberIntType, &prefixLength) &&
+ (prefixLength >= 0) && (prefixLength <= (sizeof(struct in6_addr) * 8))) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static options ipv6Options[] = {
+ { "ConfigMethod", "configuration method"
+ , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
+ { "config" , "configuration method"
+ , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
+ { "Addresses" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
+ { "address" , "address" , isOther , &kSCPropNetIPv6Addresses , __doIPv6Addresses , (void *)TRUE },
+ { "PrefixLength", "prefix length", isNumber , &kSCPropNetIPv6PrefixLength, __doIPv6PrefixLength, NULL },
+ { "Router" , "address" , isOther , &kSCPropNetIPv6Router , __doIPv6Addresses , (void *)FALSE },
+
+ { "?" , NULL , isHelp , NULL , NULL ,
+ "\nIPv6 configuration commands\n\n"
+ " set protocol config {Automatic|MANUAL}\n"
+ "\n w/config=Automatic\n"
+ " None\n"
+ "\n w/config=MANUAL\n"
+ " set protocol address x:x:x:x:x:x\n"
+ " set protocol router x:x:x:x:x:x\n"
+ " set protocol prefixlength n\n"
+ }
+};
+#define N_IPV6_OPTIONS (sizeof(ipv6Options) / sizeof(ipv6Options[0]))
+
+
+static Boolean
+set_protocol_ipv6(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(ipv6Options, N_IPV6_OPTIONS, argc, argv, newConfiguration);
+ if (ok) {
+ unsigned int flags;
+ CFStringRef method;
+ CFIndex methodIndex;
+
+ // validate configuration
+ method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv6ConfigMethod);
+ methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
+ if (methodIndex == kCFNotFound) {
+ SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv6Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Addresses)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("IP address not allowed with %@ configuration\n"),
+ ipv6ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv6PrefixLength) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6PrefixLength)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("Prefix length not allowed with %@ configuration\n"),
+ ipv6ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+
+ if (!(flags & allowIPv6Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Router)) {
+ SCPrint(TRUE, stdout,
+ CFSTR("Router not allowed with %@ configuration\n"),
+ ipv6ConfigMethods[methodIndex].selection);
+ return FALSE;
+ }
+ }
+
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+typedef const struct {
+ const char *proxy;
+ const CFStringRef *keyEnable;
+ const CFStringRef *keyProxy;
+ const CFStringRef *keyPort;
+ const CFStringRef *keyURL;
+} proxyKeys;
+
+static proxyKeys proxyKeys_FTP = { "FTP" , &kSCPropNetProxiesFTPEnable , &kSCPropNetProxiesFTPProxy , &kSCPropNetProxiesFTPPort , NULL };
+static proxyKeys proxyKeys_Gopher = { "Gopher", &kSCPropNetProxiesGopherEnable , &kSCPropNetProxiesGopherProxy, &kSCPropNetProxiesGopherPort, NULL };
+static proxyKeys proxyKeys_HTTP = { "HTTP" , &kSCPropNetProxiesHTTPEnable , &kSCPropNetProxiesHTTPProxy , &kSCPropNetProxiesHTTPPort , NULL };
+static proxyKeys proxyKeys_HTTPS = { "HTTPS" , &kSCPropNetProxiesHTTPSEnable , &kSCPropNetProxiesHTTPSProxy , &kSCPropNetProxiesHTTPSPort , NULL };
+static proxyKeys proxyKeys_RTSP = { "RTSP" , &kSCPropNetProxiesRTSPEnable , &kSCPropNetProxiesRTSPProxy , &kSCPropNetProxiesRTSPPort , NULL };
+static proxyKeys proxyKeys_SOCKS = { "SOCKS" , &kSCPropNetProxiesSOCKSEnable , &kSCPropNetProxiesSOCKSProxy , &kSCPropNetProxiesSOCKSPort , NULL };
+static proxyKeys proxyKeys_PAC = { ".pac" , &kSCPropNetProxiesProxyAutoConfigEnable , NULL , NULL , &kSCPropNetProxiesProxyAutoConfigURLString };
+static proxyKeys proxyKeys_WPAD = { "WPAD" , &kSCPropNetProxiesProxyAutoDiscoveryEnable, NULL , NULL , NULL };
+
+static proxyKeys *currentProxy = NULL;
+
+
+static int __doProxySelect (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyEnable (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyHost (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyPort (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyURL (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+
+
+static options proxyOptions[] = {
+ // general options
+ { "ExceptionsList" , "exceptions", isStringArray, &kSCPropNetProxiesExceptionsList , NULL , NULL },
+ { "ExcludeSimpleHostnames", NULL , isBoolean , &kSCPropNetProxiesExcludeSimpleHostnames, NULL , NULL },
+ // proxy selection
+ { "FTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_FTP },
+ { "Gopher" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_Gopher },
+ { "HTTP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTP },
+ { "HTTPS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_HTTPS },
+ { "RTSP" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_RTSP },
+ { "SOCKS" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_SOCKS },
+ { "ProxyAutoConfig" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
+ { ".pac" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_PAC },
+ { "ProxyAutoDiscovery" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
+ { "WPAD" , NULL , isOther , NULL , __doProxySelect , (void *)&proxyKeys_WPAD },
+ // proxy modifiers
+ { "disable" , NULL , isOther , NULL , __doProxyEnable , (void *)FALSE },
+ { "enable" , NULL , isOther , NULL , __doProxyEnable , (void *)TRUE },
+ { "proxy" , NULL , isOther , NULL , __doProxyHost , NULL },
+ { "host" , NULL , isOther , NULL , __doProxyHost , NULL },
+ { "port" , NULL , isOther , NULL , __doProxyPort , NULL },
+ { "url" , NULL , isOther , NULL , __doProxyURL , NULL },
+ // (ftp) proxy modifiers
+ { "FTPPassive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
+ { "passive" , NULL , isBoolean , &kSCPropNetProxiesFTPPassive , __doProxyFTPPassive, NULL },
+ // help
+ { "?" , NULL , isHelp , NULL , NULL ,
+ "\nProxy configuration commands\n\n"
+ " set protocol ExceptionsList exception[,exception-2]\n"
+ " set protocol ExcludeSimpleHostnames {enable|disable}\n"
+ "\n"
+ " set protocol ftp {enable|disable}\n"
+ " set protocol ftp host proxy-host\n"
+ " set protocol ftp port proxy-port\n"
+ " set protocol ftp passive {enable|disable}\n"
+ "\n"
+ " set protocol http {enable|disable}\n"
+ " set protocol http host proxy-host\n"
+ " set protocol http port proxy-port\n"
+ "\n"
+ " set protocol https {enable|disable}\n"
+ " set protocol https host proxy-host\n"
+ " set protocol https port proxy-port\n"
+ "\n"
+ " set protocol rtsp {enable|disable}\n"
+ " set protocol rtsp host proxy-host\n"
+ " set protocol rtsp port proxy-port\n"
+ "\n"
+ " set protocol socks {enable|disable}\n"
+ " set protocol socks host proxy-host\n"
+ " set protocol socks port proxy-port\n"
+ "\n"
+ " set protocol .pac {enable|disable}\n"
+ " set protocol .pac url .pac-url\n"
+ "\n"
+ " set protocol wpad {enable|disable}\n"
+ }
+};
+#define N_PROXY_OPTIONS (sizeof(proxyOptions) / sizeof(proxyOptions[0]))
+
+
+static int
+__doProxySelect(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ CFIndex nextOption;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("proxy option[s] not specified\n"));
+ return -1;
+ }
+
+ currentProxy = (proxyKeys *)info;
+
+ nextOption = _find_option(argv[0], proxyOptions, N_PROXY_OPTIONS);
+ if ((nextOption == kCFNotFound) ||
+ (proxyOptions[nextOption].handler == __doProxySelect)) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy option[s] not specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+__doProxyEnable(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean enabled = (info == (void *)FALSE) ? FALSE : TRUE;
+
+ if (currentProxy == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+ return -1;
+ }
+
+ if (currentProxy->keyEnable == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy cannot be %s\n"),
+ currentProxy->proxy,
+ enabled ? "enabled" : "disabled");
+ return -1;
+ }
+
+
+ if (enabled) {
+ CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_1);
+ } else {
+ CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_0);
+
+ if (currentProxy->keyProxy != NULL) {
+ CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
+ }
+
+ if (currentProxy->keyPort != NULL) {
+ CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
+ }
+
+ if (currentProxy->keyURL != NULL) {
+ CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
+ }
+ }
+
+ return 0;
+}
+
+
+static Boolean
+__proxy_enabled(CFDictionaryRef configuration, const CFStringRef *enableKey)
+{
+ CFNumberRef num;
+ int val;
+
+ if (enableKey == NULL) {
+ return TRUE; // if proxy does not need to be enabled
+ }
+
+ num = CFDictionaryGetValue(configuration, *enableKey);
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &val) ||
+ (val == 0)) {
+ return FALSE; // if not enabled
+ }
+
+ return TRUE;
+}
+
+
+static int
+__doProxyHost(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (currentProxy == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+ return -1;
+ }
+
+ if (currentProxy->keyProxy == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy host cannot be specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy host not specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef host;
+
+ host = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), host);
+ CFRelease(host);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
+ }
+
+ return 1;
+}
+
+
+static int
+__doProxyPort(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (currentProxy == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+ return -1;
+ }
+
+ if (currentProxy->keyPort == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy port cannot be specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy port not specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFNumberRef num;
+ int port;
+
+ num = _copy_number(argv[0]);
+ if (!isA_CFNumber(num) ||
+ !CFNumberGetValue(num, kCFNumberIntType, &port) ||
+ (port < 0) || (port > 65535)) {
+ SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ CFDictionarySetValue(newConfiguration, *(currentProxy->keyPort), num);
+ CFRelease(num);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
+ }
+
+ return 1;
+}
+
+
+static int
+__doProxyURL(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (currentProxy == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+ return -1;
+ }
+
+ if (currentProxy->keyURL == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy URL cannot be specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("%s proxy URL not specified\n"), currentProxy->proxy);
+ return -1;
+ }
+
+ if (strlen(argv[0]) > 0) {
+ CFStringRef url;
+
+ url = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ CFDictionarySetValue(newConfiguration, *(currentProxy->keyURL), url);
+ CFRelease(url);
+ } else {
+ CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
+ }
+
+ return 1;
+}
+
+
+static int
+__doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ if (currentProxy == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+ return -1;
+ }
+
+ if (currentProxy != &proxyKeys_FTP) {
+ SCPrint(TRUE, stdout, CFSTR("passive can only be enable for FTP proxy\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static Boolean
+set_protocol_proxies(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+ Boolean ok;
+
+ ok = _process_options(proxyOptions, N_PROXY_OPTIONS, argc, argv, newConfiguration);
+ return ok;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+set_protocol(int argc, char **argv)
+{
+ CFDictionaryRef configuration;
+ CFMutableDictionaryRef newConfiguration = NULL;
+ Boolean ok = FALSE;
+ CFStringRef protocolType;
+
+ if (net_protocol == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+ return;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return;
+ }
+
+ configuration = SCNetworkProtocolGetConfiguration(net_protocol);
+ if (configuration == NULL) {
+ newConfiguration = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ } else {
+ newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
+ CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
+ }
+
+ protocolType = SCNetworkProtocolGetProtocolType(net_protocol);
+ if (CFEqual(protocolType, kSCNetworkProtocolTypeAppleTalk)) {
+ ok = set_protocol_appletalk(argc, argv, newConfiguration);
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
+ ok = set_protocol_dns(argc, argv, newConfiguration);
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
+ ok = set_protocol_ipv4(argc, argv, newConfiguration);
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
+ ok = set_protocol_ipv6(argc, argv, newConfiguration);
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
+ ok = set_protocol_proxies(argc, argv, newConfiguration);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("this protocols configuration cannot be changed\n"));
+ }
+
+ if (!ok) {
+ goto done;
+ }
+
+ if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
+ ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
+ if (!SCNetworkProtocolSetConfiguration(net_protocol, newConfiguration)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ net_changed = TRUE;
+ }
+
+ done :
+
+ if (newConfiguration != NULL) CFRelease(newConfiguration);
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_protocol(int argc, char **argv)
+{
+ CFDictionaryRef configuration;
+ SCNetworkProtocolRef protocol = NULL;
+ CFStringRef protocolType;
+
+ if (argc > 0) {
+ protocol = _find_protocol(argv[0]);
+ } else {
+ if (net_protocol != NULL) {
+ protocol = net_protocol;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+ return;
+ }
+ }
+
+ if (protocol == NULL) {
+ return;
+ }
+
+ protocolType = SCNetworkProtocolGetProtocolType(protocol);
+ SCPrint(TRUE, stdout, CFSTR("protocol type = %@\n"), protocolType);
+
+ configuration = SCNetworkProtocolGetConfiguration(protocol);
+ if (configuration != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("\n protocol configuration\n"));
+ _show_entity(configuration, CFSTR(""));
+ }
+
+ if (_sc_debug) {
+ SCPrint(TRUE, stdout, CFSTR("\n%@\n"), protocol);
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_protocols(int argc, char **argv)
+{
+ CFIndex i;
+ CFIndex n;
+
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return;
+ }
+
+ if (net_service == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+ return;
+ }
+
+ if (protocols != NULL) CFRelease(protocols);
+ protocols = SCNetworkServiceCopyProtocols(net_service);
+ if (protocols == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ n = CFArrayGetCount(protocols);
+ if (n > 1) {
+ CFMutableArrayRef sorted;
+
+ sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, n),
+ _compare_protocols,
+ NULL);
+ CFRelease(protocols);
+ protocols = sorted;
+ }
+
+ for (i = 0; i < n; i++) {
+ SCNetworkProtocolRef protocol;
+ CFStringRef protocolType;
+
+ protocol = CFArrayGetValueAtIndex(protocols, i);
+ protocolType = SCNetworkProtocolGetProtocolType(protocol);
+
+ SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%*s :"),
+ ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) ? '>' : ' ',
+ i + 1,
+ protocolType,
+ sizeof("AppleTalk") - CFStringGetLength(protocolType) - 1,
+ "");
+
+ if (SCNetworkProtocolGetEnabled(protocol)) {
+ CFStringRef description;
+
+ description = _protocol_description(protocol, FALSE);
+ SCPrint(TRUE, stdout, CFSTR(" %@"), description);
+ CFRelease(description);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR(" *DISABLED*"));
+ }
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+ }
+
+ return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFStringRef
+_protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty)
+{
+ CFDictionaryRef configuration;
+ CFMutableStringRef description = NULL;
+ CFStringRef protocolType;
+
+ description = CFStringCreateMutable(NULL, 0);
+
+ if (!SCNetworkProtocolGetEnabled(protocol)) {
+ goto done;
+ }
+
+ configuration = SCNetworkProtocolGetConfiguration(protocol);
+ if (configuration == NULL) {
+ goto done;
+ }
+
+ protocolType = SCNetworkProtocolGetProtocolType(protocol);
+ if (CFEqual(protocolType, kSCNetworkProtocolTypeAppleTalk)) {
+ CFStringRef method;
+
+ method = CFDictionaryGetValue(configuration, kSCPropNetAppleTalkConfigMethod);
+ if (isA_CFString(method)) {
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%@"),
+ method);
+ }
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
+ CFStringRef domain;
+ CFArrayRef search;
+ CFArrayRef servers;
+
+ domain = CFDictionaryGetValue(configuration, kSCPropNetDNSDomainName);
+ if (isA_CFString(domain)) {
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("domain=%@"),
+ domain);
+ }
+
+ search = CFDictionaryGetValue(configuration, kSCPropNetDNSSearchDomains);
+ if (isA_CFArray(search)) {
+ CFStringRef str;
+
+ str = CFStringCreateByCombiningStrings(NULL, search, CFSTR(","));
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%ssearch=%@"),
+ CFStringGetLength(description) > 0 ? ", " : "",
+ str);
+ CFRelease(str);
+ }
+
+ servers = CFDictionaryGetValue(configuration, kSCPropNetDNSServerAddresses);
+ if (isA_CFArray(servers)) {
+ CFStringRef str;
+
+ str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%sservers=%@"),
+ CFStringGetLength(description) > 0 ? ", " : "",
+ str);
+ CFRelease(str);
+ }
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
+ CFStringRef method;
+
+ method = CFDictionaryGetValue(configuration, kSCPropNetIPv4ConfigMethod);
+ if (isA_CFString(method)) {
+ CFArrayRef addresses;
+
+ addresses = CFDictionaryGetValue(configuration, kSCPropNetIPv4Addresses);
+ if (CFEqual(method, kSCValNetIPv4ConfigMethodINFORM) &&
+ isA_CFArray(addresses)) {
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%@, address=%@"),
+ method,
+ CFArrayGetValueAtIndex(addresses, 0));
+ } else if (CFEqual(method, kSCValNetIPv4ConfigMethodManual) &&
+ isA_CFArray(addresses)) {
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%@, address=%@"),
+ method,
+ CFArrayGetValueAtIndex(addresses, 0));
+ } else {
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%@"),
+ method);
+ }
+ }
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
+ CFStringRef method;
+
+ method = CFDictionaryGetValue(configuration, kSCPropNetIPv6ConfigMethod);
+ if (isA_CFString(method)) {
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%@"),
+ method);
+ }
+ } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
+ CFIndex i;
+ static proxyKeys *keys[] = { &proxyKeys_FTP, &proxyKeys_Gopher, &proxyKeys_HTTP, &proxyKeys_HTTPS,
+ &proxyKeys_RTSP, &proxyKeys_SOCKS, &proxyKeys_PAC, &proxyKeys_WPAD };
+
+ for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
+ proxyKeys *currentProxy = keys[i];
+
+ if (!__proxy_enabled(configuration, currentProxy->keyEnable)) {
+ continue;
+ }
+
+ if (((currentProxy->keyProxy != NULL) &&
+ !CFDictionaryContainsKey(configuration, *(currentProxy->keyProxy))) ||
+ ((currentProxy->keyURL != NULL) &&
+ !CFDictionaryContainsKey(configuration, *(currentProxy->keyURL)))) {
+ continue;
+ }
+
+ CFStringAppendFormat(description,
+ NULL,
+ CFSTR("%s%s"),
+ CFStringGetLength(description) > 0 ? ", " : "",
+ currentProxy->proxy);
+ }
+ }
+
+ done :
+
+ if (skipEmpty && CFStringGetLength(description) == 0) {
+ CFRelease(description);
+ description = NULL;
+ }
+
+ return description;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_PROTOCOL_H
+#define _NET_PROTOCOL_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+CFComparisonResult _compare_protocols (const void *val1, const void *val2, void *context);
+CFStringRef _protocol_description (SCNetworkProtocolRef protocol, Boolean skipEmpty);
+
+void create_protocol (int argc, char **argv);
+void disable_protocol (int argc, char **argv);
+void enable_protocol (int argc, char **argv);
+void remove_protocol (int argc, char **argv);
+void select_protocol (int argc, char **argv);
+void set_protocol (int argc, char **argv);
+void show_protocol (int argc, char **argv);
+void show_protocols (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_PROTOCOL_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+#include "net_service.h"
+#include "net_interface.h"
+#include "net_protocol.h"
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFComparisonResult
+_compare_services(const void *val1, const void *val2, void *context)
+{
+ CFStringRef id1;
+ CFStringRef id2;
+ CFArrayRef order = (CFArrayRef)context;
+ SCNetworkServiceRef s1 = (SCNetworkServiceRef)val1;
+ SCNetworkServiceRef s2 = (SCNetworkServiceRef)val2;
+
+ id1 = SCNetworkServiceGetServiceID(s1);
+ id2 = SCNetworkServiceGetServiceID(s2);
+
+ if (order != NULL) {
+ CFIndex o1;
+ CFIndex o2;
+ CFRange range;
+
+ range = CFRangeMake(0, CFArrayGetCount(order));
+ o1 = CFArrayGetFirstIndexOfValue(order, range, id1);
+ o2 = CFArrayGetFirstIndexOfValue(order, range, id2);
+
+ if (o1 > o2) {
+ return (o2 != kCFNotFound) ? kCFCompareGreaterThan : kCFCompareLessThan;
+ } else if (o1 < o2) {
+ return (o1 != kCFNotFound) ? kCFCompareLessThan : kCFCompareGreaterThan;
+ }
+ }
+
+ return CFStringCompare(id1, id2, 0);
+}
+
+
+static SCNetworkServiceRef
+_find_service(char *match)
+{
+ Boolean allowIndex = TRUE;
+ CFIndex i;
+ CFIndex n;
+ CFStringRef select_name = NULL;
+ SCNetworkServiceRef selected = NULL;
+
+ if (services == NULL) {
+ if (net_set == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+ return NULL;
+ }
+
+ services = SCNetworkSetCopyServices(net_set);
+ if (services == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return NULL;
+ }
+
+ allowIndex = FALSE;
+ }
+
+ // try to select the service by its serviceID
+
+ select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+ n = CFArrayGetCount(services);
+ for (i = 0; i < n; i++) {
+ SCNetworkServiceRef service;
+ CFStringRef serviceID;
+
+ service = CFArrayGetValueAtIndex(services, i);
+ serviceID = SCNetworkServiceGetServiceID(service);
+ if (CFEqual(select_name, serviceID)) {
+ selected = service;
+ goto done;
+ }
+ }
+
+ // try to select the service by its name
+
+ for (i = 0; i < n; i++) {
+ SCNetworkServiceRef service;
+ CFStringRef serviceName;
+
+ service = CFArrayGetValueAtIndex(services, i);
+ serviceName = SCNetworkServiceGetName(service);
+ if ((serviceName != NULL) && CFEqual(select_name, serviceName)) {
+ if (selected == NULL) {
+ selected = service;
+ } else {
+ // if multiple services match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the service by its name (case insensitive)
+
+ for (i = 0; i < n; i++) {
+ SCNetworkServiceRef service;
+ CFStringRef serviceName;
+
+ service = CFArrayGetValueAtIndex(services, i);
+ serviceName = SCNetworkServiceGetName(service);
+ if ((serviceName != NULL) &&
+ CFStringCompare(select_name,
+ serviceName,
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ if (selected == NULL) {
+ selected = service;
+ } else {
+ // if multiple services match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the service by its [BSD] interface name
+
+ for (i = 0; i < n; i++) {
+ SCNetworkInterfaceRef interface;
+ CFStringRef interfaceName = NULL;
+ SCNetworkServiceRef service;
+
+ service = CFArrayGetValueAtIndex(services, i);
+
+ interface = SCNetworkServiceGetInterface(service);
+ while ((interface != NULL) && (interfaceName == NULL)) {
+ interfaceName = SCNetworkInterfaceGetBSDName(interface);
+ if (interfaceName == NULL) {
+ interface = SCNetworkInterfaceGetInterface(interface);
+ }
+ }
+
+ if (interfaceName == NULL) {
+ continue;
+ }
+
+ if (CFStringCompare(select_name,
+ interfaceName,
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ if (selected == NULL) {
+ selected = service;
+ } else {
+ // if multiple services match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the service by its index
+
+ if (allowIndex) {
+ char *end;
+ char *str = match;
+ long val;
+
+ errno = 0;
+ val = strtol(str, &end, 10);
+ if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+ if ((val > 0) && (val <= n)) {
+ selected = CFArrayGetValueAtIndex(services, val - 1);
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("no match, which service?\n"));
+
+ done :
+
+ if (select_name != NULL) CFRelease(select_name);
+ return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_service(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+ CFStringRef interfaceName;
+ Boolean ok;
+ CFArrayRef order;
+ CFMutableArrayRef newOrder;
+ SCNetworkServiceRef service = NULL;
+ CFStringRef serviceName;
+ CFStringRef setName;
+ CFArrayRef supported;
+
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return;
+ }
+
+ if (net_set == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+ return;
+ }
+
+ if (argc < 1) {
+ if (net_interface == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
+ return;
+ }
+
+ interface = net_interface;
+ } else {
+ interface = _find_interface(argv[0]);
+ argv++;
+ argc--;
+ }
+
+ if (interface == NULL) {
+ return;
+ }
+
+ supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
+ if (supported == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("no network protocols are supported over this interface\n"));
+ return;
+ }
+
+ service = SCNetworkServiceCreate(prefs, interface);
+ if (service == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ if ((argc > 0) && (strlen(argv[0]) > 0)) {
+ Boolean ok;
+
+ serviceName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ argv++;
+ argc--;
+
+ ok = SCNetworkServiceSetName(service, serviceName);
+ CFRelease(serviceName);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("service not created: %s\n"), SCErrorString(SCError()));
+ CFRelease(service);
+ return;
+ }
+ }
+
+ ok = SCNetworkSetAddService(net_set, service);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ (void)SCNetworkServiceRemove(service);
+ goto done;
+ }
+
+ net_changed = TRUE;
+
+ order = SCNetworkSetGetServiceOrder(net_set);
+ if (order == NULL) {
+ newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ } else {
+ newOrder = CFArrayCreateMutableCopy(NULL, 0, order);
+ }
+ CFArrayAppendValue(newOrder, SCNetworkServiceGetServiceID(service));
+ ok = SCNetworkSetSetServiceOrder(net_set, newOrder);
+ CFRelease(newOrder);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ (void)SCNetworkServiceRemove(service);
+ goto done;
+ }
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetBSDName(interface);
+ }
+ if (interfaceName != NULL) {
+ if (!SCNetworkServiceSetName(service, interfaceName)) {
+ CFIndex i;
+
+ for (i = 2; i < 100; i++) {
+ serviceName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ %d"), interfaceName, i);
+ ok = SCNetworkServiceSetName(service, serviceName);
+ CFRelease(serviceName);
+ if (ok) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (net_service != NULL) CFRelease(net_service);
+ net_service = CFRetain(service);
+
+ serviceName = SCNetworkServiceGetName(service);
+ if (serviceName != NULL) {
+ SCPrint(TRUE, stdout,
+ CFSTR("service \"%@\" (%@) created and selected\n"),
+ serviceName,
+ SCNetworkServiceGetServiceID(service));
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("service ID \"%@\" created and selected\n"),
+ SCNetworkServiceGetServiceID(service));
+ }
+
+ setName = SCNetworkSetGetName(net_set);
+ if (setName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("& added to set \"%@\"\n"), setName);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("& added to set ID \"%@\"\n"),
+ SCNetworkSetGetSetID(net_set));
+ }
+
+ if (net_interface != NULL) CFRelease(net_interface);
+ net_interface = CFRetain(interface);
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetBSDName(interface);
+ }
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+ }
+
+ SCPrint(TRUE, stdout,
+ CFSTR("& interface \"%@\" selected\n"),
+ interfaceName);
+
+ if (protocols != NULL) {
+ CFRelease(protocols);
+ protocols = NULL;
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ if (services != NULL) {
+ CFRelease(services);
+ services = NULL;
+ }
+
+ done :
+
+ if (service != NULL) CFRelease(service);
+ return;
+}
+
+
+__private_extern__
+void
+disable_service(int argc, char **argv)
+{
+ SCNetworkServiceRef service;
+
+ if (argc == 1) {
+ service = _find_service(argv[0]);
+ } else {
+ if (net_service != NULL) {
+ service = net_service;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+ return;
+ }
+ }
+
+ if (service == NULL) {
+ return;
+ }
+
+ if (!SCNetworkServiceSetEnabled(service, FALSE)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+
+ return;
+}
+
+
+__private_extern__
+void
+enable_service(int argc, char **argv)
+{
+ SCNetworkServiceRef service;
+
+ if (argc == 1) {
+ service = _find_service(argv[0]);
+ } else {
+ if (net_service != NULL) {
+ service = net_service;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+ return;
+ }
+ }
+
+ if (service == NULL) {
+ return;
+ }
+
+ if (!SCNetworkServiceSetEnabled(service, TRUE)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+
+ return;
+}
+
+
+__private_extern__
+void
+remove_service(int argc, char **argv)
+{
+ SCNetworkServiceRef service = NULL;
+ CFStringRef serviceName;
+
+ if (argc == 1) {
+ service = _find_service(argv[0]);
+ } else {
+ if (net_service != NULL) {
+ service = net_service;
+ }
+ }
+
+ if (service == NULL) {
+ return;
+ }
+
+ CFRetain(service);
+
+ if (!SCNetworkServiceRemove(service)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ net_changed = TRUE;
+
+ serviceName = SCNetworkServiceGetName(service);
+ if (serviceName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("service \"%@\" removed\n"), serviceName);
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("service ID \"%@\" removed\n"),
+ SCNetworkServiceGetServiceID(service));
+ }
+
+ if ((net_service != NULL) && CFEqual(service, net_service)) {
+ CFRelease(net_service);
+ net_service = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+
+ if (protocols != NULL) {
+ CFRelease(protocols);
+ protocols = NULL;
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ if (net_interface != NULL) {
+ CFRelease(net_interface);
+ net_interface = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+ }
+ }
+
+ if (services != NULL) {
+ CFRelease(services);
+ services = NULL;
+ }
+
+ done :
+
+ CFRelease(service);
+ return;
+}
+
+
+__private_extern__
+void
+select_service(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+ SCNetworkServiceRef service;
+ CFStringRef serviceName;
+
+ service = _find_service(argv[0]);
+
+ if (service == NULL) {
+ return;
+ }
+
+ if (net_service != NULL) CFRelease(net_service);
+ net_service = CFRetain(service);
+
+ serviceName = SCNetworkServiceGetName(service);
+ if (serviceName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("service \"%@\" selected\n"), serviceName);
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("service ID \"%@\" selected\n"),
+ SCNetworkServiceGetServiceID(service));
+ }
+
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface != NULL) {
+ CFStringRef interfaceName;
+
+ if (net_interface != NULL) CFRelease(net_interface);
+ net_interface = CFRetain(interface);
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetBSDName(interface);
+ }
+ if (interfaceName == NULL) {
+ interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+ }
+
+ SCPrint(TRUE, stdout,
+ CFSTR("& interface \"%@\" selected\n"),
+ interfaceName);
+ } else {
+ if (net_interface != NULL) {
+ CFRelease(net_interface);
+ net_interface = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+ }
+ }
+
+ if (protocols != NULL) {
+ CFRelease(protocols);
+ protocols = NULL;
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+set_service(int argc, char **argv)
+{
+ Boolean ok;
+
+ if (net_service == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+ return;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return;
+ }
+
+ while (argc > 0) {
+ char *command;
+
+ command = argv[0];
+ argv++;
+ argc--;
+
+ if (strcmp(command, "name") == 0) {
+ CFStringRef serviceName;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("name not specified\n"));
+ return;
+ }
+
+ serviceName = (strlen(argv[0]) > 0)
+ ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8)
+ : NULL;
+ argv++;
+ argc--;
+
+ ok = SCNetworkServiceSetName(net_service, serviceName);
+ if (serviceName != NULL) CFRelease(serviceName);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+ } else if (strcmp(command, "order") == 0) {
+
+ char *end;
+ long newIndex;
+ CFIndex nServices;
+ char *str;
+ CFArrayRef services;
+
+ services = SCNetworkSetCopyServices(net_set);
+ nServices = CFArrayGetCount(services);
+ CFRelease(services);
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("order not specified\n"));
+ return;
+ }
+
+ if (net_set == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+ return;
+ }
+
+ str = argv[0];
+ argv++;
+ argc--;
+
+ errno = 0;
+ newIndex = strtol(str, &end, 10);
+ if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+ if ((newIndex > 0) && (newIndex <= nServices)) {
+ CFIndex curIndex;
+ CFMutableArrayRef newOrder;
+ CFArrayRef order;
+ CFStringRef serviceID = SCNetworkServiceGetServiceID(net_service);
+
+ order = SCNetworkSetGetServiceOrder(net_set);
+ if (order == NULL) {
+ newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ } else {
+ newOrder = CFArrayCreateMutableCopy(NULL, 0, order);
+ }
+
+ curIndex = CFArrayGetFirstIndexOfValue(newOrder,
+ CFRangeMake(0, CFArrayGetCount(newOrder)),
+ serviceID);
+ if (curIndex != kCFNotFound) {
+ CFArrayRemoveValueAtIndex(newOrder, curIndex);
+ }
+
+ if (newIndex <= CFArrayGetCount(newOrder)) {
+ CFArrayInsertValueAtIndex(newOrder, newIndex - 1, serviceID);
+ } else {
+ CFArrayAppendValue(newOrder, serviceID);
+ }
+
+ ok = SCNetworkSetSetServiceOrder(net_set, newOrder);
+ CFRelease(newOrder);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("set order to what?\n"));
+ return;
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return;
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ }
+ }
+
+ return;
+}
+
+
+static void
+__show_service_interface(SCNetworkServiceRef service, const char *prefix)
+{
+ CFStringRef description;
+ SCNetworkInterfaceRef interface;
+
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface == NULL) {
+ return;
+ }
+
+ description = _interface_description(interface);
+ SCPrint(TRUE, stdout, CFSTR("%s%@\n"), prefix, description);
+ CFRelease(description);
+
+ return;
+}
+
+static void
+__show_service_protocols(SCNetworkServiceRef service, const char *prefix, Boolean skipEmpty)
+{
+ CFIndex i;
+ CFIndex n;
+ CFArrayRef protocols;
+
+ protocols = SCNetworkServiceCopyProtocols(service);
+ if (protocols == NULL) {
+ return;
+ }
+
+ n = CFArrayGetCount(protocols);
+ if (n > 1) {
+ CFMutableArrayRef sorted;
+
+ sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, n),
+ _compare_protocols,
+ NULL);
+ CFRelease(protocols);
+ protocols = sorted;
+ }
+
+ for (i = 0; i < n; i++) {
+ CFStringRef description;
+ SCNetworkProtocolRef protocol;
+
+ protocol = CFArrayGetValueAtIndex(protocols, i);
+ description = _protocol_description(protocol, skipEmpty);
+ if (description != NULL) {
+ CFStringRef protocolType;
+
+ protocolType = SCNetworkProtocolGetProtocolType(protocol);
+ SCPrint(TRUE, stdout,
+ CFSTR("%s%@%*s : %@\n"),
+ prefix,
+ protocolType,
+ sizeof("Interface") - CFStringGetLength(protocolType) - 1,
+ "",
+ description);
+ CFRelease(description);
+ }
+ }
+
+ CFRelease(protocols);
+ return;
+}
+
+
+__private_extern__
+void
+show_service(int argc, char **argv)
+{
+ SCNetworkInterfaceRef interface;
+ CFArrayRef protocols;
+ SCNetworkServiceRef service;
+ CFStringRef serviceName;
+
+ if (argc == 1) {
+ service = _find_service(argv[0]);
+ } else {
+ if (net_service != NULL) {
+ service = net_service;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+ return;
+ }
+ }
+
+ if (service == NULL) {
+ return;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("service id = %@\n"), SCNetworkServiceGetServiceID(service));
+
+ serviceName = SCNetworkServiceGetName(service);
+ SCPrint(TRUE, stdout, CFSTR("name = %@\n"),
+ (serviceName != NULL) ? serviceName : CFSTR(""));
+
+ interface = SCNetworkServiceGetInterface(service);
+ if (interface != NULL) {
+ CFStringRef interfaceName;
+
+ interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+ if (interfaceName != NULL) {
+ CFRetain(interfaceName);
+ } else {
+ interfaceName = _interface_description(interface);
+ }
+ if (interfaceName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("interface = %@\n"), interfaceName);
+ CFRelease(interfaceName);
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("\n No interface!\n\n"));
+ }
+
+ protocols = SCNetworkServiceCopyProtocols(service);
+ if (protocols != NULL) {
+ CFIndex n;
+
+ n = CFArrayGetCount(protocols);
+ if (n > 1) {
+ CFMutableArrayRef sorted;
+
+ sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, n),
+ _compare_protocols,
+ NULL);
+ CFRelease(protocols);
+ protocols = sorted;
+ }
+
+ if (n > 0) {
+ CFIndex i;
+
+ SCPrint(TRUE, stdout, CFSTR("configured protocols = "));
+ for (i = 0; i < n; i++) {
+ SCNetworkProtocolRef protocol;
+
+ protocol = CFArrayGetValueAtIndex(protocols, i);
+ SCPrint(TRUE, stdout, CFSTR("%s%@"),
+ (i == 0) ? "" : ", ",
+ SCNetworkProtocolGetProtocolType(protocol));
+ }
+ SCPrint(TRUE, stdout, CFSTR("\n"));
+
+ __show_service_protocols(service, " ", FALSE);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("no configured protocols\n"));
+ }
+
+ CFRelease(protocols);
+ }
+
+ if (_sc_debug) {
+ SCPrint(TRUE, stdout, CFSTR("\n%@\n"), service);
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+show_services(int argc, char **argv)
+{
+ CFIndex i;
+ CFIndex n;
+
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return;
+ }
+
+ if (argc == 1) {
+ if (services != NULL) CFRelease(services);
+ services = SCNetworkServiceCopyAll(prefs);
+ } else {
+ if (net_set == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+ return;
+ }
+
+ if (services != NULL) CFRelease(services);
+ services = SCNetworkSetCopyServices(net_set);
+ n = (services != NULL) ? CFArrayGetCount(services) : 0;
+ if (n > 1) {
+ CFArrayRef order;
+ CFMutableArrayRef sorted;
+
+ order = SCNetworkSetGetServiceOrder(net_set);
+ sorted = CFArrayCreateMutableCopy(NULL, 0, services);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, CFArrayGetCount(sorted)),
+ _compare_services,
+ (void *)order);
+ CFRelease(services);
+ services = sorted;
+ }
+ }
+
+ if (services == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ n = CFArrayGetCount(services);
+ for (i = 0; i < n; i++) {
+ SCNetworkServiceRef service;
+ CFStringRef serviceName;
+ CFStringRef serviceID;
+
+ service = CFArrayGetValueAtIndex(services, i);
+ serviceID = SCNetworkServiceGetServiceID(service);
+ serviceName = SCNetworkServiceGetName(service);
+ if (serviceName == NULL) serviceName = CFSTR("");
+
+ SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%-*s (%@)%s\n"),
+ ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
+ i + 1,
+ serviceName,
+ 30 - CFStringGetLength(serviceName),
+ " ",
+ serviceID,
+ SCNetworkServiceGetEnabled(service) ? "" : " *DISABLED*");
+
+ __show_service_interface(service, " Interface : ");
+ __show_service_protocols(service, " ", TRUE);
+ }
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_SERVICE_H
+#define _NET_SERVICE_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+CFComparisonResult _compare_services (const void *val1, const void *val2, void *context);
+
+void create_service (int argc, char **argv);
+void disable_service (int argc, char **argv);
+void enable_service (int argc, char **argv);
+void remove_service (int argc, char **argv);
+void select_service (int argc, char **argv);
+void set_service (int argc, char **argv);
+void show_service (int argc, char **argv);
+void show_services (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_SERVICE_H */
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * August 5, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+#include "net_set.h"
+#include "net_service.h"
+
+
+/* -------------------- */
+
+
+static CFComparisonResult
+_compare_sets(const void *val1, const void *val2, void *context)
+{
+ CFStringRef id1;
+ CFStringRef id2;
+ CFStringRef name1;
+ CFStringRef name2;
+ SCNetworkSetRef s1 = (SCNetworkSetRef)val1;
+ SCNetworkSetRef s2 = (SCNetworkSetRef)val2;
+
+ name1 = SCNetworkSetGetName(s1);
+ name2 = SCNetworkSetGetName(s2);
+
+ if (name1 != NULL) {
+ if (name2 != NULL) {
+ return CFStringCompare(name1, name2, 0);
+ } else {
+ return kCFCompareLessThan;
+ }
+ }
+
+ if (name2 != NULL) {
+ return kCFCompareGreaterThan;
+ }
+
+ id1 = SCNetworkSetGetSetID(s1);
+ id2 = SCNetworkSetGetSetID(s2);
+ return CFStringCompare(id1, id2, 0);
+}
+
+
+static CFArrayRef
+_copy_sets()
+{
+ CFArrayRef sets;
+ CFMutableArrayRef sorted;
+
+ sets = SCNetworkSetCopyAll(prefs);
+ if (sets == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return NULL;
+ }
+
+ sorted = CFArrayCreateMutableCopy(NULL, 0, sets);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, CFArrayGetCount(sorted)),
+ _compare_sets,
+ NULL);
+
+ CFRelease(sets);
+ sets = CFArrayCreateCopy(NULL, sorted);
+ CFRelease(sorted);
+ return sets;
+}
+
+
+static SCNetworkSetRef
+_find_set(char *match)
+{
+ Boolean allowIndex = TRUE;
+ CFIndex i;
+ CFIndex n;
+ CFStringRef select_name = NULL;
+ SCNetworkSetRef selected = NULL;
+
+ if (sets == NULL) {
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return NULL;
+ }
+
+ sets = _copy_sets();
+ if (sets == NULL) {
+ return NULL;
+ }
+
+ allowIndex = FALSE;
+ }
+
+ // try to select the set by its setID
+
+ select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+ n = CFArrayGetCount(sets);
+ for (i = 0; i < n; i++) {
+ SCNetworkSetRef set;
+ CFStringRef setID;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ setID = SCNetworkSetGetSetID(set);
+ if (CFEqual(select_name, setID)) {
+ selected = set;
+ goto done;
+
+ }
+ }
+
+ // try to select the set by its name
+
+ for (i = 0; i < n; i++) {
+ SCNetworkSetRef set;
+ CFStringRef setName;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ setName = SCNetworkSetGetName(set);
+ if ((setName != NULL) &&
+ CFEqual(select_name, setName)) {
+ if (selected == NULL) {
+ selected = set;
+ } else {
+ // if multiple sets match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple sets match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the set by its name (case insensitive)
+
+ for (i = 0; i < n; i++) {
+ SCNetworkSetRef set;
+ CFStringRef setName;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ setName = SCNetworkSetGetName(set);
+ if ((setName != NULL) &&
+ CFStringCompare(select_name,
+ setName,
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ if (selected == NULL) {
+ selected = set;
+ } else {
+ // if multiple sets match
+ selected = NULL;
+ SCPrint(TRUE, stdout, CFSTR("multiple sets match\n"));
+ goto done;
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ // try to select the set by its index
+
+ if (allowIndex) {
+ char *end;
+ char *str = match;
+ long val;
+
+ errno = 0;
+ val = strtol(str, &end, 10);
+ if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+ if ((val > 0) && (val <= n)) {
+ selected = CFArrayGetValueAtIndex(sets, val - 1);
+ }
+ }
+ }
+
+ if (selected != NULL) {
+ goto done;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("no match, which set?\n"));
+
+ done :
+
+ if (select_name != NULL) CFRelease(select_name);
+ return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_set(int argc, char **argv)
+{
+ SCNetworkSetRef set;
+ CFStringRef setName;
+
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return;
+ }
+
+ set = SCNetworkSetCreate(prefs);
+ if (set == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ if ((argc > 0) && (strlen(argv[0]) > 0)) {
+ Boolean ok;
+
+ setName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+ argv++;
+ argc--;
+
+ ok = SCNetworkSetSetName(set, setName);
+ CFRelease(setName);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("set not created: %s\n"), SCErrorString(SCError()));
+ (void) SCNetworkSetRemove(set);
+ CFRelease(set);
+ return;
+ }
+ }
+
+ net_changed = TRUE;
+
+ if (net_set != NULL) CFRelease(net_set);
+ net_set = set;
+
+ setName = SCNetworkSetGetName(set);
+ if (setName != NULL) {
+ SCPrint(TRUE, stdout,
+ CFSTR("set \"%@\" (%@) created and selected\n"),
+ setName,
+ SCNetworkSetGetSetID(set));
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("set ID \"%@\" created and selected\n"),
+ SCNetworkSetGetSetID(set));
+ }
+
+ if (net_service != NULL) {
+ CFRelease(net_service);
+ net_service = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ if (net_interface != NULL) {
+ CFRelease(net_interface);
+ net_interface = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+ }
+
+ if (sets != NULL) {
+ CFRelease(sets);
+ sets = NULL;
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+remove_set(int argc, char **argv)
+{
+ SCNetworkSetRef set = NULL;
+ CFStringRef setName;
+
+ if (argc == 1) {
+ set = _find_set(argv[0]);
+ } else {
+ if (net_set != NULL) {
+ set = net_set;
+ }
+ }
+
+ if (set == NULL) {
+ return;
+ }
+
+ CFRetain(set);
+
+ if (!SCNetworkSetRemove(set)) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ goto done;
+ }
+
+ net_changed = TRUE;
+
+ setName = SCNetworkSetGetName(set);
+ if (setName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set \"%@\" removed\n"), setName);
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("set ID \"%@\" removed\n"),
+ SCNetworkSetGetSetID(set));
+ }
+
+ if (CFEqual(set, net_set)) {
+ if (net_service != NULL) {
+ CFRelease(net_service);
+ net_service = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ if (net_interface != NULL) {
+ CFRelease(net_interface);
+ net_interface = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+ }
+ }
+
+ if (sets != NULL) {
+ CFRelease(sets);
+ sets = NULL;
+ }
+
+ done :
+
+ CFRelease(set);
+ return;
+}
+
+
+__private_extern__
+void
+select_set(int argc, char **argv)
+{
+ SCNetworkSetRef set;
+ CFStringRef setName;
+
+ set = _find_set(argv[0]);
+
+ if (set == NULL) {
+ return;
+ }
+
+ if (net_set != NULL) CFRelease(net_set);
+ net_set = CFRetain(set);
+
+ setName = SCNetworkSetGetName(set);
+ if (setName != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName);
+ } else {
+ SCPrint(TRUE, stdout,
+ CFSTR("set ID \"%@\" selected\n"),
+ SCNetworkSetGetSetID(set));
+ }
+
+ if (net_service != NULL) {
+ CFRelease(net_service);
+ net_service = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+ }
+
+ if (net_protocol != NULL) {
+ CFRelease(net_protocol);
+ net_protocol = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+ }
+
+ if (net_interface != NULL) {
+ CFRelease(net_interface);
+ net_interface = NULL;
+ SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+set_set(int argc, char **argv)
+{
+ Boolean ok;
+
+ if (net_set == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+ return;
+ }
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ return;
+ }
+
+ while (argc > 0) {
+ char *command;
+
+ command = argv[0];
+ argv++;
+ argc--;
+
+ if (strcmp(command, "name") == 0) {
+ CFStringRef setName;
+
+ if (argc < 1) {
+ SCPrint(TRUE, stdout, CFSTR("name not specified\n"));
+ return;
+ }
+
+ setName = (strlen(argv[0]) > 0)
+ ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8)
+ : NULL;
+ argv++;
+ argc--;
+
+ ok = SCNetworkSetSetName(net_set, setName);
+ if (setName != NULL) CFRelease(setName);
+ if (!ok) {
+ SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ net_changed = TRUE;
+
+ if (sets != NULL) {
+ /*
+ * since the (displayed) ordering may have changed, refresh sets
+ */
+ char *setID;
+
+ setID = _SC_cfstring_to_cstring(SCNetworkSetGetSetID(net_set),
+ NULL,
+ 0,
+ kCFStringEncodingUTF8);
+
+ CFRelease(net_set);
+ net_set = NULL;
+
+ CFRelease(sets);
+ sets = NULL;
+
+ net_set = _find_set(setID);
+ if (net_set != NULL) {
+ CFRetain(net_set);
+ }
+
+ CFAllocatorDeallocate(NULL, setID);
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+ }
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+show_set(int argc, char **argv)
+{
+ CFArrayRef services;
+ SCNetworkSetRef set = NULL;
+ CFStringRef setName;
+
+ if (argc == 1) {
+ set = _find_set(argv[0]);
+ } else {
+ if (net_set != NULL) {
+ set = net_set;
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+ return;
+ }
+ }
+
+ if (set == NULL) {
+ return;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("set id = %@\n"), SCNetworkSetGetSetID(set));
+
+ setName = SCNetworkSetGetName(set);
+ SCPrint(TRUE, stdout, CFSTR("name = %@\n"),
+ (setName != NULL) ? setName : CFSTR(""));
+
+ services = SCNetworkSetCopyServices(set);
+ if (services != NULL) {
+ CFIndex i;
+ CFIndex n;
+ CFIndex nOrder = 0;
+ CFArrayRef order;
+ CFMutableArrayRef sorted = (CFMutableArrayRef)services;
+
+ order = SCNetworkSetGetServiceOrder(set);
+ if (order != NULL) {
+ nOrder = CFArrayGetCount(order);
+ }
+
+ n = CFArrayGetCount(services);
+ if (n > 1) {
+ sorted = CFArrayCreateMutableCopy(NULL, 0, services);
+ CFArraySortValues(sorted,
+ CFRangeMake(0, CFArrayGetCount(sorted)),
+ _compare_services,
+ (void *)order);
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("services =\n"));
+
+ for (i = 0; i < n; i++) {
+ CFIndex orderIndex = kCFNotFound;
+ SCNetworkServiceRef service;
+ CFStringRef serviceName;
+ CFStringRef serviceID;
+
+ service = CFArrayGetValueAtIndex(sorted, i);
+ serviceID = SCNetworkServiceGetServiceID(service);
+ serviceName = SCNetworkServiceGetName(service);
+ if (serviceName == NULL) serviceName = CFSTR("");
+
+ if (order != NULL) {
+ orderIndex = CFArrayGetFirstIndexOfValue(order,
+ CFRangeMake(0, nOrder),
+ serviceID);
+ }
+ if (orderIndex != kCFNotFound) {
+ SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%-*s (%@)\n"),
+ ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
+ orderIndex + 1,
+ serviceName,
+ 30 - CFStringGetLength(serviceName),
+ " ",
+ serviceID);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("%c : %@%-*s (%@)\n"),
+ ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
+ serviceName,
+ 30 - CFStringGetLength(serviceName),
+ " ",
+ serviceID);
+ }
+ }
+
+ CFRelease(services);
+
+ if (sorted != services) CFRelease(sorted);
+ }
+
+ if (_sc_debug) {
+ SCPrint(TRUE, stdout, CFSTR("\n%@\n"), set);
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+show_sets(int argc, char **argv)
+{
+ SCNetworkSetRef current;
+ CFIndex i;
+ CFIndex n;
+
+ if (prefs == NULL) {
+ SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+ return;
+ }
+
+ if (sets == NULL) {
+ sets = _copy_sets();
+ if (sets == NULL) {
+ return;
+ }
+ }
+
+ current = SCNetworkSetCopyCurrent(prefs);
+
+ n = CFArrayGetCount(sets);
+ for (i = 0; i < n; i++) {
+ SCNetworkSetRef set;
+ CFStringRef setID;
+ CFStringRef setName;
+
+ set = CFArrayGetValueAtIndex(sets, i);
+ setID = SCNetworkSetGetSetID(set);
+ setName = SCNetworkSetGetName(set);
+ if (setName == NULL) setName = CFSTR("");
+
+ SCPrint(TRUE, stdout, CFSTR(" %c%c%2d: %@%-*s (%@)\n"),
+ ((current != NULL) && CFEqual(set, current)) ? '*' : ' ',
+ ((net_set != NULL) && CFEqual(set, net_set)) ? '>' : ' ',
+ i + 1,
+ setName,
+ 30 - CFStringGetLength(setName),
+ " ",
+ setID);
+ }
+
+ if (current != NULL) CFRelease(current);
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * October 4, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_SET_H
+#define _NET_SET_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+void create_set (int argc, char **argv);
+void remove_set (int argc, char **argv);
+void select_set (int argc, char **argv);
+void set_set (int argc, char **argv);
+void show_set (int argc, char **argv);
+void show_sets (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_SET_H */
--- /dev/null
+/*
+ * Copyright (c) 2000-2003 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * June 1, 2001 Allan Nathanson <ajn@apple.com>
+ * - public API conversion
+ *
+ * November 9, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "scutil.h"
+#include "notifications.h"
+
+
+static int osig;
+static struct sigaction *oact = NULL;
+
+
+static CFComparisonResult
+sort_keys(const void *p1, const void *p2, void *context) {
+ CFStringRef key1 = (CFStringRef)p1;
+ CFStringRef key2 = (CFStringRef)p2;
+ return CFStringCompare(key1, key2, 0);
+}
+
+
+__private_extern__
+void
+storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+ int i;
+ CFIndex n;
+
+ SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
+
+ n = CFArrayGetCount(changedKeys);
+ if (n > 0) {
+ for (i = 0; i < n; i++) {
+ SCPrint(TRUE,
+ stdout,
+ CFSTR(" changed key [%d] = %@\n"),
+ i,
+ CFArrayGetValueAtIndex(changedKeys, i));
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR(" no changed key's.\n"));
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_list(int argc, char **argv)
+{
+ int i;
+ CFArrayRef list;
+ CFIndex listCnt;
+ Boolean isRegex = FALSE;
+ CFMutableArrayRef sortedList;
+
+ if (store == NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoStoreSession));
+ return;
+ }
+
+ if (argc == 1)
+ isRegex = TRUE;
+
+ list = isRegex ? watchedPatterns : watchedKeys;
+ if (!list) {
+ SCPrint(TRUE,
+ stdout,
+ CFSTR(" no notifier %s.\n"),
+ isRegex ? "patterns" : "keys");
+ return;
+ }
+
+ listCnt = CFArrayGetCount(list);
+ sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list);
+ CFArraySortValues(sortedList,
+ CFRangeMake(0, listCnt),
+ sort_keys,
+ NULL);
+
+ if (listCnt > 0) {
+ for (i = 0; i < listCnt; i++) {
+ SCPrint(TRUE,
+ stdout,
+ CFSTR(" notifier %s [%d] = %@\n"),
+ isRegex ? "pattern" : "key",
+ i,
+ CFArrayGetValueAtIndex(sortedList, i));
+ }
+ } else {
+ SCPrint(TRUE,
+ stdout,
+ CFSTR(" no notifier %s.\n"),
+ isRegex ? "patterns" : "keys");
+ }
+ CFRelease(sortedList);
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_add(int argc, char **argv)
+{
+ CFStringRef key;
+ CFMutableArrayRef keys;
+ Boolean isRegex = FALSE;
+
+ if (store == NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoStoreSession));
+ return;
+ }
+
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+ if (argc == 2)
+ isRegex = TRUE;
+
+ keys = isRegex ? watchedPatterns : watchedKeys;
+ if (CFArrayContainsValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusKeyExists));
+ CFRelease(key);
+ return;
+ }
+
+ CFArrayAppendValue(keys, key);
+ CFRelease(key);
+
+ if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_remove(int argc, char **argv)
+{
+ CFStringRef key;
+ CFMutableArrayRef keys;
+ CFIndex i;
+ Boolean isRegex = FALSE;
+
+ if (store == NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoStoreSession));
+ return;
+ }
+
+ key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+ if (argc == 2)
+ isRegex = TRUE;
+
+ keys = isRegex ? watchedPatterns : watchedKeys;
+ i = CFArrayGetFirstIndexOfValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key);
+ CFRelease(key);
+
+ if (i == kCFNotFound) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoKey));
+ return;
+ }
+
+ CFArrayRemoveValueAtIndex(keys, i);
+
+ if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_changes(int argc, char **argv)
+{
+ CFArrayRef list;
+ CFIndex listCnt;
+ int i;
+
+ list = SCDynamicStoreCopyNotifiedKeys(store);
+ if (!list) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ listCnt = CFArrayGetCount(list);
+ if (listCnt > 0) {
+ for (i = 0; i < listCnt; i++) {
+ SCPrint(TRUE,
+ stdout,
+ CFSTR(" changedKey [%d] = %@\n"),
+ i,
+ CFArrayGetValueAtIndex(list, i));
+ }
+ } else {
+ SCPrint(TRUE, stdout, CFSTR(" no changedKey's.\n"));
+ }
+ CFRelease(list);
+
+ return;
+}
+
+
+static void *
+_watcher(void *arg)
+{
+ notifyRl = CFRunLoopGetCurrent();
+ if (!notifyRl) {
+ SCPrint(TRUE, stdout, CFSTR(" CFRunLoopGetCurrent() failed\n"));
+ return NULL;
+ }
+
+ notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+ if (!notifyRls) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return NULL;
+ }
+ CFRunLoopAddSource(notifyRl, notifyRls, kCFRunLoopDefaultMode);
+
+ CFRunLoopRun();
+ return NULL;
+}
+
+__private_extern__
+void
+do_notify_watch(int argc, char **argv)
+{
+ pthread_attr_t tattr;
+ pthread_t tid;
+
+ if (notifyRl) {
+ return;
+ }
+
+ pthread_attr_init(&tattr);
+ pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+ pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+// pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
+ pthread_create(&tid, &tattr, _watcher, NULL);
+ pthread_attr_destroy(&tattr);
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_wait(int argc, char **argv)
+{
+ if (!SCDynamicStoreNotifyWait(store)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ return;
+}
+
+
+static boolean_t
+notificationWatcher(SCDynamicStoreRef store, void *arg)
+{
+ SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
+ SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
+ return TRUE;
+}
+
+
+static boolean_t
+notificationWatcherVerbose(SCDynamicStoreRef store, void *arg)
+{
+ SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
+ SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
+ do_notify_changes(0, NULL); /* report the keys which changed */
+ return TRUE;
+}
+
+
+__private_extern__
+void
+do_notify_callback(int argc, char **argv)
+{
+ SCDynamicStoreCallBack_v1 func = notificationWatcher;
+
+ if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
+ func = notificationWatcherVerbose;
+ }
+
+ if (!SCDynamicStoreNotifyCallback(store, CFRunLoopGetCurrent(), func, "Changed detected by callback handler!")) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_file(int argc, char **argv)
+{
+ int32_t reqID = 0;
+ int fd;
+ union {
+ char data[4];
+ int32_t gotID;
+ } buf;
+ char *bufPtr;
+ int needed;
+
+ if (argc == 1) {
+ if ((sscanf(argv[0], "%d", &reqID) != 1)) {
+ SCPrint(TRUE, stdout, CFSTR("invalid identifier.\n"));
+ return;
+ }
+ }
+
+ if (!SCDynamicStoreNotifyFileDescriptor(store, reqID, &fd)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ bzero(buf.data, sizeof(buf.data));
+ bufPtr = &buf.data[0];
+ needed = sizeof(buf.gotID);
+ while (needed > 0) {
+ int got;
+
+ got = read(fd, bufPtr, needed);
+ if (got == -1) {
+ /* if error detected */
+ SCPrint(TRUE, stdout, CFSTR("read() failed: %s.\n"), strerror(errno));
+ break;
+ }
+
+ if (got == 0) {
+ /* if end of file detected */
+ SCPrint(TRUE, stdout, CFSTR("read(): detected end of file.\n"));
+ break;
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("Received %d bytes.\n"), got);
+ bufPtr += got;
+ needed -= got;
+ }
+
+ if (needed != sizeof(buf.gotID)) {
+ SCPrint(TRUE, stdout, CFSTR(" Received notification, identifier = %d.\n"), buf.gotID);
+ }
+
+ /* this utility only allows processes one notification per "n.file" request */
+ (void) SCDynamicStoreNotifyCancel(store);
+
+ (void) close(fd); /* close my side of the file descriptor */
+
+ return;
+}
+
+
+static void
+signalCatcher(int signum)
+{
+ static int n = 0;
+
+ SCPrint(TRUE, stdout, CFSTR("Received sig%s (#%d).\n"), sys_signame[signum], n++);
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_signal(int argc, char **argv)
+{
+ int sig;
+ pid_t pid;
+ struct sigaction nact;
+ int ret;
+
+ if (isdigit(*argv[0])) {
+ if ((sscanf(argv[0], "%d", &sig) != 1) || (sig <= 0) || (sig >= NSIG)) {
+ SCPrint(TRUE, stdout, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG-1);
+ return;
+ }
+ } else {
+ for (sig = 1; sig < NSIG; sig++) {
+ if (strcasecmp(argv[0], sys_signame[sig]) == 0)
+ break;
+ }
+ if (sig >= NSIG) {
+ CFMutableStringRef str;
+
+ SCPrint(TRUE, stdout, CFSTR("Signal must be one of the following:\n"));
+
+ str = CFStringCreateMutable(NULL, 0);
+ for (sig = 1; sig < NSIG; sig++) {
+ CFStringAppendFormat(str, NULL, CFSTR(" %-6s"), sys_signame[sig]);
+ if ((sig % 10) == 0) {
+ CFStringAppendFormat(str, NULL, CFSTR("\n"));
+ }
+ }
+ if ((sig % 10) != 0) {
+ CFStringAppendFormat(str, NULL, CFSTR("\n"));
+ }
+ SCPrint(TRUE, stdout, CFSTR("%@"), str);
+ CFRelease(str);
+ return;
+ }
+
+ }
+
+ if ((argc != 2) || (sscanf(argv[1], "%d", &pid) != 1)) {
+ pid = getpid();
+ }
+
+ if (oact != NULL) {
+ ret = sigaction(osig, oact, NULL); /* restore original signal handler */
+ } else {
+ oact = malloc(sizeof(struct sigaction));
+ }
+
+ nact.sa_handler = signalCatcher;
+ sigemptyset(&nact.sa_mask);
+ nact.sa_flags = SA_RESTART;
+ ret = sigaction(sig, &nact, oact);
+ osig = sig;
+ SCPrint(TRUE, stdout, CFSTR("signal handler started.\n"));
+
+ if (!SCDynamicStoreNotifySignal(store, pid, sig)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ return;
+}
+
+
+__private_extern__
+void
+do_notify_cancel(int argc, char **argv)
+{
+ int ret;
+
+ if (notifyRls) {
+ CFRunLoopSourceInvalidate(notifyRls);
+ CFRelease(notifyRls);
+ notifyRls = NULL;
+ }
+
+ if (notifyRl) {
+ CFRunLoopStop(notifyRl);
+ notifyRl = NULL;
+ }
+
+ if (!SCDynamicStoreNotifyCancel(store)) {
+ SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
+ return;
+ }
+
+ if (oact != NULL) {
+ ret = sigaction(osig, oact, NULL); /* restore original signal handler */
+ free(oact);
+ oact = NULL;
+ }
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2000 Apple Computer, 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@
+ */
+
+/*
+ * Modification History
+ *
+ * June 1, 2001 Allan Nathanson <ajn@apple.com>
+ * - public API conversion
+ *
+ * November 9, 2000 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NOTIFICATIONS_H
+#define _NOTIFICATIONS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+void storeCallback (SCDynamicStoreRef store,
+ CFArrayRef changedKeys,
+ void *info);
+
+void do_notify_list (int argc, char **argv);
+void do_notify_add (int argc, char **argv);
+void do_notify_remove (int argc, char **argv);
+void do_notify_changes (int argc, char **argv);
+void do_notify_watch (int argc, char **argv);
+void do_notify_wait (int argc, char **argv);
+void do_notify_callback (int argc, char **argv);
+void do_notify_signal (int argc, char **argv);
+void do_notify_file (int argc, char **argv);
+void do_notify_cancel (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NOTIFICATIONS_H */
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * November 9, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "scutil.h"
-#include "notify.h"
-
-
-static int osig;
-static struct sigaction *oact = NULL;
-
-
-static CFComparisonResult
-sort_keys(const void *p1, const void *p2, void *context) {
- CFStringRef key1 = (CFStringRef)p1;
- CFStringRef key2 = (CFStringRef)p2;
- return CFStringCompare(key1, key2, 0);
-}
-
-
-void
-storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
-{
- int i;
- CFIndex n;
-
- SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
-
- n = CFArrayGetCount(changedKeys);
- if (n > 0) {
- for (i = 0; i < n; i++) {
- SCPrint(TRUE,
- stdout,
- CFSTR(" changed key [%d] = %@\n"),
- i,
- CFArrayGetValueAtIndex(changedKeys, i));
- }
- } else {
- SCPrint(TRUE, stdout, CFSTR(" no changed key's.\n"));
- }
-
- return;
-}
-
-
-void
-do_notify_list(int argc, char **argv)
-{
- int i;
- CFArrayRef list;
- CFIndex listCnt;
- Boolean isRegex = FALSE;
- CFMutableArrayRef sortedList;
-
- if (!store) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoStoreSession));
- return;
- }
-
- if (argc == 1)
- isRegex = TRUE;
-
- list = isRegex ? watchedPatterns : watchedKeys;
- if (!list) {
- SCPrint(TRUE,
- stdout,
- CFSTR(" no notifier %s.\n"),
- isRegex ? "patterns" : "keys");
- return;
- }
-
- listCnt = CFArrayGetCount(list);
- sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list);
- CFArraySortValues(sortedList,
- CFRangeMake(0, listCnt),
- sort_keys,
- NULL);
-
- if (listCnt > 0) {
- for (i = 0; i < listCnt; i++) {
- SCPrint(TRUE,
- stdout,
- CFSTR(" notifier %s [%d] = %@\n"),
- isRegex ? "pattern" : "key",
- i,
- CFArrayGetValueAtIndex(sortedList, i));
- }
- } else {
- SCPrint(TRUE,
- stdout,
- CFSTR(" no notifier %s.\n"),
- isRegex ? "patterns" : "keys");
- }
- CFRelease(sortedList);
-
- return;
-}
-
-
-void
-do_notify_add(int argc, char **argv)
-{
- CFStringRef key;
- CFMutableArrayRef keys;
- Boolean isRegex = FALSE;
-
- if (!store) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoStoreSession));
- return;
- }
-
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
-
- if (argc == 2)
- isRegex = TRUE;
-
- keys = isRegex ? watchedPatterns : watchedKeys;
- if (CFArrayContainsValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusKeyExists));
- CFRelease(key);
- return;
- }
-
- CFArrayAppendValue(keys, key);
- CFRelease(key);
-
- if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- }
-
- return;
-}
-
-
-void
-do_notify_remove(int argc, char **argv)
-{
- CFStringRef key;
- CFMutableArrayRef keys;
- CFIndex i;
- Boolean isRegex = FALSE;
-
- if (!store) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoStoreSession));
- return;
- }
-
- key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
-
- if (argc == 2)
- isRegex = TRUE;
-
- keys = isRegex ? watchedPatterns : watchedKeys;
- i = CFArrayGetFirstIndexOfValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key);
- CFRelease(key);
-
- if (i == kCFNotFound) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNoKey));
- return;
- }
-
- CFArrayRemoveValueAtIndex(keys, i);
-
- if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- }
-
- return;
-}
-
-
-void
-do_notify_changes(int argc, char **argv)
-{
- CFArrayRef list;
- CFIndex listCnt;
- int i;
-
- list = SCDynamicStoreCopyNotifiedKeys(store);
- if (!list) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return;
- }
-
- listCnt = CFArrayGetCount(list);
- if (listCnt > 0) {
- for (i = 0; i < listCnt; i++) {
- SCPrint(TRUE,
- stdout,
- CFSTR(" changedKey [%d] = %@\n"),
- i,
- CFArrayGetValueAtIndex(list, i));
- }
- } else {
- SCPrint(TRUE, stdout, CFSTR(" no changedKey's.\n"));
- }
- CFRelease(list);
-
- return;
-}
-
-
-static void *
-_watcher(void *arg)
-{
- notifyRl = CFRunLoopGetCurrent();
- if (!notifyRl) {
- SCPrint(TRUE, stdout, CFSTR(" CFRunLoopGetCurrent() failed\n"));
- return NULL;
- }
-
- notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
- if (!notifyRls) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return NULL;
- }
- CFRunLoopAddSource(notifyRl, notifyRls, kCFRunLoopDefaultMode);
-
- CFRunLoopRun();
- return NULL;
-}
-
-void
-do_notify_watch(int argc, char **argv)
-{
- pthread_attr_t tattr;
- pthread_t tid;
-
- if (notifyRl) {
- return;
- }
-
- pthread_attr_init(&tattr);
- pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
- pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-// pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
- pthread_create(&tid, &tattr, _watcher, NULL);
- pthread_attr_destroy(&tattr);
-
- return;
-}
-
-
-void
-do_notify_wait(int argc, char **argv)
-{
- if (!SCDynamicStoreNotifyWait(store)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return;
- }
-
- return;
-}
-
-
-static boolean_t
-notificationWatcher(SCDynamicStoreRef store, void *arg)
-{
- SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
- SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
- return TRUE;
-}
-
-
-static boolean_t
-notificationWatcherVerbose(SCDynamicStoreRef store, void *arg)
-{
- SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
- SCPrint(TRUE, stdout, CFSTR(" arg = %s.\n"), (char *)arg);
- do_notify_changes(0, NULL); /* report the keys which changed */
- return TRUE;
-}
-
-
-void
-do_notify_callback(int argc, char **argv)
-{
- SCDynamicStoreCallBack_v1 func = notificationWatcher;
-
- if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
- func = notificationWatcherVerbose;
- }
-
- if (!SCDynamicStoreNotifyCallback(store, CFRunLoopGetCurrent(), func, "Changed detected by callback handler!")) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return;
- }
-
- return;
-}
-
-
-void
-do_notify_file(int argc, char **argv)
-{
- int32_t reqID = 0;
- int fd;
- union {
- char data[4];
- int32_t gotID;
- } buf;
- char *bufPtr;
- int needed;
-
- if (argc == 1) {
- if ((sscanf(argv[0], "%d", &reqID) != 1)) {
- SCPrint(TRUE, stdout, CFSTR("invalid identifier.\n"));
- return;
- }
- }
-
- if (!SCDynamicStoreNotifyFileDescriptor(store, reqID, &fd)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return;
- }
-
- bzero(buf.data, sizeof(buf.data));
- bufPtr = &buf.data[0];
- needed = sizeof(buf.gotID);
- while (needed > 0) {
- int got;
-
- got = read(fd, bufPtr, needed);
- if (got == -1) {
- /* if error detected */
- SCPrint(TRUE, stdout, CFSTR("read() failed: %s.\n"), strerror(errno));
- break;
- }
-
- if (got == 0) {
- /* if end of file detected */
- SCPrint(TRUE, stdout, CFSTR("read(): detected end of file.\n"));
- break;
- }
-
- SCPrint(TRUE, stdout, CFSTR("Received %d bytes.\n"), got);
- bufPtr += got;
- needed -= got;
- }
-
- if (needed != sizeof(buf.gotID)) {
- SCPrint(TRUE, stdout, CFSTR(" Received notification, identifier = %d.\n"), buf.gotID);
- }
-
- /* this utility only allows processes one notification per "n.file" request */
- (void) SCDynamicStoreNotifyCancel(store);
-
- (void) close(fd); /* close my side of the file descriptor */
-
- return;
-}
-
-
-static void
-signalCatcher(int signum)
-{
- static int n = 0;
-
- SCPrint(TRUE, stdout, CFSTR("Received sig%s (#%d).\n"), sys_signame[signum], n++);
- return;
-}
-
-
-void
-do_notify_signal(int argc, char **argv)
-{
- int sig;
- pid_t pid;
- struct sigaction nact;
- int ret;
-
- if (isdigit(*argv[0])) {
- if ((sscanf(argv[0], "%d", &sig) != 1) || (sig <= 0) || (sig >= NSIG)) {
- SCPrint(TRUE, stdout, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG-1);
- return;
- }
- } else {
- for (sig = 1; sig < NSIG; sig++) {
- if (strcasecmp(argv[0], sys_signame[sig]) == 0)
- break;
- }
- if (sig >= NSIG) {
- CFMutableStringRef str;
-
- SCPrint(TRUE, stdout, CFSTR("Signal must be one of the following:\n"));
-
- str = CFStringCreateMutable(NULL, 0);
- for (sig = 1; sig < NSIG; sig++) {
- CFStringAppendFormat(str, NULL, CFSTR(" %-6s"), sys_signame[sig]);
- if ((sig % 10) == 0) {
- CFStringAppendFormat(str, NULL, CFSTR("\n"));
- }
- }
- if ((sig % 10) != 0) {
- CFStringAppendFormat(str, NULL, CFSTR("\n"));
- }
- SCPrint(TRUE, stdout, CFSTR("%@"), str);
- CFRelease(str);
- return;
- }
-
- }
-
- if ((argc != 2) || (sscanf(argv[1], "%d", &pid) != 1)) {
- pid = getpid();
- }
-
- if (oact != NULL) {
- ret = sigaction(osig, oact, NULL); /* restore original signal handler */
- } else {
- oact = malloc(sizeof(struct sigaction));
- }
-
- nact.sa_handler = signalCatcher;
- sigemptyset(&nact.sa_mask);
- nact.sa_flags = SA_RESTART;
- ret = sigaction(sig, &nact, oact);
- osig = sig;
- SCPrint(TRUE, stdout, CFSTR("signal handler started.\n"));
-
- if (!SCDynamicStoreNotifySignal(store, pid, sig)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return;
- }
-
- return;
-}
-
-
-void
-do_notify_cancel(int argc, char **argv)
-{
- int ret;
-
- if (notifyRls) {
- CFRunLoopRemoveSource(notifyRl, notifyRls, kCFRunLoopDefaultMode);
- CFRelease(notifyRls);
- notifyRls = NULL;
- }
-
- if (notifyRl) {
- CFRunLoopStop(notifyRl);
- notifyRl = NULL;
- }
-
- if (!SCDynamicStoreNotifyCancel(store)) {
- SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
- return;
- }
-
- if (oact != NULL) {
- ret = sigaction(osig, oact, NULL); /* restore original signal handler */
- free(oact);
- oact = NULL;
- }
-
- return;
-}
+++ /dev/null
-/*
- * Copyright (c) 2000 Apple Computer, 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@
- */
-
-/*
- * Modification History
- *
- * June 1, 2001 Allan Nathanson <ajn@apple.com>
- * - public API conversion
- *
- * November 9, 2000 Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#ifndef _NOTIFY_H
-#define _NOTIFY_H
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-void storeCallback (SCDynamicStoreRef store,
- CFArrayRef changedKeys,
- void *info);
-
-void do_notify_list (int argc, char **argv);
-void do_notify_add (int argc, char **argv);
-void do_notify_remove (int argc, char **argv);
-void do_notify_changes (int argc, char **argv);
-void do_notify_watch (int argc, char **argv);
-void do_notify_wait (int argc, char **argv);
-void do_notify_callback (int argc, char **argv);
-void do_notify_signal (int argc, char **argv);
-void do_notify_file (int argc, char **argv);
-void do_notify_cancel (int argc, char **argv);
-
-__END_DECLS
-
-#endif /* !_NOTIFY_H */
/*
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
static SCPreferencesRef
_open()
{
- SCPreferencesRef prefs;
-
prefs = SCPreferencesCreate(NULL, CFSTR("scutil"), NULL);
- if (!prefs) {
+ if (prefs == NULL) {
SCPrint(TRUE,
stdout,
CFSTR("SCPreferencesCreate() failed: %s\n"),
{
CFStringEncoding encoding;
CFStringRef hostname;
- SCPreferencesRef prefs;
if (argc == 0) {
hostname = _copyStringFromSTDIN();
}
+static void
+get_HostName(int argc, char **argv)
+{
+ CFStringRef hostname;
+
+ prefs = _open();
+ hostname = SCPreferencesGetHostName(prefs);
+ if (hostname == NULL) {
+ int sc_status = SCError();
+
+ switch (sc_status) {
+ case kSCStatusNoKey :
+ SCPrint(TRUE,
+ stderr,
+ CFSTR("HostName: not set\n"));
+ break;
+ default :
+ SCPrint(TRUE,
+ stderr,
+ CFSTR("SCPreferencesGetHostName() failed: %s\n"),
+ SCErrorString(SCError()));
+ break;
+ }
+ CFRelease(prefs);
+ exit (1);
+ }
+
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
+ CFRelease(hostname);
+ exit(0);
+}
+
+
+static void
+set_HostName(int argc, char **argv)
+{
+ CFStringRef hostname = NULL;
+
+ if (argc == 0) {
+ hostname = _copyStringFromSTDIN();
+ } else {
+ hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingASCII);
+ }
+
+ prefs = _open();
+ if (!SCPreferencesSetHostName(prefs, hostname)) {
+ SCPrint(TRUE,
+ stderr,
+ CFSTR("SCPreferencesSetHostName() failed: %s\n"),
+ SCErrorString(SCError()));
+ CFRelease(hostname);
+ CFRelease(prefs);
+ exit (1);
+ }
+ _save(prefs);
+ CFRelease(hostname);
+ CFRelease(prefs);
+ exit(0);
+}
+
+
static void
get_LocalHostName(int argc, char **argv)
{
set_LocalHostName(int argc, char **argv)
{
CFStringRef hostname = NULL;
- SCPreferencesRef prefs;
if (argc == 0) {
hostname = _copyStringFromSTDIN();
typedef void (*pref_func) (int argc, char **argv);
-static struct {
+static const struct {
char *pref;
pref_func get;
pref_func set;
-} prefs[] = {
+} pref_keys[] = {
{ "ComputerName", get_ComputerName, set_ComputerName },
+ { "HostName", get_HostName, set_HostName },
{ "LocalHostName", get_LocalHostName, set_LocalHostName }
};
-#define N_PREFS (sizeof(prefs) / sizeof(prefs[0]))
+#define N_PREF_KEYS (sizeof(pref_keys) / sizeof(pref_keys[0]))
+__private_extern__
int
findPref(char *pref)
{
int i;
- for (i = 0; i < (int)N_PREFS; i++) {
- if (strcmp(pref, prefs[i].pref) == 0) {
+ for (i = 0; i < (int)N_PREF_KEYS; i++) {
+ if (strcmp(pref, pref_keys[i].pref) == 0) {
return i;
}
}
}
+__private_extern__
void
do_getPref(char *pref, int argc, char **argv)
{
i = findPref(pref);
if (i >= 0) {
- (*prefs[i].get)(argc, argv);
+ (*pref_keys[i].get)(argc, argv);
}
return;
}
+__private_extern__
void
do_setPref(char *pref, int argc, char **argv)
{
i = findPref(pref);
if (i >= 0) {
- (*prefs[i].set)(argc, argv);
+ (*pref_keys[i].set)(argc, argv);
}
return;
}
--- /dev/null
+.\"
+.\" @(#)scutil.8
+.\"
+.Dd November 4, 2003
+.Dt SCUTIL 8
+.Os Mac OS X
+.Sh NAME
+.Nm scutil
+.Nd Manage system configuration parameters
+.Sh SYNOPSIS
+.Nm
+.Br
+.Nm
+.Fl r Bro "" Ar nodename | Ar address | Ar local-address remote-address "" Brc
+.Br
+.Nm
+.Fl w Ar dynamic-store-key Op Fl t Ar timeout
+.Br
+.Nm
+.Fl -get Ar pref
+.Br
+.Nm
+.Fl -set Ar pref Op Ar newval
+.\".Br
+.\".Nm
+.\".Fl -net
+.Sh DESCRIPTION
+Invoked with no options,
+.Nm
+provides a command line interface to the
+.Qq dynamic store
+data maintained by
+.Xr configd 8 .
+Interaction with this data (using the SystemConfiguration.framework
+SCDynamicStore APIs) is handled with a set of commands read from
+standard input.
+A list of the available commands is available by entering the
+.Ar help
+directive.
+.Pp
+The
+.Fl r
+option provides a means of checking the network reachability of a host, an IP
+address, or a pair of local and remote IP addresses.
+Network
+.Qq reachability
+is a term that indicates whether network communication is possible between
+the current host and the specified host.
+.Pp
+The
+.Fl w
+option provides a means of checking for (and optionally waiting for the
+creation of) a dynamic store key.
+.Pp
+The
+.Fl -get
+and
+.Fl -set
+options provide a means of reporting and updating a select group of
+persistent system preferences.
+.\".Pp
+.\"Lastly, the
+.\".Fl -net
+.\"option provides a means of managing the system's network configuration.
+.Sh OPTIONS
+.Bl -tag -width xx
+.It Fl r Bro "" Ar nodename | Ar address | Ar local-address remote-address "" Brc
+Check the network reachability of the specified host name, IP address, or a
+pair of local and remote IP addresses.
+One or more of the following strings will be reported to standard output.
+.Pp
+.Bl -tag -width "Transient Connection"
+.It Not Reachable
+The specified nodename/address cannot be reached using the current network
+configuration.
+.It Reachable
+The specified nodename/address can be reached using the current network
+configuration.
+.It Transient Connection
+The specified nodename/address can be reached via a transient (e.g. PPP)
+connection.
+.It Connection Required
+The specified nodename/address can be reached using the current network
+configuration but a connection must first be established.
+As an example, this status would be returned for a dialup connection
+that was not currently active but could handle network traffic for the
+target system.
+.It Connection Automatic
+The specified nodename/address can be reached using the current network
+configuration but a connection must first be established.
+Any traffic directed to the specified name/address will initiate the
+connection.
+.It Local Address
+The specified nodename/address is one associated with a network interface
+on the system.
+.It Directly Reachable Addresss
+Network traffic to the specified nodename/address will not go through a
+gateway but is routed directly to one of the interfaces on the system.
+.El
+.Pp
+A zero exit status will be returned when the reachability status is reported correctly.
+A non-zero exit status will be returned if errors are detected with an error reported to standard error.
+.It Fl w Ar dynamic-store-key Op Fl t Ar timeout
+Check if the specified key exists in the
+.Qq dynamic store
+data maintained by
+.Xr configd 8 .
+If present,
+.Nm
+will return with a zero exit status.
+If not present,
+.Nm
+will wait for the specified time for the key to be established.
+A non-zero exit status will be returned if the key was not created within the specified time.
+.Pp
+.Nm
+will wait indefinitely if a timeout of 0 seconds is specified.
+The default timeout is 15 seconds.
+.It Fl -get Ar pref
+Retrieves the specified preference. The current value will be reported on standard output.
+.Pp
+Supported preferences include:
+ComputerName
+LocalHostName
+.It Fl -set Ar pref Op Ar newval
+Updates the specified preference with the new value.
+If the new value is not specified on the command line then it will be read from standard input.
+.Pp
+Supported preferences include:
+ComputerName
+LocalHostName
+.Pp
+The
+.Fl -set
+option requires super-user access.
+.\".It Fl -net
+.\"Provides a command line interface to the
+.\".Qq network configuration .
+.\"Interaction with this data (using the SystemConfiguration.framework
+.\"SCNetworkConfiguration APIs) is handled with a set of commands read
+.\"from standard input. A list of the available commands is available
+.\"by entering the help directive.
+.\".Pp
+.\"The
+.\".Fl -net
+.\"option requires super-user access.
+.El
+.Sh SEE ALSO
+.Xr configd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in Mac OS X Public Beta.
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
/*
* Modification History
*
+ * August 4, 2004 Allan Nathanson <ajn@apple.com>
+ * - added network configuration (prefs) support
+ *
* September 25, 2002 Allan Nathanson <ajn@apple.com>
* - added command line history & editing
*
#include "scutil.h"
#include "commands.h"
#include "dictionary.h"
-#include "tests.h"
+#include "net.h"
#include "prefs.h"
+#include "session.h"
+#include "tests.h"
#include "SCDynamicStoreInternal.h"
#define LINE_LENGTH 256
-int nesting = 0;
-CFRunLoopRef notifyRl = NULL;
-CFRunLoopSourceRef notifyRls = NULL;
-SCDynamicStoreRef store = NULL;
-CFPropertyListRef value = NULL;
-CFMutableArrayRef watchedKeys = NULL;
-CFMutableArrayRef watchedPatterns = NULL;
+__private_extern__ InputRef currentInput = NULL;
+__private_extern__ int nesting = 0;
+__private_extern__ CFRunLoopRef notifyRl = NULL;
+__private_extern__ CFRunLoopSourceRef notifyRls = NULL;
+__private_extern__ SCPreferencesRef prefs = NULL;
+__private_extern__ SCDynamicStoreRef store = NULL;
+__private_extern__ CFPropertyListRef value = NULL;
+__private_extern__ CFMutableArrayRef watchedKeys = NULL;
+__private_extern__ CFMutableArrayRef watchedPatterns = NULL;
-static struct option longopts[] = {
+static const struct option longopts[] = {
// { "debug", no_argument, NULL, 'd' },
// { "verbose", no_argument, NULL, 'v' },
// { "SPI", no_argument, NULL, 'p' },
-// { "check-reachability", required_argument, NULL, 'r' },
+// { "check-reachability", required_argument, NULL, 'r' },
// { "timeout", required_argument, NULL, 't' },
// { "wait-key", required_argument, NULL, 'w' },
+ { "dns", no_argument, NULL, 0 },
{ "get", required_argument, NULL, 0 },
{ "help", no_argument, NULL, '?' },
+ { "net", no_argument, NULL, 0 },
+ { "proxy", no_argument, NULL, 0 },
{ "set", required_argument, NULL, 0 },
- { NULL, 0, NULL, 0 }
+ { NULL, 0, NULL, 0 }
};
}
-char *
+static char *
getString(char **line)
{
char *s, *e, c, *string;
}
+__private_extern__
Boolean
process_line(InputRef src)
{
- char line[LINE_LENGTH], *s, *arg, **argv = NULL;
- int i, argc;
-
- /* if end-of-file, exit */
+ char *arg;
+ int argc = 0;
+ char **argv = NULL;
+ int i;
+ char line[LINE_LENGTH];
+ char *s = line;
+
+ // if end-of-file, exit
if (getLine(line, sizeof(line), src) == NULL)
return FALSE;
SCPrint(TRUE, stdout, CFSTR("%d> %s\n"), nesting, line);
}
- /* if requested, exit */
- if (strcasecmp(line, "exit") == 0) return FALSE;
- if (strcasecmp(line, "quit") == 0) return FALSE;
- if (strcasecmp(line, "q" ) == 0) return FALSE;
-
- /* break up the input line */
- s = line;
- argc = 0;
+ // break up the input line
while ((arg = getString(&s)) != NULL) {
if (argc == 0)
argv = (char **)malloc(2 * sizeof(char *));
else
- argv = (char **)realloc(argv, ((argc + 2) * sizeof(char *)));
+ argv = (char **)reallocf(argv, ((argc + 2) * sizeof(char *)));
argv[argc++] = arg;
}
- /* process the command */
- if (argc > 0) {
- argv[argc] = NULL; /* just in case... */
+ if (argc == 0) {
+ return TRUE; // if no arguments
+ }
- if (*argv[0] != '#')
- do_command(argc, argv);
+ /* process the command */
+ if (*argv[0] != '#') {
+ argv[argc] = NULL; // just in case...
+ currentInput = src;
+ do_command(argc, argv);
+ }
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
+ /* free the arguments */
+ for (i = 0; i < argc; i++) {
+ free(argv[i]);
}
+ free(argv);
- return TRUE;
+ return !termRequested;
}
-void
+static void
usage(const char *command)
{
SCPrint(TRUE, stderr, CFSTR("usage: %s\n"), command);
SCPrint(TRUE, stderr, CFSTR("\t\t\tComputerName, LocalHostName\n"));
SCPrint(TRUE, stderr, CFSTR("\tnewval\tNew preference value to be set. If not specified,\n"));
SCPrint(TRUE, stderr, CFSTR("\t\tthe new value will be read from standard input.\n"));
+ SCPrint(TRUE, stderr, CFSTR("\n"));
+ SCPrint(TRUE, stderr, CFSTR(" or: %s --dns\n"), command);
+ SCPrint(TRUE, stderr, CFSTR("\tshow DNS configuration.\n"));
+ SCPrint(TRUE, stderr, CFSTR("\n"));
+ SCPrint(TRUE, stderr, CFSTR(" or: %s --proxy\n"), command);
+ SCPrint(TRUE, stderr, CFSTR("\tshow \"proxy\" configuration.\n"));
+
+ if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
+ SCPrint(TRUE, stderr, CFSTR("\n"));
+ SCPrint(TRUE, stderr, CFSTR(" or: %s --net\n"), command);
+ SCPrint(TRUE, stderr, CFSTR("\tmanage network configuration.\n"));
+ }
+
exit (EX_USAGE);
}
int
main(int argc, char * const argv[])
{
+ Boolean dns = FALSE;
char *get = NULL;
+ Boolean net = FALSE;
extern int optind;
int opt;
int opti;
const char *prog = argv[0];
+ Boolean proxy = FALSE;
Boolean reach = FALSE;
char *set = NULL;
InputRef src;
xStore++;
break;
case 0:
- if (strcmp(longopts[opti].name, "get") == 0) {
+ if (strcmp(longopts[opti].name, "dns") == 0) {
+ dns = TRUE;
+ xStore++;
+ } else if (strcmp(longopts[opti].name, "get") == 0) {
get = optarg;
xStore++;
+ } else if (strcmp(longopts[opti].name, "net") == 0) {
+ net = TRUE;
+ xStore++;
+ } else if (strcmp(longopts[opti].name, "proxy") == 0) {
+ proxy = TRUE;
+ xStore++;
} else if (strcmp(longopts[opti].name, "set") == 0) {
set = optarg;
xStore++;
/* NOT REACHED */
}
+ /* are we looking up the DNS configuration */
+ if (dns) {
+ do_showDNSConfiguration(argc, (char **)argv);
+ /* NOT REACHED */
+ }
+
/* are we looking up a preference value */
if (get) {
if (findPref(get) < 0) {
/* NOT REACHED */
}
+ /* are we looking up the proxy configuration */
+ if (proxy) {
+ do_showProxyConfiguration(argc, (char **)argv);
+ /* NOT REACHED */
+ }
+
/* are we changing a preference value */
if (set) {
if (findPref(set) < 0) {
/* NOT REACHED */
}
- /* start with an empty dictionary */
- do_dictInit(0, NULL);
+ if (net) {
+ /* if we are going to be managing the network configuration */
+ commands = (cmdInfo *)commands_prefs;
+ nCommands = nCommands_prefs;
+
+ if (!getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
+ usage(prog);
+ }
+
+ do_net_init(); /* initialization */
+ do_net_open(0, NULL); /* open default prefs */
+ } else {
+ /* if we are going to be managing the dynamic store */
+ commands = (cmdInfo *)commands_store;
+ nCommands = nCommands_store;
+
+ do_dictInit(0, NULL); /* start with an empty dictionary */
+ do_open(0, NULL); /* open the dynamic store */
+ }
/* allocate command input stream */
src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
} Input, *InputRef;
+extern InputRef currentInput;
extern int nesting;
extern CFRunLoopRef notifyRl;
extern CFRunLoopSourceRef notifyRls;
+extern SCPreferencesRef prefs;
extern SCDynamicStoreRef store;
extern CFPropertyListRef value;
extern CFMutableArrayRef watchedKeys;
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include "scutil.h"
#include "session.h"
-#include "notify.h"
+#include "notifications.h"
+__private_extern__
void
do_open(int argc, char **argv)
{
CFRelease(watchedPatterns);
}
- store = SCDynamicStoreCreate(NULL, CFSTR("scutil"), storeCallback, NULL);
- if (!store) {
+ if (argc < 1) {
+ store = SCDynamicStoreCreate(NULL, CFSTR("scutil"), storeCallback, NULL);
+ } else {
+ CFMutableDictionaryRef options;
+
+ options = CFDictionaryCreateMutable(NULL,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(options, kSCDynamicStoreUseSessionKeys, kCFBooleanTrue);
+ store = SCDynamicStoreCreateWithOptions(NULL,
+ CFSTR("scutil"),
+ options,
+ storeCallback,
+ NULL);
+ CFRelease(options);
+ }
+ if (store == NULL) {
SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
return;
}
}
+__private_extern__
void
do_close(int argc, char **argv)
{
if (notifyRls) {
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
+ CFRunLoopSourceInvalidate(notifyRls);
CFRelease(notifyRls);
notifyRls = NULL;
}
}
+__private_extern__
void
do_lock(int argc, char **argv)
{
}
+__private_extern__
void
do_unlock(int argc, char **argv)
{
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <dnsinfo.h>
+__private_extern__
void
do_checkReachability(int argc, char **argv)
{
}
+__private_extern__
+void
+do_showDNSConfiguration(int argc, char **argv)
+{
+ dns_config_t *dns_config;
+
+ dns_config = dns_configuration_copy();
+ if (dns_config) {
+ int n;
+
+ SCPrint(TRUE, stdout, CFSTR("DNS configuration\n"));
+
+ for (n = 0; n < dns_config->n_resolver; n++) {
+ int i;
+ dns_resolver_t *resolver = dns_config->resolver[n];
+
+ SCPrint(TRUE, stdout, CFSTR("\nresolver #%d\n"), n + 1);
+
+ if (resolver->domain != NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" domain : %s\n"), resolver->domain);
+ }
+
+ for (i = 0; i < resolver->n_search; i++) {
+ SCPrint(TRUE, stdout, CFSTR(" search domain[%d] : %s\n"), i, resolver->search[i]);
+ }
+
+ for (i = 0; i < resolver->n_nameserver; i++) {
+ char buf[128];
+
+ _SC_sockaddr_to_string(resolver->nameserver[i], buf, sizeof(buf));
+ SCPrint(TRUE, stdout, CFSTR(" nameserver[%d] : %s\n"), i, buf);
+ }
+
+ for (i = 0; i < resolver->n_sortaddr; i++) {
+ SCPrint(TRUE, stdout, CFSTR(" sortaddr[%d] : %s/%s\n"),
+ i,
+ inet_ntoa(resolver->sortaddr[i]->address),
+ inet_ntoa(resolver->sortaddr[i]->mask));
+ }
+
+ if (resolver->options != NULL) {
+ SCPrint(TRUE, stdout, CFSTR(" options : %s\n"), resolver->options);
+ }
+
+ if (resolver->port != 0) {
+ SCPrint(TRUE, stdout, CFSTR(" port : %hd\n"), ntohs(resolver->port));
+ }
+
+ if (resolver->timeout != 0) {
+ SCPrint(TRUE, stdout, CFSTR(" timeout : %d\n"), resolver->timeout);
+ }
+
+ if (resolver->search_order != 0) {
+ SCPrint(TRUE, stdout, CFSTR(" order : %d\n"), resolver->search_order);
+ }
+ }
+
+ dns_configuration_free(dns_config);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+ }
+
+ exit(0);
+}
+
+
+__private_extern__
+void
+do_showProxyConfiguration(int argc, char **argv)
+{
+ CFDictionaryRef proxies;
+
+ proxies = SCDynamicStoreCopyProxies(NULL);
+ if (proxies != NULL) {
+ SCPrint(TRUE, stdout, CFSTR("%@\n"), proxies);
+ } else {
+ SCPrint(TRUE, stdout, CFSTR("No proxy configuration available\n"));
+ }
+
+ exit(0);
+}
+
+
+__private_extern__
void
do_snapshot(int argc, char **argv)
{
}
+__private_extern__
void
do_wait(char *waitKey, int timeout)
{
CFMutableArrayRef keys;
store = SCDynamicStoreCreate(NULL, CFSTR("scutil (wait)"), waitKeyFound, NULL);
- if (!store) {
+ if (store == NULL) {
SCPrint(TRUE, stderr,
CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
exit(1);
}
keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- key = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingMacRoman);
+ key = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingUTF8);
CFArrayAppendValue(keys, key);
if (!SCDynamicStoreSetNotificationKeys(store, keys, NULL)) {
}
CFRelease(key);
- if (waitTimeout > 0) {
+ if (timeout > 0) {
signal(SIGALRM, waitTimeout);
bzero(&itv, sizeof(itv));
itv.it_value.tv_sec = timeout;
/*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
__BEGIN_DECLS
-void do_checkReachability (int argc, char **argv);
-void do_snapshot (int argc, char **argv);
-void do_wait (char *waitKey, int timeout);
+void do_checkReachability (int argc, char **argv);
+void do_showDNSConfiguration (int argc, char **argv);
+void do_showProxyConfiguration (int argc, char **argv);
+void do_snapshot (int argc, char **argv);
+void do_wait (char *waitKey, int timeout);
__END_DECLS