From: Apple Date: Mon, 11 Apr 2005 05:37:04 +0000 (+0000) Subject: configd-130.tar.gz X-Git-Tag: mac-os-x-104^0 X-Git-Url: https://git.saurik.com/apple/configd.git/commitdiff_plain/dbf6a266c384fc8b55e00a396eebe5cb62e21547?hp=4c5e92e2493bdfbbce40e998f3b607c72c47af2c configd-130.tar.gz --- diff --git a/APPLE_LICENSE b/APPLE_LICENSE new file mode 100644 index 0000000..fe81a60 --- /dev/null +++ b/APPLE_LICENSE @@ -0,0 +1,367 @@ +APPLE PUBLIC SOURCE LICENSE +Version 2.0 - August 6, 2003 + +Please read this License carefully before downloading this software. +By downloading or using this software, you are agreeing to be bound by +the terms of this License. If you do not or cannot agree to the terms +of this License, please do not download or use the software. + +1. General; Definitions. This License applies to any program or other +work which Apple Computer, Inc. ("Apple") makes publicly available and +which contains a notice placed by Apple identifying such program or +work as "Original Code" and stating that it is subject to the terms of +this Apple Public Source License version 2.0 ("License"). As used in +this License: + +1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is +the grantor of rights, (i) claims of patents that are now or hereafter +acquired, owned by or assigned to Apple and (ii) that cover subject +matter contained in the Original Code, but only to the extent +necessary to use, reproduce and/or distribute the Original Code +without infringement; and (b) in the case where You are the grantor of +rights, (i) claims of patents that are now or hereafter acquired, +owned by or assigned to You and (ii) that cover subject matter in Your +Modifications, taken alone or in combination with Original Code. + +1.2 "Contributor" means any person or entity that creates or +contributes to the creation of Modifications. + +1.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Externally Deploy" means: (a) to sublicense, distribute or +otherwise make Covered Code available, directly or indirectly, to +anyone other than You; and/or (b) to use Covered Code, alone or as +part of a Larger Work, in any way to provide a service, including but +not limited to delivery of content, through electronic communication +with a client other than You. + +1.5 "Larger Work" means a work which combines Covered Code or portions +thereof with code not governed by the terms of this License. + +1.6 "Modifications" mean any addition to, deletion from, and/or change +to, the substance and/or structure of the Original Code, any previous +Modifications, the combination of Original Code and any previous +Modifications, and/or any respective portions thereof. When code is +released as a series of files, a Modification is: (a) any addition to +or deletion from the contents of a file containing Covered Code; +and/or (b) any new file or other representation of computer program +statements that contains any part of Covered Code. + +1.7 "Original Code" means (a) the Source Code of a program or other +work as originally made available by Apple under this License, +including the Source Code of any updates or upgrades to such programs +or works made available by Apple under this License, and that has been +expressly identified by Apple as such in the header file(s) of such +work; and (b) the object code compiled from such Source Code and +originally made available by Apple under this License. + +1.8 "Source Code" means the human readable form of a program or other +work that is suitable for making modifications to it, including all +modules it contains, plus any associated interface definition files, +scripts used to control compilation and installation of an executable +(object code). + +1.9 "You" or "Your" means an individual or a legal entity exercising +rights under this License. For legal entities, "You" or "Your" +includes any entity which controls, is controlled by, or is under +common control with, You, where "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of fifty percent +(50%) or more of the outstanding shares or beneficial ownership of +such entity. + +2. Permitted Uses; Conditions & Restrictions. Subject to the terms +and conditions of this License, Apple hereby grants You, effective on +the date You accept this License and download the Original Code, a +world-wide, royalty-free, non-exclusive license, to the extent of +Apple's Applicable Patent Rights and copyrights covering the Original +Code, to do the following: + +2.1 Unmodified Code. You may use, reproduce, display, perform, +internally distribute within Your organization, and Externally Deploy +verbatim, unmodified copies of the Original Code, for commercial or +non-commercial purposes, provided that in each instance: + +(a) You must retain and reproduce in all copies of Original Code the +copyright and other proprietary notices and disclaimers of Apple as +they appear in the Original Code, and keep intact all notices in the +Original Code that refer to this License; and + +(b) You must include a copy of this License with every copy of Source +Code of Covered Code and documentation You distribute or Externally +Deploy, and You may not offer or impose any terms on such Source Code +that alter or restrict this License or the recipients' rights +hereunder, except as permitted under Section 6. + +2.2 Modified Code. You may modify Covered Code and use, reproduce, +display, perform, internally distribute within Your organization, and +Externally Deploy Your Modifications and Covered Code, for commercial +or non-commercial purposes, provided that in each instance You also +meet all of these conditions: + +(a) You must satisfy all the conditions of Section 2.1 with respect to +the Source Code of the Covered Code; + +(b) You must duplicate, to the extent it does not already exist, the +notice in Exhibit A in each file of the Source Code of all Your +Modifications, and cause the modified files to carry prominent notices +stating that You changed the files and the date of any change; and + +(c) If You Externally Deploy Your Modifications, You must make +Source Code of all Your Externally Deployed Modifications either +available to those to whom You have Externally Deployed Your +Modifications, or publicly available. Source Code of Your Externally +Deployed Modifications must be released under the terms set forth in +this License, including the license grants set forth in Section 3 +below, for as long as you Externally Deploy the Covered Code or twelve +(12) months from the date of initial External Deployment, whichever is +longer. You should preferably distribute the Source Code of Your +Externally Deployed Modifications electronically (e.g. download from a +web site). + +2.3 Distribution of Executable Versions. In addition, if You +Externally Deploy Covered Code (Original Code and/or Modifications) in +object code, executable form only, You must include a prominent +notice, in the code itself as well as in related documentation, +stating that Source Code of the Covered Code is available under the +terms of this License with information on how and where to obtain such +Source Code. + +2.4 Third Party Rights. You expressly acknowledge and agree that +although Apple and each Contributor grants the licenses to their +respective portions of the Covered Code set forth herein, no +assurances are provided by Apple or any Contributor that the Covered +Code does not infringe the patent or other intellectual property +rights of any other entity. Apple and each Contributor disclaim any +liability to You for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a +condition to exercising the rights and licenses granted hereunder, You +hereby assume sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow You to distribute the Covered Code, it is +Your responsibility to acquire that license before distributing the +Covered Code. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License, You hereby grant to any +person or entity receiving or distributing Covered Code under this +License a non-exclusive, royalty-free, perpetual, irrevocable license, +under Your Applicable Patent Rights and other intellectual property +rights (other than patent) owned or controlled by You, to use, +reproduce, display, perform, modify, sublicense, distribute and +Externally Deploy Your Modifications of the same scope and extent as +Apple's licenses under Sections 2.1 and 2.2 above. + +4. Larger Works. You may create a Larger Work by combining Covered +Code with other code not governed by the terms of this License and +distribute the Larger Work as a single product. In each such instance, +You must make sure the requirements of this License are fulfilled for +the Covered Code or any portion thereof. + +5. Limitations on Patent License. Except as expressly stated in +Section 2, no other patent rights, express or implied, are granted by +Apple herein. Modifications and/or Larger Works may require additional +patent licenses from Apple which Apple may grant in its sole +discretion. + +6. Additional Terms. You may choose to offer, and to charge a fee for, +warranty, support, indemnity or liability obligations and/or other +rights consistent with the scope of the license granted herein +("Additional Terms") to one or more recipients of Covered Code. +However, You may do so only on Your own behalf and as Your sole +responsibility, and not on behalf of Apple or any Contributor. You +must obtain the recipient's agreement that any such Additional Terms +are offered by You alone, and You hereby agree to indemnify, defend +and hold Apple and every Contributor harmless for any liability +incurred by or claims asserted against Apple or such Contributor by +reason of any such Additional Terms. + +7. Versions of the License. Apple may publish revised and/or new +versions of this License from time to time. Each version will be given +a distinguishing version number. Once Original Code has been published +under a particular version of this License, You may continue to use it +under the terms of that version. You may also choose to use such +Original Code under the terms of any subsequent version of this +License published by Apple. No one other than Apple has the right to +modify the terms applicable to Covered Code created under this +License. + +8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in +part pre-release, untested, or not fully tested works. The Covered +Code may contain errors that could cause failures or loss of data, and +may be incomplete or contain inaccuracies. You expressly acknowledge +and agree that use of the Covered Code, or any portion thereof, is at +Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND +WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND +APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE +PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM +ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF +MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR +PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST +INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE +FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, +THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR +ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO +ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE +AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. +You acknowledge that the Covered Code is not intended for use in the +operation of nuclear facilities, aircraft navigation, communication +systems, or air traffic control machines in which case the failure of +the Covered Code could lead to death, personal injury, or severe +physical or environmental damage. + +9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO +EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING +TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR +ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, +TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF +APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY +REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF +INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY +TO YOU. In no event shall Apple's total liability to You for all +damages (other than as may be required by applicable law) under this +License exceed the amount of fifty dollars ($50.00). + +10. Trademarks. This License does not grant any rights to use the +trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS", +"QuickTime", "QuickTime Streaming Server" or any other trademarks, +service marks, logos or trade names belonging to Apple (collectively +"Apple Marks") or to any trademark, service mark, logo or trade name +belonging to any Contributor. You agree not to use any Apple Marks in +or as part of the name of products derived from the Original Code or +to endorse or promote products derived from the Original Code other +than as expressly permitted by and in strict compliance at all times +with Apple's third party trademark usage guidelines which are posted +at http://www.apple.com/legal/guidelinesfor3rdparties.html. + +11. Ownership. Subject to the licenses granted under this License, +each Contributor retains all rights, title and interest in and to any +Modifications made by such Contributor. Apple retains all rights, +title and interest in and to the Original Code and any Modifications +made by or on behalf of Apple ("Apple Modifications"), and such Apple +Modifications will not be automatically subject to this License. Apple +may, at its sole discretion, choose to license such Apple +Modifications under this License, or on different terms from those +contained in this License or may choose not to license them at all. + +12. Termination. + +12.1 Termination. This License and the rights granted hereunder will +terminate: + +(a) automatically without notice from Apple if You fail to comply with +any term(s) of this License and fail to cure such breach within 30 +days of becoming aware of such breach; + +(b) immediately in the event of the circumstances described in Section +13.5(b); or + +(c) automatically without notice from Apple if You, at any time during +the term of this License, commence an action for patent infringement +against Apple; provided that Apple did not first commence +an action for patent infringement against You in that instance. + +12.2 Effect of Termination. Upon termination, You agree to immediately +stop any further use, reproduction, modification, sublicensing and +distribution of the Covered Code. All sublicenses to the Covered Code +which have been properly granted prior to termination shall survive +any termination of this License. Provisions which, by their nature, +should remain in effect beyond the termination of this License shall +survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, +12.2 and 13. No party will be liable to any other for compensation, +indemnity or damages of any sort solely as a result of terminating +this License in accordance with its terms, and termination of this +License will be without prejudice to any other right or remedy of +any party. + +13. Miscellaneous. + +13.1 Government End Users. The Covered Code is a "commercial item" as +defined in FAR 2.101. Government software and technical data rights in +the Covered Code include only those rights customarily provided to the +public as defined in this License. This customary commercial license +in technical data and software is provided in accordance with FAR +12.211 (Technical Data) and 12.212 (Computer Software) and, for +Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- +Commercial Items) and 227.7202-3 (Rights in Commercial Computer +Software or Computer Software Documentation). Accordingly, all U.S. +Government End Users acquire Covered Code with only those rights set +forth herein. + +13.2 Relationship of Parties. This License will not be construed as +creating an agency, partnership, joint venture or any other form of +legal association between or among You, Apple or any Contributor, and +You will not represent to the contrary, whether expressly, by +implication, appearance or otherwise. + +13.3 Independent Development. Nothing in this License will impair +Apple's right to acquire, license, develop, have others develop for +it, market and/or distribute technology or products that perform the +same or similar functions as, or otherwise compete with, +Modifications, Larger Works, technology or products that You may +develop, produce, market or distribute. + +13.4 Waiver; Construction. Failure by Apple or any Contributor to +enforce any provision of this License will not be deemed a waiver of +future enforcement of that or any other provision. Any law or +regulation which provides that the language of a contract shall be +construed against the drafter will not apply to this License. + +13.5 Severability. (a) If for any reason a court of competent +jurisdiction finds any provision of this License, or portion thereof, +to be unenforceable, that provision of the License will be enforced to +the maximum extent permissible so as to effect the economic benefits +and intent of the parties, and the remainder of this License will +continue in full force and effect. (b) Notwithstanding the foregoing, +if applicable law prohibits or restricts You from fully and/or +specifically complying with Sections 2 and/or 3 or prevents the +enforceability of either of those Sections, this License will +immediately terminate and You must immediately discontinue any use of +the Covered Code and destroy all copies of it that are in your +possession or control. + +13.6 Dispute Resolution. Any litigation or other dispute resolution +between You and Apple relating to this License shall take place in the +Northern District of California, and You and Apple hereby consent to +the personal jurisdiction of, and venue in, the state and federal +courts within that District with respect to this License. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. + +13.7 Entire Agreement; Governing Law. This License constitutes the +entire agreement between the parties with respect to the subject +matter hereof. This License shall be governed by the laws of the +United States and the State of California, except that body of +California law concerning conflicts of law. + +Where You are located in the province of Quebec, Canada, the following +clause applies: The parties hereby confirm that they have requested +that this License and all related documents be drafted in English. Les +parties ont exige que le present contrat et tous les documents +connexes soient rediges en anglais. + +EXHIBIT A. + +"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights +Reserved. + +This file contains Original Code and/or Modifications of Original Code +as defined in and that are subject to the Apple Public Source License +Version 2.0 (the 'License'). You may not use this file except in +compliance with the License. Please obtain a copy of the License at +http://www.opensource.apple.com/apsl/ and read it before using this +file. + +The Original Code and all software distributed under the License are +distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +Please see the License for the specific language governing rights and +limitations under the License." diff --git a/Makefile b/Makefile deleted file mode 100644 index 1e2e8c8..0000000 --- a/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# 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 diff --git a/Makefile.postamble b/Makefile.postamble deleted file mode 100644 index 8198896..0000000 --- a/Makefile.postamble +++ /dev/null @@ -1,105 +0,0 @@ -############################################################################### -# 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 diff --git a/Makefile.preamble b/Makefile.preamble deleted file mode 100644 index 480f47f..0000000 --- a/Makefile.preamble +++ /dev/null @@ -1,138 +0,0 @@ -############################################################################### -# 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: <> -# 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 diff --git a/PB.project b/PB.project deleted file mode 100644 index 2890710..0000000 --- a/PB.project +++ /dev/null @@ -1,30 +0,0 @@ -{ - "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"; -} diff --git a/Plugins/ATconfig/Info.plist b/Plugins/ATconfig/Info.plist new file mode 100644 index 0000000..048a8f9 --- /dev/null +++ b/Plugins/ATconfig/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ATconfig + CFBundleIdentifier + com.apple.SystemConfiguration.ATconfig + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Requires + + com.apple.SystemConfiguration.InterfaceNamer + com.apple.SystemConfiguration.KernelEventMonitor + com.apple.SystemConfiguration.PreferencesMonitor + + + diff --git a/Plugins/ATconfig/atconfig.c b/Plugins/ATconfig/atconfig.c new file mode 100644 index 0000000..7bf129e --- /dev/null +++ b/Plugins/ATconfig/atconfig.c @@ -0,0 +1,1570 @@ +/* + * 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 + * - startup/shutdown AT networking without Kicker's help and + * publish the state information after the configuration is + * active. + * + * April 29, 2002 Allan Nathanson + * - add global state information (primary service, interface) + * + * June 24, 2001 Allan Nathanson + * - update to public SystemConfiguration.framework APIs + * + * July 7, 2000 Allan Nathanson + * - initial revision + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 +#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 diff --git a/Plugins/ATconfig/cfManager.c b/Plugins/ATconfig/cfManager.c new file mode 100644 index 0000000..73bcd59 --- /dev/null +++ b/Plugins/ATconfig/cfManager.c @@ -0,0 +1,260 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +#include +#include + +#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 */ diff --git a/Plugins/ATconfig/cfManager.h b/Plugins/ATconfig/cfManager.h new file mode 100644 index 0000000..373c371 --- /dev/null +++ b/Plugins/ATconfig/cfManager.h @@ -0,0 +1,52 @@ +/* + * 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 + * - initial revision + */ + +#ifndef __CFMANAGER_H +#define __CFMANAGER_H + +#include +#include + + +__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 */ diff --git a/Plugins/IPMonitor/Info.plist b/Plugins/IPMonitor/Info.plist new file mode 100644 index 0000000..bb883e4 --- /dev/null +++ b/Plugins/IPMonitor/Info.plist @@ -0,0 +1,31 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + IPMonitor + CFBundleIdentifier + com.apple.SystemConfiguration.IPMonitor + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Requires + + com.apple.SystemConfiguration.IPConfiguration + com.apple.SystemConfiguration.PreferencesMonitor + + Builtin + + + diff --git a/Plugins/IPMonitor/Resolvers.plist b/Plugins/IPMonitor/Resolvers.plist new file mode 100644 index 0000000..c59cf4d --- /dev/null +++ b/Plugins/IPMonitor/Resolvers.plist @@ -0,0 +1,25 @@ + + + + + + Options + attempts:4 + ServerAddresses + + 224.0.0.251 + ff02::fb + + ServerPort + 5353 + ServerTimeout + 2 + SupplementalMatchDomains + + local + 254.169.in-addr.arpa + 0.8.e.f.ip6.arpa + + + + diff --git a/Plugins/IPMonitor/dns-configuration.c b/Plugins/IPMonitor/dns-configuration.c new file mode 100644 index 0000000..bcbae5a --- /dev/null +++ b/Plugins/IPMonitor/dns-configuration.c @@ -0,0 +1,776 @@ +/* + * 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 + * - initial revision + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +/* 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; +} + diff --git a/Plugins/IPMonitor/ip_plugin.c b/Plugins/IPMonitor/ip_plugin.c new file mode 100644 index 0000000..8603a74 --- /dev/null +++ b/Plugins/IPMonitor/ip_plugin.c @@ -0,0 +1,2409 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* for SCLog() */ + +#include + +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(""), + 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 + diff --git a/Plugins/IPMonitor/set-hostname.c b/Plugins/IPMonitor/set-hostname.c new file mode 100644 index 0000000..b5408f9 --- /dev/null +++ b/Plugins/IPMonitor/set-hostname.c @@ -0,0 +1,932 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include // for SCLog(), SCPrint() + +#include + + +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 */ diff --git a/Plugins/InterfaceNamer/Info.plist b/Plugins/InterfaceNamer/Info.plist new file mode 100644 index 0000000..69db34e --- /dev/null +++ b/Plugins/InterfaceNamer/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + InterfaceNamer + CFBundleIdentifier + com.apple.SystemConfiguration.InterfaceNamer + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Builtin + + + diff --git a/Plugins/InterfaceNamer/ifnamer.c b/Plugins/InterfaceNamer/ifnamer.c new file mode 100644 index 0000000..a0a9620 --- /dev/null +++ b/Plugins/InterfaceNamer/ifnamer.c @@ -0,0 +1,1432 @@ +/* + * 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 + * - 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 + * - update to public SystemConfiguration.framework APIs + * + * January 23, 2001 Dieter Siegmund + * - 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include // for SCLog(), SCPrint() +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#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 */ diff --git a/Plugins/KernelEventMonitor/Info.plist b/Plugins/KernelEventMonitor/Info.plist new file mode 100644 index 0000000..0a9b667 --- /dev/null +++ b/Plugins/KernelEventMonitor/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + KernelEventMonitor + CFBundleIdentifier + com.apple.SystemConfiguration.KernelEventMonitor + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Requires + + com.apple.SystemConfiguration.InterfaceNamer + + Builtin + + + diff --git a/Plugins/KernelEventMonitor/ev_appletalk.c b/Plugins/KernelEventMonitor/ev_appletalk.c new file mode 100644 index 0000000..cbcfd2e --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_appletalk.c @@ -0,0 +1,400 @@ +/* + * 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 + * - split code out from eventmon.c + */ + +#include "eventmon.h" +#include "cache.h" +#include "ev_appletalk.h" + +// from +#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; +} diff --git a/Plugins/KernelEventMonitor/ev_appletalk.h b/Plugins/KernelEventMonitor/ev_appletalk.h new file mode 100644 index 0000000..bb48ef4 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_appletalk.h @@ -0,0 +1,48 @@ +/* + * 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 + * - split code out from eventmon.c + */ + + +#ifndef _EV_APPLETALK_H +#define _EV_APPLETALK_H + +#include +#include + +__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 */ + diff --git a/Plugins/KernelEventMonitor/ev_dlil.c b/Plugins/KernelEventMonitor/ev_dlil.c new file mode 100644 index 0000000..516fe99 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_dlil.c @@ -0,0 +1,291 @@ +/* + * 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 + * - 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; +} diff --git a/Plugins/KernelEventMonitor/ev_dlil.h b/Plugins/KernelEventMonitor/ev_dlil.h new file mode 100644 index 0000000..6ab9a80 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_dlil.h @@ -0,0 +1,45 @@ +/* + * 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 + * - 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 */ + diff --git a/Plugins/KernelEventMonitor/ev_ipv4.c b/Plugins/KernelEventMonitor/ev_ipv4.c new file mode 100644 index 0000000..c8071e7 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_ipv4.c @@ -0,0 +1,256 @@ +/* + * 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 + * - 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; +} diff --git a/Plugins/KernelEventMonitor/ev_ipv4.h b/Plugins/KernelEventMonitor/ev_ipv4.h new file mode 100644 index 0000000..8a38843 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_ipv4.h @@ -0,0 +1,46 @@ +/* + * 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 + * - split code out from eventmon.c + */ + + +#ifndef _EV_IPV4_H +#define _EV_IPV4_H + +#include + +__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 */ + diff --git a/Plugins/KernelEventMonitor/ev_ipv6.c b/Plugins/KernelEventMonitor/ev_ipv6.c new file mode 100644 index 0000000..47705c4 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_ipv6.c @@ -0,0 +1,407 @@ +/* + * 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 + * - 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; +} diff --git a/Plugins/KernelEventMonitor/ev_ipv6.h b/Plugins/KernelEventMonitor/ev_ipv6.h new file mode 100644 index 0000000..24113d5 --- /dev/null +++ b/Plugins/KernelEventMonitor/ev_ipv6.h @@ -0,0 +1,44 @@ +/* + * 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 + * - initial revision + */ + + +#ifndef _EV_IPV6_H +#define _EV_IPV6_H + +#include + +__BEGIN_DECLS + +void interface_update_ipv6 (struct ifaddrs *ifap, const char *if_name); + +__END_DECLS + +#endif /* _EV_IPV6_H */ + diff --git a/Plugins/KernelEventMonitor/eventmon.c b/Plugins/KernelEventMonitor/eventmon.c new file mode 100644 index 0000000..24946f3 --- /dev/null +++ b/Plugins/KernelEventMonitor/eventmon.c @@ -0,0 +1,727 @@ +/* + * 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 + * - 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 + * - added support for KEV_INET6_xxx events + * + * January 6, 2002 Jessica Vazquez + * - added handling for KEV_ATALK_xxx events + * + * July 2, 2001 Dieter Siegmund + * - 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 + * - update to public SystemConfiguration.framework APIs + * + * May 17, 2001 Allan Nathanson + * - add/maintain per-interface address/netmask/destaddr information + * in the dynamic store. + * + * June 30, 2000 Allan Nathanson + * - 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 diff --git a/Plugins/KernelEventMonitor/eventmon.h b/Plugins/KernelEventMonitor/eventmon.h new file mode 100644 index 0000000..ed6054c --- /dev/null +++ b/Plugins/KernelEventMonitor/eventmon.h @@ -0,0 +1,70 @@ +/* + * 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 + * - split code out from eventmon.c + */ + + +#ifndef _EVENTMON_H +#define _EVENTMON_H + +#include +#include +#include +#define KERNEL_PRIVATE +#include +#undef KERNEL_PRIVATE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern SCDynamicStoreRef store; +extern Boolean _verbose; + + +__BEGIN_DECLS + +int dgram_socket (int domain); + +__END_DECLS + +#endif /* _EVENTMON_H */ + diff --git a/Plugins/Kicker/Info.plist b/Plugins/Kicker/Info.plist new file mode 100644 index 0000000..d692f89 --- /dev/null +++ b/Plugins/Kicker/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Kicker + CFBundleIdentifier + com.apple.SystemConfiguration.Kicker + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Requires + + com.apple.SystemConfiguration.ATconfig + com.apple.SystemConfiguration.IPConfiguration + com.apple.SystemConfiguration.IPMonitor + + Builtin + + + diff --git a/Plugins/Kicker/Kicker.xml b/Plugins/Kicker/Kicker.xml new file mode 100644 index 0000000..182a9aa --- /dev/null +++ b/Plugins/Kicker/Kicker.xml @@ -0,0 +1,43 @@ + + + + + + execCommand + $BUNDLE/Contents/Resources/enable-network + execUID + 0 + keys + + State:/Network/Global/IPv4 + + name + enable-network + + + keys + + State:/Network/Global/DNS + State:/Network/Global/IPv4 + State:/Network/Global/IPv6 + State:/Network/Global/NetInfo + + name + network_change + postName + com.apple.system.config.network_change + + + execCommand + /usr/sbin/AppleFileServer + execUID + 0 + keys + + daemon:AppleFileServer + + name + AppleFileServer + + + diff --git a/Plugins/Kicker/enable-network b/Plugins/Kicker/enable-network new file mode 100755 index 0000000..b68cc8d --- /dev/null +++ b/Plugins/Kicker/enable-network @@ -0,0 +1,15 @@ +#!/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 diff --git a/Plugins/Kicker/kicker.c b/Plugins/Kicker/kicker.c new file mode 100644 index 0000000..efc49aa --- /dev/null +++ b/Plugins/Kicker/kicker.c @@ -0,0 +1,537 @@ +/* + * 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 + * - updated to use _SCDPluginExecCommand() + * + * June 23, 2001 Allan Nathanson + * - updated to public SystemConfiguration.framework APIs + * + * June 4, 2001 Allan Nathanson + * - add changed keys as the arguments to the kicker script + * + * June 30, 2000 Allan Nathanson + * - initial revision + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include // for SCLog() +#include +#include + +/* + * 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 diff --git a/Plugins/LinkConfiguration/Info.plist b/Plugins/LinkConfiguration/Info.plist new file mode 100644 index 0000000..4907af2 --- /dev/null +++ b/Plugins/LinkConfiguration/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + LinkConfiguration + CFBundleIdentifier + com.apple.SystemConfiguration.LinkConfiguration + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Requires + + com.apple.SystemConfiguration.InterfaceNamer + + Builtin + + + diff --git a/Plugins/LinkConfiguration/linkconfig.c b/Plugins/LinkConfiguration/linkconfig.c new file mode 100644 index 0000000..75d7262 --- /dev/null +++ b/Plugins/LinkConfiguration/linkconfig.c @@ -0,0 +1,512 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +//#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include // 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 diff --git a/Plugins/PreferencesMonitor/Info.plist b/Plugins/PreferencesMonitor/Info.plist new file mode 100644 index 0000000..0c1b578 --- /dev/null +++ b/Plugins/PreferencesMonitor/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + PreferencesMonitor + CFBundleIdentifier + com.apple.SystemConfiguration.PreferencesMonitor + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 0.0.1d1 + Builtin + + + diff --git a/Plugins/PreferencesMonitor/prefsmon.c b/Plugins/PreferencesMonitor/prefsmon.c new file mode 100644 index 0000000..9071ef7 --- /dev/null +++ b/Plugins/PreferencesMonitor/prefsmon.c @@ -0,0 +1,495 @@ +/* + * 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 + * - use SCPreference notification APIs + * + * June 24, 2001 Allan Nathanson + * - update to public SystemConfiguration.framework APIs + * + * November 10, 2000 Allan Nathanson + * - initial revision + */ + + +#include +#include +#include +#include + + +#include +#include +#include + + +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 diff --git a/Plugins/common/cache.c b/Plugins/common/cache.c new file mode 100644 index 0000000..04415d6 --- /dev/null +++ b/Plugins/common/cache.c @@ -0,0 +1,183 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +#include // 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; +} diff --git a/Plugins/common/cache.h b/Plugins/common/cache.h new file mode 100644 index 0000000..c2847f4 --- /dev/null +++ b/Plugins/common/cache.h @@ -0,0 +1,63 @@ +/* + * 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 + * - initial revision + */ + + +#ifndef _CACHE_H +#define _CACHE_H + + +#include +#include + + +__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 */ diff --git a/SystemConfiguration.fproj/BondConfiguration.c b/SystemConfiguration.fproj/BondConfiguration.c new file mode 100644 index 0000000..5343842 --- /dev/null +++ b/SystemConfiguration.fproj/BondConfiguration.c @@ -0,0 +1,2050 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#define KERNEL_PRIVATE +#include +#include +#undef KERNEL_PRIVATE +#include +#include +#include +#include + +/* ---------- 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(" {"), 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(" {"), 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(" {"), 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); +} diff --git a/SystemConfiguration.fproj/BondConfiguration.h b/SystemConfiguration.fproj/BondConfiguration.h new file mode 100644 index 0000000..f634ed7 --- /dev/null +++ b/SystemConfiguration.fproj/BondConfiguration.h @@ -0,0 +1,146 @@ +/* + * 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 +#include +#include + + +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 */ diff --git a/SystemConfiguration.fproj/BondConfigurationPrivate.h b/SystemConfiguration.fproj/BondConfigurationPrivate.h new file mode 100644 index 0000000..4e6d4d5 --- /dev/null +++ b/SystemConfiguration.fproj/BondConfigurationPrivate.h @@ -0,0 +1,52 @@ +/* + * 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 +#include + +#include + + +/*! + @header BONDConfigurationPrivate + */ + + +#define BOND_PREFERENCES_ID CFSTR("VirtualNetworkInterfaces.plist") + + +__BEGIN_DECLS + +CFArrayRef +_BondPreferencesCopyActiveInterfaces (); + +Boolean +_BondPreferencesUpdateConfiguration (BondPreferencesRef prefs); + +__END_DECLS + +#endif /* _BONDCONFIGURATIONPRIVATE_H */ diff --git a/SystemConfiguration.fproj/CustomInfo.plist b/SystemConfiguration.fproj/CustomInfo.plist deleted file mode 100644 index b2deea5..0000000 --- a/SystemConfiguration.fproj/CustomInfo.plist +++ /dev/null @@ -1,5 +0,0 @@ -{ - CFBundleName = "SystemConfiguration"; - CFBundleIdentifier = "com.apple.SystemConfiguration"; - CFBundleShortVersionString = "1.7.1"; -} diff --git a/SystemConfiguration.fproj/DHCP.c b/SystemConfiguration.fproj/DHCP.c index 7b6d1d7..2adc194 100644 --- a/SystemConfiguration.fproj/DHCP.c +++ b/SystemConfiguration.fproj/DHCP.c @@ -106,7 +106,7 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID, { CFMutableDictionaryRef dict = NULL; CFStringRef path = NULL; - SCPreferencesRef session = NULL; + SCPreferencesRef prefs = NULL; Boolean success = FALSE; if (applicationID == NULL) { @@ -116,12 +116,12 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID, 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, @@ -165,19 +165,19 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID, 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); @@ -196,7 +196,7 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID, UInt8 * options = NULL; CFArrayRef parms; CFStringRef path = NULL; - SCPreferencesRef session = NULL; + SCPreferencesRef prefs = NULL; if (applicationID == NULL) { goto done; @@ -205,12 +205,12 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID, 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; } @@ -222,8 +222,8 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID, options = S_get_char_array(parms, count); done: - if (session) { - CFRelease(session); + if (prefs) { + CFRelease(prefs); } if (path) { CFRelease(path); diff --git a/SystemConfiguration.fproj/DHCPClientPreferences.h b/SystemConfiguration.fproj/DHCPClientPreferences.h index 7ba074a..5e0d005 100644 --- a/SystemConfiguration.fproj/DHCPClientPreferences.h +++ b/SystemConfiguration.fproj/DHCPClientPreferences.h @@ -28,7 +28,9 @@ #include /*! - @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 @@ -36,15 +38,15 @@ __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 @@ -55,14 +57,14 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID, /*! @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 * diff --git a/SystemConfiguration.fproj/DeviceOnHold.c b/SystemConfiguration.fproj/DeviceOnHold.c index 0ee06ce..b904d0f 100644 --- a/SystemConfiguration.fproj/DeviceOnHold.c +++ b/SystemConfiguration.fproj/DeviceOnHold.c @@ -82,8 +82,6 @@ __DeviceOnHoldDeallocate(CFTypeRef cf) { DeviceOnHoldPrivateRef DeviceOnHoldPrivate = (DeviceOnHoldPrivateRef)cf; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__DeviceOnHoldDeallocate:")); - /* release resources */ if (DeviceOnHoldPrivate->name) CFRelease(DeviceOnHoldPrivate->name); if (DeviceOnHoldPrivate->sock != -1) { @@ -167,27 +165,29 @@ IsDeviceOnHoldSupported(CFStringRef deviceName, // "modem" 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)) { @@ -220,10 +220,6 @@ IsDeviceOnHoldSupported(CFStringRef deviceName, // "modem" // to know the exact driver they are searching for. return result; - - errorExit: - - return FALSE; } @@ -235,7 +231,7 @@ DeviceOnHoldCreate(CFAllocatorRef allocator, DeviceOnHoldPrivateRef devicePrivate; int status; - if (CFStringCompare(deviceName, CFSTR("modem"), NULL) != kCFCompareEqualTo) { + if (CFStringCompare(deviceName, CFSTR("modem"), 0) != kCFCompareEqualTo) { return NULL; } diff --git a/SystemConfiguration.fproj/DeviceOnHold.h b/SystemConfiguration.fproj/DeviceOnHold.h index 7cd4902..0d88c53 100644 --- a/SystemConfiguration.fproj/DeviceOnHold.h +++ b/SystemConfiguration.fproj/DeviceOnHold.h @@ -29,6 +29,11 @@ #include +/*! + @header DeviceOnHold + */ + + /*! @enum @discussion Returned status codes from DeviceOnHoldGetStatus() diff --git a/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings b/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings new file mode 100644 index 0000000..66ff790 Binary files /dev/null and b/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings differ diff --git a/SystemConfiguration.fproj/Info.plist b/SystemConfiguration.fproj/Info.plist new file mode 100644 index 0000000..65f8955 --- /dev/null +++ b/SystemConfiguration.fproj/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + SystemConfiguration + CFBundleGetInfoString + 1.8.0 + CFBundleIdentifier + com.apple.SystemConfiguration + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SystemConfiguration + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.8.0 + CFBundleSignature + ???? + CFBundleVersion + 1.8.0 + + diff --git a/SystemConfiguration.fproj/LinkConfiguration.c b/SystemConfiguration.fproj/LinkConfiguration.c index b88db0e..202e650 100644 --- a/SystemConfiguration.fproj/LinkConfiguration.c +++ b/SystemConfiguration.fproj/LinkConfiguration.c @@ -445,11 +445,18 @@ __getMTULimits(char ifr_name[IFNAMSIZ], 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' */ @@ -531,7 +538,7 @@ NetworkInterfaceCopyMTU(CFStringRef interface, 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; } @@ -552,38 +559,22 @@ NetworkInterfaceCopyMTU(CFStringRef interface, /* 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; diff --git a/SystemConfiguration.fproj/LinkConfiguration.h b/SystemConfiguration.fproj/LinkConfiguration.h index f33f8c7..cb598fd 100644 --- a/SystemConfiguration.fproj/LinkConfiguration.h +++ b/SystemConfiguration.fproj/LinkConfiguration.h @@ -28,6 +28,9 @@ #include #include +/*! + @header LinkConfiguration +*/ __BEGIN_DECLS diff --git a/SystemConfiguration.fproj/Makefile b/SystemConfiguration.fproj/Makefile index 1b406d4..dad23e6 100644 --- a/SystemConfiguration.fproj/Makefile +++ b/SystemConfiguration.fproj/Makefile @@ -1,99 +1,14 @@ # -# 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 diff --git a/SystemConfiguration.fproj/Makefile.postamble b/SystemConfiguration.fproj/Makefile.postamble deleted file mode 100644 index 6b3aedf..0000000 --- a/SystemConfiguration.fproj/Makefile.postamble +++ /dev/null @@ -1,127 +0,0 @@ -############################################################################### -# 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 diff --git a/SystemConfiguration.fproj/Makefile.preamble b/SystemConfiguration.fproj/Makefile.preamble deleted file mode 100644 index ac111af..0000000 --- a/SystemConfiguration.fproj/Makefile.preamble +++ /dev/null @@ -1,177 +0,0 @@ -############################################################################### -# 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: <> -# 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 diff --git a/SystemConfiguration.fproj/NetworkConfiguration.plist b/SystemConfiguration.fproj/NetworkConfiguration.plist new file mode 100644 index 0000000..a56f100 --- /dev/null +++ b/SystemConfiguration.fproj/NetworkConfiguration.plist @@ -0,0 +1,407 @@ + + + + + Interface + + 6to4-IPv4 + + Bluetooth + + Bond + + Ethernet + + FireWire + + IEEE80211 + + IrDA + + L2TP-IPv4 + + Modem + + ConnectionScript + Apple Internal 56K Modem (v.92) + DataCompression + 1 + DialMode + WaitForDialTone + ErrorCorrection + 1 + HoldCallWaitingAudibleAlert + 1 + HoldDisconnectOnAnswer + 0 + HoldEnabled + 0 + HoldReminder + 1 + HoldReminderTime + 10 + PulseDial + 0 + Speaker + 1 + + PPP-Bluetooth + + PPP-Ethernet + + ACSPEnabled + 0 + CommDisplayTerminalWindow + 0 + CommRedialCount + 1 + CommRedialEnabled + 1 + CommRedialInterval + 5 + CommUseTerminalScript + 0 + DialOnDemand + 0 + DisconnectOnIdle + 0 + DisconnectOnIdleTimer + 1800 + DisconnectOnLogout + 1 + DisconnectOnSleep + 1 + IPCPCompressionVJ + 1 + IdleReminder + 0 + IdleReminderTimer + 1800 + LCPEchoEnabled + 1 + LCPEchoFailure + 4 + LCPEchoInterval + 10 + Logfile + /var/log/ppp.log + VerboseLogging + 0 + + PPP-IrDA + + PPP-L2TP + + PPP-Modem + + ACSPEnabled + 0 + CommDisplayTerminalWindow + 0 + CommRedialCount + 1 + CommRedialEnabled + 1 + CommRedialInterval + 5 + CommUseTerminalScript + 0 + DialOnDemand + 0 + DisconnectOnIdle + 1 + DisconnectOnIdleTimer + 600 + DisconnectOnLogout + 1 + DisconnectOnSleep + 1 + IPCPCompressionVJ + 1 + IdleReminder + 0 + IdleReminderTimer + 1800 + LCPEchoEnabled + 1 + LCPEchoFailure + 4 + LCPEchoInterval + 10 + Logfile + /var/log/ppp.log + VerboseLogging + 0 + + PPP-PPTP + + PPP-Serial + + PPTP-IPv4 + + Serial + + VLAN + + + Protocol + + 6to4-IPv4 + + IPv6 + + ConfigMethod + 6to4 + + + Bond + + DNS + + IPv4 + + ConfigMethod + DHCP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + Ethernet + + AppleTalk + + ConfigMethod + Node + + DNS + + IPv4 + + ConfigMethod + DHCP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + FireWire + + DNS + + IPv4 + + ConfigMethod + DHCP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + IEEE80211 + + AppleTalk + + DNS + + IPv4 + + ConfigMethod + DHCP + + IPv6 + + Proxies + + FTPPassive + 1 + + + PPP-Bluetooth + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPP-Ethernet + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPP-IrDA + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPP-L2TP + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPP-Modem + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPP-PPTP + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPP-Serial + + DNS + + IPv4 + + ConfigMethod + PPP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + PPTP-IPv4 + + PPTP-L2TP + + VLAN + + DNS + + IPv4 + + ConfigMethod + DHCP + + IPv6 + + ConfigMethod + Automatic + + Proxies + + FTPPassive + 1 + + + + + diff --git a/SystemConfiguration.fproj/PB.project b/SystemConfiguration.fproj/PB.project deleted file mode 100644 index 3d2e5a7..0000000 --- a/SystemConfiguration.fproj/PB.project +++ /dev/null @@ -1,165 +0,0 @@ -{ - "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"; -} diff --git a/SystemConfiguration.fproj/SCD.c b/SystemConfiguration.fproj/SCD.c index 50c0f86..188bfaa 100644 --- a/SystemConfiguration.fproj/SCD.c +++ b/SystemConfiguration.fproj/SCD.c @@ -475,7 +475,7 @@ typedef struct { static pthread_once_t tsKeyInitialized = PTHREAD_ONCE_INIT; -static pthread_key_t tsDataKey = NULL; +static pthread_key_t tsDataKey; static void diff --git a/SystemConfiguration.fproj/SCDAdd.c b/SystemConfiguration.fproj/SCDAdd.c index 00503ab..0e12fbb 100644 --- a/SystemConfiguration.fproj/SCDAdd.c +++ b/SystemConfiguration.fproj/SCDAdd.c @@ -40,7 +40,7 @@ #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; @@ -53,13 +53,77 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR 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; @@ -98,8 +162,10 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR 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); diff --git a/SystemConfiguration.fproj/SCDAddSession.c b/SystemConfiguration.fproj/SCDAddSession.c deleted file mode 100644 index 7957db1..0000000 --- a/SystemConfiguration.fproj/SCDAddSession.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 - * - public API conversion - * - * October 17, 2000 Allan Nathanson - * - initial revision - */ - -#include -#include - -#include -#include -#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; -} diff --git a/SystemConfiguration.fproj/SCDConsoleUser.c b/SystemConfiguration.fproj/SCDConsoleUser.c index ad97b87..6fc7bc6 100644 --- a/SystemConfiguration.fproj/SCDConsoleUser.c +++ b/SystemConfiguration.fproj/SCDConsoleUser.c @@ -56,11 +56,19 @@ #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 @@ -84,13 +92,12 @@ SCDynamicStoreCopyConsoleUser(SCDynamicStoreRef store, 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; @@ -153,13 +160,12 @@ SCDynamicStoreCopyConsoleInformation(SCDynamicStoreRef store) 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; @@ -200,24 +206,22 @@ SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef store, 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; } @@ -226,19 +230,25 @@ SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef store, &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); @@ -264,20 +274,19 @@ SCDynamicStoreSetConsoleUser(SCDynamicStoreRef store, 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; } diff --git a/SystemConfiguration.fproj/SCDGet.c b/SystemConfiguration.fproj/SCDGet.c index 1d566af..dcc82a1 100644 --- a/SystemConfiguration.fproj/SCDGet.c +++ b/SystemConfiguration.fproj/SCDGet.c @@ -59,13 +59,7 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, 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; @@ -108,8 +102,10 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, 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); @@ -118,10 +114,12 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, 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; } @@ -135,8 +133,6 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, expDict = _SCUnserializeMultiple(dict); CFRelease(dict); - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), expDict); - return expDict; } @@ -155,12 +151,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) 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; @@ -190,8 +181,10 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) 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); @@ -200,10 +193,12 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) 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; } @@ -214,7 +209,5 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key) return NULL; } - SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" value = %@"), data); - return data; } diff --git a/SystemConfiguration.fproj/SCDHostName.c b/SystemConfiguration.fproj/SCDHostName.c index 7bd5fe1..5d6fc59 100644 --- a/SystemConfiguration.fproj/SCDHostName.c +++ b/SystemConfiguration.fproj/SCDHostName.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -49,18 +49,17 @@ CFStringRef 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; @@ -69,7 +68,7 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef store, key = SCDynamicStoreKeyCreateComputerName(NULL); dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); - if (!dict) { + if (dict == NULL) { goto done; } if (!isA_CFDictionary(dict)) { @@ -78,13 +77,13 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef store, } 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, @@ -99,21 +98,21 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef store, 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); @@ -126,8 +125,8 @@ SCPreferencesSetComputerName(SCPreferencesRef session, kSCPrefSystem, kSCCompSystem); - dict = SCPreferencesPathGetValue(session, path); - if (dict) { + dict = SCPreferencesPathGetValue(prefs, path); + if (dict != NULL) { newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); } else { newDict = CFDictionaryCreateMutable(NULL, @@ -142,13 +141,103 @@ SCPreferencesSetComputerName(SCPreferencesRef session, 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; } @@ -168,18 +257,17 @@ SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator) 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; @@ -188,7 +276,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store) key = SCDynamicStoreKeyCreateHostNames(NULL); dict = SCDynamicStoreCopyValue(store, key); CFRelease(key); - if (!dict) { + if (dict == NULL) { goto done; } if (!isA_CFDictionary(dict)) { @@ -197,7 +285,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store) } name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName)); - if (!name) { + if (name == NULL) { _SCErrorSet(kSCStatusNoKey); goto done; } @@ -206,7 +294,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store) done : if (tempSession) CFRelease(store); - if (dict) CFRelease(dict); + if (dict != NULL) CFRelease(dict); return name; } @@ -275,21 +363,21 @@ _SC_CFStringIsValidDNSName(CFStringRef 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)) { @@ -320,8 +408,8 @@ SCPreferencesSetLocalHostName(SCPreferencesRef session, kSCCompNetwork, kSCCompHostNames); - dict = SCPreferencesPathGetValue(session, path); - if (dict) { + dict = SCPreferencesPathGetValue(prefs, path); + if (dict != NULL) { newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); } else { newDict = CFDictionaryCreateMutable(NULL, @@ -330,26 +418,20 @@ SCPreferencesSetLocalHostName(SCPreferencesRef session, &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; } diff --git a/SystemConfiguration.fproj/SCDList.c b/SystemConfiguration.fproj/SCDList.c index 4ab3068..406f859 100644 --- a/SystemConfiguration.fproj/SCDList.c +++ b/SystemConfiguration.fproj/SCDList.c @@ -52,12 +52,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) 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; @@ -87,8 +82,10 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) 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); @@ -97,10 +94,12 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern) 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; } diff --git a/SystemConfiguration.fproj/SCDLock.c b/SystemConfiguration.fproj/SCDLock.c index c478dc8..8279699 100644 --- a/SystemConfiguration.fproj/SCDLock.c +++ b/SystemConfiguration.fproj/SCDLock.c @@ -46,9 +46,7 @@ SCDynamicStoreLock(SCDynamicStoreRef store) 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; @@ -64,8 +62,10 @@ SCDynamicStoreLock(SCDynamicStoreRef store) 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); diff --git a/SystemConfiguration.fproj/SCDNotifierAdd.c b/SystemConfiguration.fproj/SCDNotifierAdd.c index 85c2969..04a17df 100644 --- a/SystemConfiguration.fproj/SCDNotifierAdd.c +++ b/SystemConfiguration.fproj/SCDNotifierAdd.c @@ -49,13 +49,7 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is 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; @@ -84,8 +78,10 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is 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); diff --git a/SystemConfiguration.fproj/SCDNotifierCancel.c b/SystemConfiguration.fproj/SCDNotifierCancel.c index 41613e0..b3f139b 100644 --- a/SystemConfiguration.fproj/SCDNotifierCancel.c +++ b/SystemConfiguration.fproj/SCDNotifierCancel.c @@ -46,9 +46,7 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) 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; @@ -68,17 +66,12 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) 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; @@ -96,8 +89,10 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) 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); diff --git a/SystemConfiguration.fproj/SCDNotifierGetChanges.c b/SystemConfiguration.fproj/SCDNotifierGetChanges.c index 8711312..6684826 100644 --- a/SystemConfiguration.fproj/SCDNotifierGetChanges.c +++ b/SystemConfiguration.fproj/SCDNotifierGetChanges.c @@ -49,9 +49,7 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store) 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; @@ -69,8 +67,10 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store) (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); @@ -79,10 +79,12 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store) 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; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c index f5cac08..d64572b 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaCallback.c @@ -51,19 +51,27 @@ informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) 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 */ } } @@ -73,13 +81,10 @@ informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) } #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); @@ -113,9 +118,7 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef store, , NULL }; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback:")); - - if (!store) { + if (store == NULL) { /* sorry, you must provide a session */ _SCErrorSet(kSCStatusNoStoreSession); return FALSE; @@ -149,16 +152,18 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef store, 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, @@ -167,8 +172,10 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef store, (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); @@ -186,15 +193,10 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef store, 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; } @@ -210,7 +212,9 @@ rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) 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) { @@ -218,10 +222,10 @@ rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) } #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); @@ -242,7 +246,9 @@ rlsPortInvalidate(CFMachPortRef mp, void *info) { 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); } @@ -253,7 +259,9 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) 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 @@ -267,22 +275,23 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) 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; } @@ -296,19 +305,23 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) 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); @@ -318,11 +331,11 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) 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; @@ -335,36 +348,43 @@ rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode) 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; @@ -385,14 +405,20 @@ rlsPerform(void *info) 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) { @@ -407,6 +433,8 @@ rlsPerform(void *info) context_release(context_info); } + done : + CFRelease(changedKeys); return; } @@ -453,9 +481,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef allocator, { 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; @@ -478,7 +504,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef allocator, return NULL; } - if (storePrivate->rls) { + if (storePrivate->rls != NULL) { CFRetain(storePrivate->rls); } else { CFRunLoopSourceContext context = { 0 // version @@ -496,7 +522,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef allocator, storePrivate->rls = CFRunLoopSourceCreate(allocator, order, &context); } - if (!storePrivate->rls) { + if (storePrivate->rls == NULL) { _SCErrorSet(kSCStatusFailed); return NULL; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaFD.c b/SystemConfiguration.fproj/SCDNotifierInformViaFD.c index 7aec221..6e3521e 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaFD.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaFD.c @@ -56,9 +56,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, 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; @@ -78,7 +76,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, 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; } @@ -94,14 +92,14 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, 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; } @@ -113,8 +111,10 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, (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); @@ -124,7 +124,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, *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; } diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c b/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c index bef3896..10b4aa0 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c @@ -47,9 +47,7 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, 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; @@ -70,18 +68,17 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, /* 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); @@ -97,16 +94,18 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, 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, @@ -114,8 +113,10 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, (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); diff --git a/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c b/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c index 4356c6e..96464a1 100644 --- a/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c +++ b/SystemConfiguration.fproj/SCDNotifierInformViaSignal.c @@ -47,11 +47,7 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) 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; @@ -71,7 +67,7 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) 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; } @@ -79,8 +75,10 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) 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); diff --git a/SystemConfiguration.fproj/SCDNotifierRemove.c b/SystemConfiguration.fproj/SCDNotifierRemove.c index 06f81b9..5278a57 100644 --- a/SystemConfiguration.fproj/SCDNotifierRemove.c +++ b/SystemConfiguration.fproj/SCDNotifierRemove.c @@ -49,13 +49,7 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean 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; @@ -84,8 +78,10 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean 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); diff --git a/SystemConfiguration.fproj/SCDNotifierSetKeys.c b/SystemConfiguration.fproj/SCDNotifierSetKeys.c index c9eb908..ad5626d 100644 --- a/SystemConfiguration.fproj/SCDNotifierSetKeys.c +++ b/SystemConfiguration.fproj/SCDNotifierSetKeys.c @@ -52,13 +52,7 @@ SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, 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; @@ -99,8 +93,10 @@ SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, 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); diff --git a/SystemConfiguration.fproj/SCDNotifierWait.c b/SystemConfiguration.fproj/SCDNotifierWait.c index 2417fd2..7597e93 100644 --- a/SystemConfiguration.fproj/SCDNotifierWait.c +++ b/SystemConfiguration.fproj/SCDNotifierWait.c @@ -49,7 +49,7 @@ waitForMachMessage(mach_port_t port) 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; } @@ -61,7 +61,7 @@ waitForMachMessage(mach_port_t port) 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; } @@ -79,9 +79,7 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store) 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; @@ -102,18 +100,17 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store) /* 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; @@ -128,25 +125,28 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store) 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); @@ -161,8 +161,6 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store) /* set notifier active */ storePrivate->notifyStatus = Using_NotifierWait; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Waiting...")); - msgid = waitForMachMessage(port); /* set notifier inactive */ @@ -170,26 +168,32 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store) 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); diff --git a/SystemConfiguration.fproj/SCDNotify.c b/SystemConfiguration.fproj/SCDNotify.c index 409523b..c06615b 100644 --- a/SystemConfiguration.fproj/SCDNotify.c +++ b/SystemConfiguration.fproj/SCDNotify.c @@ -47,12 +47,7 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef store, 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; @@ -80,8 +75,10 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef store, 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); diff --git a/SystemConfiguration.fproj/SCDOpen.c b/SystemConfiguration.fproj/SCDOpen.c index 1ce5cfb..77352f5 100644 --- a/SystemConfiguration.fproj/SCDOpen.c +++ b/SystemConfiguration.fproj/SCDOpen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,6 +32,8 @@ */ #include +#include +#include #include #include #include @@ -41,14 +43,66 @@ #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(" {\n"), cf, allocator); - CFStringAppendFormat(result, NULL, CFSTR("}")); + CFStringAppendFormat(result, NULL, CFSTR(" { "), 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; } @@ -63,23 +117,23 @@ __SCDynamicStoreDeallocate(CFTypeRef cf) 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; @@ -89,14 +143,24 @@ __SCDynamicStoreDeallocate(CFTypeRef cf) 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; } @@ -117,11 +181,54 @@ static const CFRuntimeClass __SCDynamicStoreClass = { }; +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; } @@ -132,6 +239,7 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, SCDynamicStoreCallBack callout, SCDynamicStoreContext *context) { + int sc_status = kSCStatusOK; uint32_t size; SCDynamicStorePrivateRef storePrivate; @@ -144,15 +252,17 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, __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; @@ -167,8 +277,8 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, 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); } } @@ -176,8 +286,7 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, 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); @@ -195,135 +304,150 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef allocator, 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 */ diff --git a/SystemConfiguration.fproj/SCDPlugin.c b/SystemConfiguration.fproj/SCDPlugin.c index a92f51d..c14e62d 100644 --- a/SystemConfiguration.fproj/SCDPlugin.c +++ b/SystemConfiguration.fproj/SCDPlugin.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -135,6 +135,9 @@ reaper(int sigraised) MACH_PORT_NULL, /* rcv_name */ 0, /* timeout */ MACH_PORT_NULL); /* notify */ + if (status == MACH_SEND_TIMED_OUT) { + mach_msg_destroy(&msg.header); + } return; } @@ -298,19 +301,9 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack callout, 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 { @@ -321,6 +314,14 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack callout, 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)); diff --git a/SystemConfiguration.fproj/SCDPlugin.h b/SystemConfiguration.fproj/SCDPlugin.h index 24955c4..9aa8f1d 100644 --- a/SystemConfiguration.fproj/SCDPlugin.h +++ b/SystemConfiguration.fproj/SCDPlugin.h @@ -37,15 +37,21 @@ /* - @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") /*! @@ -56,7 +62,7 @@ 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, @@ -86,6 +92,19 @@ typedef void (*SCDynamicStoreBundleStartFunction) (const char *bundleName, 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 @@ -97,10 +116,10 @@ typedef void (*SCDynamicStoreBundlePrimeFunction) (); @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); /*! @@ -111,8 +130,8 @@ typedef void (*SCDPluginExecCallBack) (pid_t pid, @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 diff --git a/SystemConfiguration.fproj/SCDPrivate.c b/SystemConfiguration.fproj/SCDPrivate.c index 4248bd6..ed1e0cb 100644 --- a/SystemConfiguration.fproj/SCDPrivate.c +++ b/SystemConfiguration.fproj/SCDPrivate.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -35,6 +35,13 @@ #include #include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -59,7 +66,13 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi 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) { @@ -67,10 +80,6 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi } } - if (len >= bufLen) { - len = bufLen - 1; - } - (void)CFStringGetBytes(cfstr, CFRangeMake(0, len), encoding, @@ -85,19 +94,70 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi } +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; @@ -118,10 +178,7 @@ _SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dat *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; @@ -153,7 +210,7 @@ _SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dat 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 { @@ -165,10 +222,7 @@ _SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dat if (*obj == NULL) { if (xmlError) { - SCLog(TRUE, - LOG_ERR, - CFSTR("CFPropertyListCreateFromXMLData() failed: %@"), - xmlError); + SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserialize(): %@"), xmlError); CFRelease(xmlError); } _SCErrorSet(kSCStatusFailed); @@ -196,7 +250,7 @@ _SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *da 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; @@ -217,10 +271,7 @@ _SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *da *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; @@ -247,7 +298,7 @@ _SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex da 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 { @@ -255,7 +306,7 @@ _SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex da } if (*str == NULL) { - SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateFromExternalRepresentation() failed")); + SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserializeString() failed")); return FALSE; } @@ -276,10 +327,7 @@ _SCSerializeData(CFDataRef data, void **dataRef, CFIndex *dataLen) *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; @@ -299,7 +347,7 @@ _SCUnserializeData(CFDataRef *data, void *dataRef, CFIndex dataLen) *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; } @@ -391,7 +439,7 @@ _SCUnserializeMultiple(CFDictionaryRef dict) 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; } } @@ -424,6 +472,153 @@ _SCUnserializeMultiple(CFDictionaryRef dict) } +__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() { diff --git a/SystemConfiguration.fproj/SCDRemove.c b/SystemConfiguration.fproj/SCDRemove.c index b523f56..d3a997c 100644 --- a/SystemConfiguration.fproj/SCDRemove.c +++ b/SystemConfiguration.fproj/SCDRemove.c @@ -49,12 +49,7 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) 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; @@ -82,8 +77,10 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key) 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); diff --git a/SystemConfiguration.fproj/SCDSet.c b/SystemConfiguration.fproj/SCDSet.c index aba8569..5b26a4c 100644 --- a/SystemConfiguration.fproj/SCDSet.c +++ b/SystemConfiguration.fproj/SCDSet.c @@ -59,22 +59,15 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, 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*/ @@ -85,7 +78,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, newInfo = _SCSerializeMultiple(keysToSet); if (!newInfo) { _SCErrorSet(kSCStatusFailed); - return NULL; + return FALSE; } ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen); @@ -93,7 +86,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, if (!ok) { _SCErrorSet(kSCStatusFailed); - return NULL; + return FALSE; } } @@ -102,7 +95,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, if (!_SCSerialize(keysToRemove, &xmlRemove, (void **)&myRemoveRef, &myRemoveLen)) { if (xmlSet) CFRelease(xmlSet); _SCErrorSet(kSCStatusFailed); - return NULL; + return FALSE; } } @@ -112,7 +105,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, if (xmlSet) CFRelease(xmlSet); if (xmlRemove) CFRelease(xmlRemove); _SCErrorSet(kSCStatusFailed); - return NULL; + return FALSE; } } @@ -132,8 +125,10 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store, 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); @@ -162,13 +157,7 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR 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; @@ -208,8 +197,10 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR 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); diff --git a/SystemConfiguration.fproj/SCDSnapshot.c b/SystemConfiguration.fproj/SCDSnapshot.c index 13e069d..5f69bb7 100644 --- a/SystemConfiguration.fproj/SCDSnapshot.c +++ b/SystemConfiguration.fproj/SCDSnapshot.c @@ -46,9 +46,7 @@ SCDynamicStoreSnapshot(SCDynamicStoreRef store) 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; @@ -63,8 +61,10 @@ SCDynamicStoreSnapshot(SCDynamicStoreRef store) 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); diff --git a/SystemConfiguration.fproj/SCDTouch.c b/SystemConfiguration.fproj/SCDTouch.c index 4450e9e..8b71a7b 100644 --- a/SystemConfiguration.fproj/SCDTouch.c +++ b/SystemConfiguration.fproj/SCDTouch.c @@ -49,12 +49,7 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) 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; @@ -82,8 +77,10 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) 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); diff --git a/SystemConfiguration.fproj/SCDUnlock.c b/SystemConfiguration.fproj/SCDUnlock.c index c847c3f..d901171 100644 --- a/SystemConfiguration.fproj/SCDUnlock.c +++ b/SystemConfiguration.fproj/SCDUnlock.c @@ -46,9 +46,7 @@ SCDynamicStoreUnlock(SCDynamicStoreRef store) 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; @@ -63,8 +61,10 @@ SCDynamicStoreUnlock(SCDynamicStoreRef store) /* (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); diff --git a/SystemConfiguration.fproj/SCDynamicStore.h b/SystemConfiguration.fproj/SCDynamicStore.h index ea0d504..babb95c 100644 --- a/SystemConfiguration.fproj/SCDynamicStore.h +++ b/SystemConfiguration.fproj/SCDynamicStore.h @@ -25,37 +25,52 @@ #define _SCDYNAMICSTORE_H #include -#include -#include #include - /*! @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; @@ -67,11 +82,11 @@ typedef struct { /*! @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, @@ -84,7 +99,7 @@ __BEGIN_DECLS /*! @function SCDynamicStoreGetTypeID - Returns the type identifier of all SCDynamicStore instances. + @discussion Returns the type identifier of all SCDynamicStore instances. */ CFTypeID SCDynamicStoreGetTypeID (void); @@ -93,21 +108,21 @@ 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 ( @@ -118,23 +133,71 @@ 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: + + + + + + + + +
key + value +
kSCDynamicStoreUseSessionKeysCFBooleanRef
+ + 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. @@ -150,14 +213,13 @@ SCDynamicStoreCreateRunLoopSource ( /*! @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 ( @@ -167,13 +229,13 @@ 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 ( @@ -184,15 +246,15 @@ 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 ( @@ -203,15 +265,12 @@ 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 ( @@ -221,15 +280,15 @@ 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 @@ -241,12 +300,12 @@ SCDynamicStoreCopyMultiple ( /*! @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 ( @@ -257,12 +316,12 @@ 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 ( @@ -275,10 +334,10 @@ 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 @@ -291,9 +350,11 @@ SCDynamicStoreRemoveValue ( @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 ( @@ -304,14 +365,14 @@ 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 ( @@ -323,12 +384,14 @@ 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 ( diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h b/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h index 088b408..5cab3e1 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h +++ b/SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h @@ -30,9 +30,10 @@ /*! - @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. */ @@ -40,17 +41,16 @@ __BEGIN_DECLS /*! @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(). @@ -60,14 +60,14 @@ SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store, CFStringRef serviceID); /*! @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. */ @@ -77,11 +77,12 @@ DHCPInfoGetOptionData(CFDictionaryRef info, UInt8 code); /*! @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. */ diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h b/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h index e95c460..36f5f63 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h +++ b/SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,15 +25,17 @@ #define _SCDYNAMICSTORECOPYSPECIFIC_H #include +#include #include #include /*! @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.). */ @@ -41,13 +43,14 @@ __BEGIN_DECLS /*! @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. */ @@ -60,17 +63,22 @@ SCDynamicStoreCopyComputerName ( /*! @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. */ @@ -84,13 +92,10 @@ SCDynamicStoreCopyConsoleUser ( /*! @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. */ @@ -101,12 +106,12 @@ SCDynamicStoreCopyLocalHostName ( /*! @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. */ @@ -118,12 +123,81 @@ SCDynamicStoreCopyLocation ( /*! @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: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
key + type + description +
kSCPropNetProxiesExceptionsListCFArray[CFString]Host name patterns which should bypass the proxy
kSCPropNetProxiesHTTPEnableCFNumber (0 or 1)Enables/disables the use of an HTTP proxy
kSCPropNetProxiesHTTPProxyCFStringThe proxy host
kSCPropNetProxiesHTTPPortCFNumberThe proxy port number
kSCPropNetProxiesHTTPSEnableCFNumber (0 or 1)Enables/disables the use of an HTTPS proxy
kSCPropNetProxiesHTTPSProxyCFStringThe proxy host
kSCPropNetProxiesHTTPSPortCFNumberThe proxy port number
kSCPropNetProxiesFTPEnableCFNumber (0 or 1)Enables/disables the use of an FTP proxy
kSCPropNetProxiesFTPProxyCFStringThe proxy host
kSCPropNetProxiesFTPPortCFNumberThe proxy port number
kSCPropNetProxiesFTPPassiveCFNumber (0 or 1)Enable passive mode operation for use behind connection + filter-ing firewalls.
+ + 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 diff --git a/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h b/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h index 5746a81..380f260 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h +++ b/SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h @@ -30,9 +30,9 @@ /*! - @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. */ @@ -41,11 +41,14 @@ __BEGIN_DECLS /* * 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 diff --git a/SystemConfiguration.fproj/SCDynamicStoreInternal.h b/SystemConfiguration.fproj/SCDynamicStoreInternal.h index 51f28b2..6017d20 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreInternal.h +++ b/SystemConfiguration.fproj/SCDynamicStoreInternal.h @@ -56,10 +56,7 @@ typedef struct { /* per-session flags */ Boolean locked; - - /* SCDynamicStoreKeys being watched */ - CFMutableSetRef keys; - CFMutableSetRef patterns; + Boolean useSessionKeys; /* current status of notification requests */ __SCDynamicStoreNotificationStatus notifyStatus; @@ -74,8 +71,11 @@ typedef struct { 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; diff --git a/SystemConfiguration.fproj/SCDynamicStoreKey.h b/SystemConfiguration.fproj/SCDynamicStoreKey.h index 18bde7d..b875558 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreKey.h +++ b/SystemConfiguration.fproj/SCDynamicStoreKey.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,19 +30,31 @@ /*! @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 ( @@ -53,6 +65,21 @@ 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 ( @@ -63,6 +90,19 @@ 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 ( @@ -72,6 +112,23 @@ 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 ( @@ -83,6 +140,24 @@ 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 ( @@ -94,10 +169,16 @@ 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 ( @@ -106,10 +187,15 @@ 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 ( @@ -118,11 +204,16 @@ 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 ( @@ -131,10 +222,16 @@ 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 ( @@ -143,10 +240,16 @@ 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 ( diff --git a/SystemConfiguration.fproj/SCDynamicStorePrivate.h b/SystemConfiguration.fproj/SCDynamicStorePrivate.h index ebf7b28..7ea34c2 100644 --- a/SystemConfiguration.fproj/SCDynamicStorePrivate.h +++ b/SystemConfiguration.fproj/SCDynamicStorePrivate.h @@ -25,17 +25,19 @@ #define _SCDYNAMICSTOREPRIVATE_H #include -#include -#include +#include #include #include +/*! + @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) ( @@ -138,7 +140,7 @@ SCDynamicStoreRemoveWatchedKey (SCDynamicStoreRef store, @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 diff --git a/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h b/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h index 76f8c90..81e7f87 100644 --- a/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h +++ b/SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h @@ -28,6 +28,10 @@ #include +/*! + @header SCDynamicStoreSetSpecificPrivate + */ + __BEGIN_DECLS /*! diff --git a/SystemConfiguration.fproj/SCLocation.c b/SystemConfiguration.fproj/SCLocation.c index 06dd869..602ab54 100644 --- a/SystemConfiguration.fproj/SCLocation.c +++ b/SystemConfiguration.fproj/SCLocation.c @@ -47,12 +47,12 @@ SCDynamicStoreCopyLocation(SCDynamicStoreRef store) 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; } diff --git a/SystemConfiguration.fproj/SCNetwork.c b/SystemConfiguration.fproj/SCNetwork.c index e5f1671..23f6648 100644 --- a/SystemConfiguration.fproj/SCNetwork.c +++ b/SystemConfiguration.fproj/SCNetwork.c @@ -81,7 +81,7 @@ SCNetworkCheckReachabilityByName(const char *nodename, SCNetworkConnectionFlags *flags) { SCNetworkReachabilityRef networkAddress; - Boolean ok; + Boolean ok; if (!nodename) { _SCErrorSet(kSCStatusInvalidArgument); @@ -98,25 +98,22 @@ Boolean 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); } diff --git a/SystemConfiguration.fproj/SCNetwork.h b/SystemConfiguration.fproj/SCNetwork.h index b9c9ee1..8dae0e8 100644 --- a/SystemConfiguration.fproj/SCNetwork.h +++ b/SystemConfiguration.fproj/SCNetwork.h @@ -32,78 +32,79 @@ /*! @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 not 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, @@ -127,8 +128,8 @@ __BEGIN_DECLS @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 ( @@ -139,35 +140,39 @@ 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 */ diff --git a/SystemConfiguration.fproj/SCNetworkConfiguration.h b/SystemConfiguration.fproj/SCNetworkConfiguration.h new file mode 100644 index 0000000..a9be635 --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkConfiguration.h @@ -0,0 +1,753 @@ +/* + * 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 +#include +#include +#include + + +/*! + @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 */ diff --git a/SystemConfiguration.fproj/SCNetworkConfigurationInternal.c b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.c new file mode 100644 index 0000000..d9f1579 --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.c @@ -0,0 +1,415 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +#include +#include + +#include +#include + + +__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; +} diff --git a/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h new file mode 100644 index 0000000..e0c981b --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h @@ -0,0 +1,218 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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 */ diff --git a/SystemConfiguration.fproj/SCNetworkConnection.c b/SystemConfiguration.fproj/SCNetworkConnection.c index bd3c331..2e01b50 100644 --- a/SystemConfiguration.fproj/SCNetworkConnection.c +++ b/SystemConfiguration.fproj/SCNetworkConnection.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,6 +24,9 @@ /* * Modification History * + * April 14, 2004 Christophe Allie + * - use mach messages + * December 20, 2002 Christophe Allie * - initial revision */ @@ -41,19 +44,22 @@ #include #include +#include + #include +#include #include #include -#include #include -#include #include #include #include #include -#include "ppp.h" - +#include +#include +#include "pppcontroller.h" +#include /* ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- */ @@ -61,16 +67,16 @@ 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; @@ -78,6 +84,9 @@ typedef struct { SCNetworkConnectionContext rlsContext; CFMutableArrayRef rlList; + /* misc info */ + int debug; + } SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef; /* ------------------------------------------------------------------------------------------- @@ -95,9 +104,9 @@ isA_SCNetworkConnection(CFTypeRef obj) 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(" {\n"), cf, allocator); @@ -109,37 +118,34 @@ __SCNetworkConnectionCopyDescription(CFTypeRef cf) /* ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- */ + 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); @@ -175,26 +181,130 @@ __SCNetworkConnectionInitialize(void) 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); @@ -202,30 +312,80 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef service /* 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; } @@ -234,53 +394,19 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef service ------------------------------------------------------------------------------------------- */ 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; @@ -289,17 +415,7 @@ SCNetworkConnectionCreateWithServiceID (CFAllocatorRef allocator, 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; } @@ -308,7 +424,7 @@ SCNetworkConnectionCreateWithServiceID (CFAllocatorRef allocator, ------------------------------------------------------------------------------------------- */ CFStringRef -SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection) +SCNetworkConnectionCopyServiceID(SCNetworkConnectionRef connection) { if (!isA_SCNetworkConnection(connection)) { _SCErrorSet(kSCStatusInvalidArgument); @@ -322,67 +438,40 @@ SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection) ------------------------------------------------------------------------------------------- */ 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; } @@ -391,59 +480,67 @@ SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection) ------------------------------------------------------------------------------------------- */ 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; } @@ -451,37 +548,97 @@ SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection) ------------------------------------------------------------------------------------------- */ 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; } @@ -489,280 +646,214 @@ SCNetworkConnectionStart (SCNetworkConnectionRef connection, ------------------------------------------------------------------------------------------- */ 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; } @@ -775,15 +866,17 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef connection, 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; @@ -796,11 +889,12 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef connection, 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; @@ -810,6 +904,7 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef connection, //************************* 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") @@ -822,58 +917,286 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef connection, 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 // ---------------------------------------------------- @@ -887,19 +1210,11 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session, 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; @@ -910,10 +1225,10 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session, kSCEntNetInterface); dict = SCDynamicStoreCopyValue(session, key); CFRelease(key); - if (dict) { + if (dict != NULL) { + CFRelease(dict); *serviceID = CFRetain(lastServiceSelectedInIC); foundService = TRUE; - CFRelease(dict); } } CFRelease(lastServiceSelectedInIC); @@ -934,10 +1249,10 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session, 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; @@ -952,17 +1267,14 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio } 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; } @@ -970,7 +1282,7 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio 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; @@ -978,11 +1290,8 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio } } while (FALSE); - if (key != NULL) - CFRelease(key); - - if (dict != NULL) - CFRelease(dict); + if (key != NULL) CFRelease(key); + if (dict != NULL) CFRelease(dict); return success; } @@ -998,16 +1307,15 @@ SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptions 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 @@ -1023,78 +1331,164 @@ SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptions } //******************************************************************************** -// 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; @@ -1108,44 +1502,14 @@ addPasswordFromKeychain(CFDictionaryRef *userOptions) 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; } //******************************************************************************** @@ -1156,7 +1520,7 @@ addPasswordFromKeychain(CFDictionaryRef *userOptions) static CFArrayRef copyKeychainEnumerator(CFStringRef uniqueIdentifier) { - char *buf = NULL; + char *buf; CFMutableArrayRef itemArray = NULL; OSStatus result; SecKeychainSearchRef search = NULL; diff --git a/SystemConfiguration.fproj/SCNetworkConnection.h b/SystemConfiguration.fproj/SCNetworkConnection.h index 74a70d1..148e3dd 100644 --- a/SystemConfiguration.fproj/SCNetworkConnection.h +++ b/SystemConfiguration.fproj/SCNetworkConnection.h @@ -34,27 +34,43 @@ /*! @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; @@ -62,7 +78,7 @@ typedef struct { 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; @@ -73,19 +89,14 @@ typedef struct { 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. */ @@ -96,57 +107,50 @@ enum { 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. */ @@ -166,7 +170,7 @@ enum { kSCNetworkConnectionPPPSuspended = 12, kSCNetworkConnectionPPPWaitingForRedial = 13 }; -typedef int32_t SCNetworkConnectionPPPStatus AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; +typedef int32_t SCNetworkConnectionPPPStatus; /*! @@ -175,13 +179,13 @@ typedef int32_t SCNetworkConnectionPPPStatus AVAILABLE_MAC_OS_X_VERSION_10_3_ 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; + ); @@ -200,24 +204,28 @@ typedef void (*SCNetworkConnectionCallBack) ( __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, @@ -228,22 +236,24 @@ Boolean SCNetworkConnectionCopyUserPreferences ( /*! @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 ( @@ -257,8 +267,8 @@ 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 ( @@ -269,15 +279,19 @@ 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: +
+@textblock
+ 
+	kSCNetworkConnectionInvalid
+	kSCNetworkConnectionDisconnected
+	kSCNetworkConnectionConnecting
+	kSCNetworkConnectionDisconnecting
+	kSCNetworkConnectionConnected
+@/textblock
+
@param connection The SCNetworkConnection to obtain status from. - @result The status value. + @result Returns the status value. */ SCNetworkConnectionStatus SCNetworkConnectionGetStatus ( @@ -291,29 +305,34 @@ 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: +
+@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
+
+ 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 ( @@ -325,23 +344,37 @@ 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: +
+@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
+
+ 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 ( @@ -351,42 +384,47 @@ 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 ( @@ -398,21 +436,22 @@ 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 ( @@ -423,13 +462,13 @@ 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 ( @@ -439,12 +478,13 @@ 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 ( @@ -456,12 +496,13 @@ 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 ( diff --git a/SystemConfiguration.fproj/SCNetworkInterface.c b/SystemConfiguration.fproj/SCNetworkInterface.c new file mode 100644 index 0000000..bb4fd5a --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkInterface.c @@ -0,0 +1,2441 @@ +/* + * 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 + * - initial revision + * which includes code originally authored by + * Robert Ulrich + * Elizaabeth Douglas + * Quinn + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include // for kIOEthernetInterfaceClass +#include +#include +#include "dy_framework.h" + +#ifndef kIODeviceSupportsHoldKey +#define kIODeviceSupportsHoldKey "V92Modem" +#endif + +#include "SCNetworkConfiguration.h" +#include "SCNetworkConfigurationInternal.h" + +#include +#include +#include +#include + + +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(" { "), 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; +} diff --git a/SystemConfiguration.fproj/SCNetworkProtocol.c b/SystemConfiguration.fproj/SCNetworkProtocol.c new file mode 100644 index 0000000..1c6c73a --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkProtocol.c @@ -0,0 +1,297 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +#include +#include +#include +#include + +#include "SCNetworkConfiguration.h" +#include "SCNetworkConfigurationInternal.h" + +#include + + +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(" { "), 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; +} diff --git a/SystemConfiguration.fproj/SCNetworkReachability.c b/SystemConfiguration.fproj/SCNetworkReachability.c index c838bc7..a0d0a54 100644 --- a/SystemConfiguration.fproj/SCNetworkReachability.c +++ b/SystemConfiguration.fproj/SCNetworkReachability.c @@ -1,15 +1,15 @@ /* - * 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, @@ -17,13 +17,16 @@ * 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 + * - use [SC] DNS configuration information + * * January 19, 2003 Allan Nathanson * - add advanced reachability APIs */ @@ -35,9 +38,10 @@ #include #include +#include +#include #include #include -#include #include #include #include @@ -54,7 +58,7 @@ #define s6_addr16 __u6_addr.__u6_addr16 #endif -#include "ppp.h" +#include #define kSCNetworkFlagsFirstResolvePending (1<<31) @@ -104,9 +108,11 @@ typedef struct { SCNetworkReachabilityContext rlsContext; CFMutableArrayRef rlList; - /* async DNS query info */ + /* [async] DNS query info */ + Boolean haveDNS; CFMachPortRef dnsPort; CFRunLoopSourceRef dnsRLS; + struct timeval dnsQueryStart; } SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef; @@ -128,10 +134,12 @@ static const CFRuntimeClass __SCNetworkReachabilityClass = { 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; @@ -139,161 +147,52 @@ static CFMutableArrayRef hn_rlList = 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; } @@ -312,7 +211,7 @@ updatePPPStatus(SCDynamicStoreRef *storeP, 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; @@ -327,10 +226,10 @@ updatePPPStatus(SCDynamicStoreRef *storeP, 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; } } @@ -364,7 +263,7 @@ updatePPPStatus(SCDynamicStoreRef *storeP, dict = SCDynamicStoreCopyMultiple(store, NULL, patterns); CFRelease(patterns); } - if (!dict) { + if (dict == NULL) { /* if we could not access the dynamic store */ goto done; } @@ -502,16 +401,16 @@ updatePPPStatus(SCDynamicStoreRef *storeP, 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; @@ -520,25 +419,29 @@ updatePPPAvailable(SCDynamicStoreRef *storeP, 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; } } @@ -566,7 +469,7 @@ updatePPPAvailable(SCDynamicStoreRef *storeP, dict = SCDynamicStoreCopyMultiple(store, NULL, patterns); CFRelease(patterns); } - if (!dict) { + if (dict == NULL) { /* if we could not access the dynamic store */ goto done; } @@ -667,8 +570,8 @@ updatePPPAvailable(SCDynamicStoreRef *storeP, done : - if (dict) CFRelease(dict); - if (storeP) *storeP = store; + if (dict != NULL) CFRelease(dict); + if (storeP != NULL) *storeP = store; return sc_status; } @@ -717,7 +620,7 @@ checkAddress(SCDynamicStoreRef *storeP, 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) @@ -725,16 +628,21 @@ checkAddress(SCDynamicStoreRef *storeP, 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; @@ -749,16 +657,6 @@ checkAddress(SCDynamicStoreRef *storeP, 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; @@ -877,7 +775,7 @@ checkAddress(SCDynamicStoreRef *storeP, 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); } } @@ -887,13 +785,13 @@ checkAddress(SCDynamicStoreRef *storeP, 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 */ @@ -948,6 +846,14 @@ checkAddress(SCDynamicStoreRef *storeP, 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; @@ -964,7 +870,10 @@ checkAddress(SCDynamicStoreRef *storeP, } } - 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; } @@ -973,7 +882,7 @@ checkAddress(SCDynamicStoreRef *storeP, if_name, (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ); - if (if_index) { + if (if_index != NULL) { *if_index = sdl->sdl_index; } @@ -1012,7 +921,7 @@ checkAddress(SCDynamicStoreRef *storeP, 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; @@ -1022,47 +931,6 @@ checkAddress(SCDynamicStoreRef *storeP, } -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) { @@ -1077,14 +945,14 @@ __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 " : "", @@ -1095,7 +963,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf) 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); @@ -1108,7 +976,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf) 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); @@ -1118,13 +986,8 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf) 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)")); @@ -1132,7 +995,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf) break; } } - if (targetPrivate->rls) { + if (targetPrivate->rls != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", flags=%8.8x, if_index=%hu"), @@ -1150,26 +1013,24 @@ __SCNetworkReachabilityDeallocate(CFTypeRef cf) { 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; @@ -1193,15 +1054,13 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef allocator) /* 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; } @@ -1226,6 +1085,7 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef allocator) targetPrivate->rlsContext.copyDescription = NULL; targetPrivate->rlList = NULL; + targetPrivate->haveDNS = FALSE; targetPrivate->dnsPort = NULL; targetPrivate->dnsRLS = NULL; @@ -1239,7 +1099,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef allocator, { SCNetworkReachabilityPrivateRef targetPrivate; - if (!address || + if ((address == NULL) || (address->sa_len == 0) || (address->sa_len > sizeof(struct sockaddr_storage))) { _SCErrorSet(kSCStatusInvalidArgument); @@ -1247,7 +1107,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef allocator, } targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator); - if (!targetPrivate) { + if (targetPrivate == NULL) { return NULL; } @@ -1271,7 +1131,7 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef allocator, return NULL; } - if (localAddress) { + if (localAddress != NULL) { if ((localAddress->sa_len == 0) || (localAddress->sa_len > sizeof(struct sockaddr_storage))) { _SCErrorSet(kSCStatusInvalidArgument); @@ -1279,7 +1139,7 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef allocator, } } - if (remoteAddress) { + if (remoteAddress != NULL) { if ((remoteAddress->sa_len == 0) || (remoteAddress->sa_len > sizeof(struct sockaddr_storage))) { _SCErrorSet(kSCStatusInvalidArgument); @@ -1288,18 +1148,18 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef allocator, } 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); } @@ -1312,15 +1172,42 @@ SCNetworkReachabilityRef 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; } @@ -1364,7 +1251,7 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef target, } 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 */ @@ -1379,37 +1266,20 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef target, 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); @@ -1423,94 +1293,41 @@ __SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinf } /* 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 */ /* @@ -1530,7 +1347,6 @@ rankReachability(SCNetworkConnectionFlags flags) } -#ifdef CHECK_IPV6_REACHABILITY static void getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info) { @@ -1542,6 +1358,7 @@ getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi getaddrinfo_async_handle_reply(msg); if (port == targetPrivate->dnsPort) { + CFRunLoopSourceInvalidate(targetPrivate->dnsRLS); CFRelease(targetPrivate->dnsRLS); targetPrivate->dnsRLS = NULL; CFRelease(targetPrivate->dnsPort); @@ -1552,38 +1369,255 @@ getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi 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 @@ -1596,41 +1630,105 @@ checkResolverReachability(SCDynamicStoreRef *storeP, *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; @@ -1641,17 +1739,19 @@ static Boolean 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, @@ -1661,7 +1761,7 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) { (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; } @@ -1670,26 +1770,6 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) { 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); @@ -1718,7 +1798,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, Boolean ok = TRUE; *flags = 0; - if (if_index) { + if (if_index != NULL) { *if_index = 0; } @@ -1733,14 +1813,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, /* * 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 */ @@ -1754,12 +1827,10 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, } } - 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. @@ -1767,13 +1838,6 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, my_flags = 0; my_index = 0; - /* - * Check if 0.0.0.0 - */ - if (isAddressZero(targetPrivate->remoteAddress, &my_flags)) { - break; - } - /* * Check "remote" address */ @@ -1788,27 +1852,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, } 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; @@ -1820,30 +1880,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, * 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; } @@ -1878,16 +1931,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, * 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); @@ -1911,6 +1971,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, 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 */ @@ -1927,13 +1988,13 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, } } } 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 */ } @@ -1958,13 +2019,13 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef *storeP, } *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; } @@ -1982,15 +2043,15 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef target, 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; } @@ -1998,6 +2059,7 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef target, static void __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) { + CFStringRef dns_key; CFStringRef key; CFMutableArrayRef keys; CFStringRef pattern; @@ -2006,34 +2068,30 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) 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, @@ -2041,7 +2099,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) CFArrayAppendValue(patterns, pattern); CFRelease(pattern); - /* Setup: per-service Interface info */ + // Setup: per-service Interface info pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, @@ -2049,7 +2107,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) CFArrayAppendValue(patterns, pattern); CFRelease(pattern); - /* Setup: per-service PPP info */ + // Setup: per-service PPP info (for kSCPropNetPPPDialOnDemand) pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, @@ -2057,15 +2115,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) 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, @@ -2073,7 +2123,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef store) CFArrayAppendValue(patterns, pattern); CFRelease(pattern); - /* State: per-interface IPv6 info */ + // State: per-interface IPv6 info pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, @@ -2094,12 +2144,13 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef store, 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); @@ -2116,35 +2167,20 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef store, 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); @@ -2155,26 +2191,51 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef store, 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); } @@ -2187,78 +2248,6 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef store, } -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) { @@ -2278,7 +2267,7 @@ 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; @@ -2288,8 +2277,15 @@ rlsPerform(void *info) 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 */ @@ -2298,8 +2294,8 @@ rlsPerform(void *info) /* 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; @@ -2308,13 +2304,12 @@ rlsPerform(void *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; @@ -2330,9 +2325,9 @@ SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target, 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; @@ -2342,8 +2337,8 @@ SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target, 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); } } @@ -2372,15 +2367,21 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, 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; } @@ -2392,7 +2393,7 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, hn_targets = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); } - if (!targetPrivate->rls) { + if (targetPrivate->rls == NULL) { CFRunLoopSourceContext context = { 0 // version , (void *)target // info , CFRetain // retain @@ -2410,24 +2411,24 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, 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 @@ -2435,7 +2436,7 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, CFRunLoopAddSource(runLoop, hn_storeRLS, runLoopMode); } - __schedule(target, runLoop, runLoopMode, hn_rlList); + _SC_schedule(target, runLoop, runLoopMode, hn_rlList); CFSetAddValue(hn_targets, target); if (init) { @@ -2456,13 +2457,13 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target, 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; @@ -2492,24 +2493,24 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, 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); } @@ -2518,19 +2519,17 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, /* * 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); @@ -2539,10 +2538,10 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, } } - (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 @@ -2554,17 +2553,21 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef target, * 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(); } } diff --git a/SystemConfiguration.fproj/SCNetworkReachability.h b/SystemConfiguration.fproj/SCNetworkReachability.h index 8efa2d3..33ffd57 100644 --- a/SystemConfiguration.fproj/SCNetworkReachability.h +++ b/SystemConfiguration.fproj/SCNetworkReachability.h @@ -33,27 +33,42 @@ /*! @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 not 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; @@ -61,32 +76,33 @@ typedef struct { 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. */ @@ -99,13 +115,13 @@ SCNetworkReachabilityCreateWithAddress ( /*! @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. */ @@ -118,12 +134,13 @@ SCNetworkReachabilityCreateWithAddressPair ( /*! @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. */ @@ -135,7 +152,8 @@ SCNetworkReachabilityCreateWithName ( /*! @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; @@ -145,13 +163,13 @@ SCNetworkReachabilityGetTypeID (void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_L @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 ( @@ -163,14 +181,14 @@ 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 ( @@ -181,10 +199,15 @@ 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 ( @@ -195,10 +218,16 @@ 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 ( diff --git a/SystemConfiguration.fproj/SCNetworkService.c b/SystemConfiguration.fproj/SCNetworkService.c new file mode 100644 index 0000000..db30ae7 --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkService.c @@ -0,0 +1,862 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +#include +#include +#include +#include + +#include + + +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(" { "), 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; +} diff --git a/SystemConfiguration.fproj/SCNetworkSet.c b/SystemConfiguration.fproj/SCNetworkSet.c new file mode 100644 index 0000000..72653fa --- /dev/null +++ b/SystemConfiguration.fproj/SCNetworkSet.c @@ -0,0 +1,701 @@ +/* + * 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 + * - initial revision + */ + + +#include +#include +#include +#include +#include +#include + +#include "SCNetworkConfiguration.h" +#include "SCNetworkConfigurationInternal.h" + +#include + + +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(" { "), 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; +} diff --git a/SystemConfiguration.fproj/SCP.c b/SystemConfiguration.fproj/SCP.c index 0d64743..e81b75f 100644 --- a/SystemConfiguration.fproj/SCP.c +++ b/SystemConfiguration.fproj/SCP.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -160,14 +160,19 @@ __SCPreferencesPath(CFAllocatorRef allocator, 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; } @@ -178,39 +183,45 @@ _SCPNotificationKey(CFAllocatorRef allocator, 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; } diff --git a/SystemConfiguration.fproj/SCPAdd.c b/SystemConfiguration.fproj/SCPAdd.c index 963c2f0..420fe32 100644 --- a/SystemConfiguration.fproj/SCPAdd.c +++ b/SystemConfiguration.fproj/SCPAdd.c @@ -36,24 +36,24 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPApply.c b/SystemConfiguration.fproj/SCPApply.c index 951eb4f..775036f 100644 --- a/SystemConfiguration.fproj/SCPApply.c +++ b/SystemConfiguration.fproj/SCPApply.c @@ -36,54 +36,49 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPCommit.c b/SystemConfiguration.fproj/SCPCommit.c index 8998e4b..0ea6dc9 100644 --- a/SystemConfiguration.fproj/SCPCommit.c +++ b/SystemConfiguration.fproj/SCPCommit.c @@ -63,21 +63,25 @@ writen(int d, const void *buf, size_t nbytes) 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; } } @@ -85,7 +89,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session) /* * if necessary, apply changes */ - if (sessionPrivate->changed) { + if (prefsPrivate->changed) { int fd; CFDataRef newPrefs; char * path; @@ -93,20 +97,20 @@ SCPreferencesCommitChanges(SCPreferencesRef session) 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); @@ -116,7 +120,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session) 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, '/'); @@ -131,7 +135,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session) } } } - 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; } @@ -141,84 +145,97 @@ SCPreferencesCommitChanges(SCPreferencesRef session) (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; } diff --git a/SystemConfiguration.fproj/SCPGet.c b/SystemConfiguration.fproj/SCPGet.c index 896d27c..297107e 100644 --- a/SystemConfiguration.fproj/SCPGet.c +++ b/SystemConfiguration.fproj/SCPGet.c @@ -40,22 +40,23 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPList.c b/SystemConfiguration.fproj/SCPList.c index 1626811..8a4266f 100644 --- a/SystemConfiguration.fproj/SCPList.c +++ b/SystemConfiguration.fproj/SCPList.c @@ -36,28 +36,31 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPLock.c b/SystemConfiguration.fproj/SCPLock.c index 88bd281..f7b1551 100644 --- a/SystemConfiguration.fproj/SCPLock.c +++ b/SystemConfiguration.fproj/SCPLock.c @@ -37,29 +37,32 @@ #include #include +#include #include 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 { @@ -68,35 +71,31 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) } } - 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; @@ -104,8 +103,8 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) /* * Attempt to acquire the lock */ - if (SCDynamicStoreAddTemporaryValue(sessionPrivate->session, - sessionPrivate->sessionKeyLock, + if (SCDynamicStoreAddTemporaryValue(prefsPrivate->session, + prefsPrivate->sessionKeyLock, value)) { haveLock = TRUE; goto done; @@ -119,13 +118,13 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) /* * 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); @@ -136,88 +135,71 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait) 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; diff --git a/SystemConfiguration.fproj/SCPOpen.c b/SystemConfiguration.fproj/SCPOpen.c index 47f21f2..2c45b57 100644 --- a/SystemConfiguration.fproj/SCPOpen.c +++ b/SystemConfiguration.fproj/SCPOpen.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright(c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,6 +24,9 @@ /* * Modification History * + * February 16, 2004 Allan Nathanson + * - add preference notification APIs + * * June 1, 2001 Allan Nathanson * - public API conversion * @@ -41,13 +44,31 @@ #include #include + static CFStringRef __SCPreferencesCopyDescription(CFTypeRef cf) { CFAllocatorRef allocator = CFGetAllocator(cf); + SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)cf; CFMutableStringRef result; result = CFStringCreateMutable(allocator, 0); - CFStringAppendFormat(result, NULL, CFSTR(" {\n"), cf, allocator); + CFStringAppendFormat(result, NULL, CFSTR(" {"), 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; @@ -57,22 +78,26 @@ __SCPreferencesCopyDescription(CFTypeRef cf) { 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; } @@ -82,14 +107,14 @@ static CFTypeID __kSCPreferencesTypeID = _kCFRuntimeNotATypeID; 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 }; @@ -112,32 +137,41 @@ __SCPreferencesCreatePrivate(CFAllocatorRef allocator) /* 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; } @@ -153,15 +187,12 @@ __SCPreferencesCreate(CFAllocatorRef allocator, 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; } @@ -184,7 +215,9 @@ __SCPreferencesCreate(CFAllocatorRef allocator, * 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 */ @@ -211,9 +244,8 @@ __SCPreferencesCreate(CFAllocatorRef allocator, } } - /* start fresh */ - bzero(&statBuf, sizeof(statBuf)); - goto create_1; + /* no preference data, start fresh */ + goto done; case EACCES : sc_status = kSCStatusAccessError; break; @@ -221,25 +253,78 @@ __SCPreferencesCreate(CFAllocatorRef allocator, 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 @@ -248,7 +333,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, 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; @@ -262,11 +347,11 @@ __SCPreferencesCreate(CFAllocatorRef allocator, 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); } @@ -278,7 +363,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, */ 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; } @@ -298,7 +383,7 @@ __SCPreferencesCreate(CFAllocatorRef allocator, /* * 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, @@ -306,21 +391,15 @@ __SCPreferencesCreate(CFAllocatorRef allocator, 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; + } @@ -329,12 +408,6 @@ SCPreferencesCreate(CFAllocatorRef allocator, 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); } @@ -345,13 +418,6 @@ SCUserPreferencesCreate(CFAllocatorRef allocator, 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); } @@ -361,3 +427,282 @@ SCPreferencesGetTypeID(void) { 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; +} diff --git a/SystemConfiguration.fproj/SCPPath.c b/SystemConfiguration.fproj/SCPPath.c index 1fd06ed..2a700de 100644 --- a/SystemConfiguration.fproj/SCPPath.c +++ b/SystemConfiguration.fproj/SCPPath.c @@ -77,7 +77,7 @@ normalizePath(CFStringRef path) static Boolean -getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity) +getPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef *entity) { CFStringRef element; CFArrayRef elements; @@ -86,7 +86,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity) CFIndex nElements; CFIndex nLinks = 0; Boolean ok = FALSE; - SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; + SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs; CFDictionaryRef value = NULL; elements = normalizePath(path); @@ -95,14 +95,15 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity) 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); @@ -163,7 +164,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity) static Boolean -setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) +setPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef entity) { CFStringRef element; CFArrayRef elements; @@ -175,7 +176,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) CFDictionaryRef node = NULL; CFMutableArrayRef nodes; Boolean ok = FALSE; - SCPreferencesPrivateRef sessionPrivate = (SCPreferencesPrivateRef)session; + SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs; elements = normalizePath(path); if (elements == NULL) { @@ -183,6 +184,8 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) return FALSE; } + __SCPreferencesAccess(prefs); + restart : nElements = CFArrayGetCount(elements); @@ -190,8 +193,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) 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); @@ -258,11 +260,11 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) 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; @@ -291,7 +293,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity) CFStringRef -SCPreferencesPathCreateUniqueChild(SCPreferencesRef session, +SCPreferencesPathCreateUniqueChild(SCPreferencesRef prefs, CFStringRef prefix) { CFStringRef child; @@ -300,12 +302,13 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef session, 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... */ @@ -328,9 +331,7 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef session, 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; } @@ -341,55 +342,55 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef session, 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; } @@ -398,16 +399,16 @@ SCPreferencesPathGetLink(SCPreferencesRef session, 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) { @@ -415,13 +416,13 @@ SCPreferencesPathSetValue(SCPreferencesRef session, 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) { @@ -429,10 +430,10 @@ SCPreferencesPathSetLink(SCPreferencesRef session, 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) { @@ -440,7 +441,7 @@ SCPreferencesPathSetLink(SCPreferencesRef session, return FALSE; } - if (!getPath(session, link, &entity)) { + if (!getPath(prefs, link, &entity)) { // if bad link return FALSE; } @@ -450,7 +451,7 @@ SCPreferencesPathSetLink(SCPreferencesRef session, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(dict, kSCResvLink, link); - ok = setPath(session, path, dict); + ok = setPath(prefs, path, dict); CFRelease(dict); return ok; @@ -458,19 +459,20 @@ SCPreferencesPathSetLink(SCPreferencesRef session, 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; } @@ -481,7 +483,7 @@ SCPreferencesPathRemoveValue(SCPreferencesRef session, return FALSE; } - ok = setPath(session, path, NULL); + ok = setPath(prefs, path, NULL); CFRelease(elements); return ok; diff --git a/SystemConfiguration.fproj/SCPRemove.c b/SystemConfiguration.fproj/SCPRemove.c index 1de5c1d..9d7c73a 100644 --- a/SystemConfiguration.fproj/SCPRemove.c +++ b/SystemConfiguration.fproj/SCPRemove.c @@ -36,23 +36,24 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPSet.c b/SystemConfiguration.fproj/SCPSet.c index c5f6c3f..ed4beff 100644 --- a/SystemConfiguration.fproj/SCPSet.c +++ b/SystemConfiguration.fproj/SCPSet.c @@ -36,18 +36,19 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPUnlock.c b/SystemConfiguration.fproj/SCPUnlock.c index c41ee10..6b07676 100644 --- a/SystemConfiguration.fproj/SCPUnlock.c +++ b/SystemConfiguration.fproj/SCPUnlock.c @@ -36,30 +36,34 @@ #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; } diff --git a/SystemConfiguration.fproj/SCPreferences.h b/SystemConfiguration.fproj/SCPreferences.h index aaebc2a..b71d33d 100644 --- a/SystemConfiguration.fproj/SCPreferences.h +++ b/SystemConfiguration.fproj/SCPreferences.h @@ -26,59 +26,127 @@ #include +#include #include #include /*! @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 ( @@ -91,120 +159,116 @@ 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 ); @@ -212,20 +276,20 @@ SCPreferencesGetValue ( @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 ); @@ -234,19 +298,19 @@ SCPreferencesAddValue ( @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 ); @@ -255,21 +319,96 @@ SCPreferencesSetValue ( @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 */ diff --git a/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h b/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h new file mode 100644 index 0000000..d0d56e8 --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h @@ -0,0 +1,59 @@ +/* + * 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 +#include +#include + + +/*! + @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 */ diff --git a/SystemConfiguration.fproj/SCPreferencesInternal.h b/SystemConfiguration.fproj/SCPreferencesInternal.h index b1f669d..971cae9 100644 --- a/SystemConfiguration.fproj/SCPreferencesInternal.h +++ b/SystemConfiguration.fproj/SCPreferencesInternal.h @@ -48,6 +48,9 @@ typedef struct { /* base CFType information */ CFRuntimeBase cfBase; + /* lock */ + pthread_mutex_t lock; + /* session name */ CFStringRef name; @@ -58,7 +61,7 @@ typedef struct { Boolean perUser; CFStringRef user; - /* configuration file path */ + /* configuration file */ char *path; char *newPath; @@ -73,6 +76,12 @@ typedef struct { CFStringRef sessionKeyCommit; CFStringRef sessionKeyApply; + /* run loop source, callout, context, rl scheduling info */ + CFRunLoopSourceRef rls; + SCPreferencesCallBack rlsFunction; + SCPreferencesContext rlsContext; + CFMutableArrayRef rlList; + /* preferences */ CFMutableDictionaryRef prefs; @@ -103,6 +112,12 @@ __SCPreferencesCreate (CFAllocatorRef allocator, Boolean perUser, CFStringRef user); +Boolean +__SCPreferencesAccess (SCPreferencesRef prefs); + +Boolean +__SCPreferencesAddSession (SCPreferencesRef prefs); + CFDataRef __SCPSignatureFromStatbuf (const struct stat *statBuf); diff --git a/SystemConfiguration.fproj/SCPreferencesPath.h b/SystemConfiguration.fproj/SCPreferencesPath.h index e3a85cd..7db6e6a 100644 --- a/SystemConfiguration.fproj/SCPreferencesPath.h +++ b/SystemConfiguration.fproj/SCPreferencesPath.h @@ -31,44 +31,46 @@ /*! @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. - -
-	
<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> -
- - 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. + +
+	@textblock
+	
+		key1
+		val1
+		key2
+		val2
+		path1
+		
+			key3
+			val3
+			key4
+			val4
+		
+	
+	@/textblock
+	
+ + 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. */ @@ -79,15 +81,14 @@ __BEGIN_DECLS @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 ); @@ -95,15 +96,14 @@ SCPreferencesPathCreateUniqueChild ( @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 ); @@ -111,31 +111,29 @@ SCPreferencesPathGetValue ( @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 ); @@ -144,16 +142,15 @@ SCPreferencesPathSetValue ( @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 ); @@ -161,14 +158,13 @@ SCPreferencesPathSetLink ( /*! @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 ); diff --git a/SystemConfiguration.fproj/SCPreferencesPathKey.c b/SystemConfiguration.fproj/SCPreferencesPathKey.c new file mode 100644 index 0000000..ef4df79 --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesPathKey.c @@ -0,0 +1,234 @@ +/* + * 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 + * - initial revision + */ + +#include + +#include + +__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; +} diff --git a/SystemConfiguration.fproj/SCPreferencesPathKey.h b/SystemConfiguration.fproj/SCPreferencesPathKey.h new file mode 100644 index 0000000..67592cb --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesPathKey.h @@ -0,0 +1,134 @@ +/* + * 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 +#include +#include + + +/*! + @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 */ diff --git a/SystemConfiguration.fproj/SCPreferencesPrivate.h b/SystemConfiguration.fproj/SCPreferencesPrivate.h index 23c37ef..3b687ce 100644 --- a/SystemConfiguration.fproj/SCPreferencesPrivate.h +++ b/SystemConfiguration.fproj/SCPreferencesPrivate.h @@ -24,10 +24,17 @@ #ifndef _SCPREFERENCESPRIVATE_H #define _SCPREFERENCESPRIVATE_H + +#include +#include #include #include +/*! + @header SCPreferencesPrivate + */ + /*! @enum SCPreferencesKeyType @discussion Used with the SCDynamicStoreKeyCreatePreferences() function @@ -46,6 +53,7 @@ enum { }; typedef int32_t SCPreferencesKeyType; + __BEGIN_DECLS /*! @@ -65,7 +73,7 @@ SCDynamicStoreKeyCreatePreferences ( 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 ( diff --git a/SystemConfiguration.fproj/SCPreferencesSetSpecific.h b/SystemConfiguration.fproj/SCPreferencesSetSpecific.h index 4ff04ea..6cce489 100644 --- a/SystemConfiguration.fproj/SCPreferencesSetSpecific.h +++ b/SystemConfiguration.fproj/SCPreferencesSetSpecific.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,9 +31,13 @@ /*! @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. */ @@ -41,16 +45,16 @@ __BEGIN_DECLS /*! @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 ( @@ -61,18 +65,18 @@ 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 ( diff --git a/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h b/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h new file mode 100644 index 0000000..51e4c7e --- /dev/null +++ b/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h @@ -0,0 +1,66 @@ +/* + * 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 +#include +#include + + +/*! + @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 */ diff --git a/SystemConfiguration.fproj/SCPrivate.h b/SystemConfiguration.fproj/SCPrivate.h index 5ee8e13..1b1d0a5 100644 --- a/SystemConfiguration.fproj/SCPrivate.h +++ b/SystemConfiguration.fproj/SCPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,6 +25,8 @@ #define _SCPRIVATE_H #include +#include +#include #include @@ -33,6 +35,12 @@ #include #include +#include +#include + +/*! + @header SCPrivate + */ /* framework variables */ extern Boolean _sc_debug; /* TRUE if debugging enabled */ @@ -43,19 +51,19 @@ __BEGIN_DECLS /*! @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 */ @@ -64,14 +72,14 @@ Boolean _SCSerialize (CFPropertyListRef obj, 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". @@ -81,14 +89,14 @@ Boolean _SCUnserialize (CFPropertyListRef *obj, 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 */ @@ -97,14 +105,14 @@ Boolean _SCSerializeString (CFStringRef str, 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". @@ -114,12 +122,12 @@ Boolean _SCUnserializeString (CFStringRef *str, 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 */ @@ -127,20 +135,20 @@ Boolean _SCSerializeData (CFDataRef 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 @@ -150,7 +158,7 @@ Boolean _SCUnserializeData (CFDataRef *data, */ CFDictionaryRef _SCSerializeMultiple (CFDictionaryRef dict); -/* +/*! @function _SCUnserializeMultiple @discussion Convert a CFDictionary containing a set of CFData values into a CFDictionary containing a set of serialized @@ -160,11 +168,11 @@ CFDictionaryRef _SCSerializeMultiple (CFDictionaryRef dict); */ 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. @@ -179,7 +187,18 @@ char * _SC_cfstring_to_cstring (CFStringRef cfstr, 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 @@ -193,7 +212,7 @@ void SCLog (Boolean condition, CFStringRef formatString, ...); -/* +/*! @function SCPrint @discussion Conditionally issue a debug message. @param condition A boolean value indicating if the message should be written @@ -207,7 +226,7 @@ void SCPrint (Boolean condition, 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 @@ -221,6 +240,33 @@ void SCTrace (Boolean condition, 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 */ diff --git a/SystemConfiguration.fproj/SCProxies.c b/SystemConfiguration.fproj/SCProxies.c index 85f55eb..9caf2cd 100644 --- a/SystemConfiguration.fproj/SCProxies.c +++ b/SystemConfiguration.fproj/SCProxies.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,6 +32,9 @@ #include #include +#include + + CFStringRef SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator) { @@ -41,39 +44,222 @@ 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; } diff --git a/SystemConfiguration.fproj/SCSchemaDefinitions.c b/SystemConfiguration.fproj/SCSchemaDefinitions.c new file mode 100644 index 0000000..f7d2d40 --- /dev/null +++ b/SystemConfiguration.fproj/SCSchemaDefinitions.c @@ -0,0 +1,254 @@ +/* + * This file is automatically generated + * DO NOT EDIT! + */ + +#include + +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"); diff --git a/SystemConfiguration.fproj/SCSchemaDefinitions.h b/SystemConfiguration.fproj/SCSchemaDefinitions.h new file mode 100644 index 0000000..d29c11d --- /dev/null +++ b/SystemConfiguration.fproj/SCSchemaDefinitions.h @@ -0,0 +1,3779 @@ +/* + * 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 + */ + +/* + * 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 + * + * 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 + +/* + * 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 + #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 + #define SC_SCHEMA_DECLARATION(k,q) extern const CFStringRef k q + #else + #import + #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 + #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 */ diff --git a/SystemConfiguration.fproj/SystemConfiguration.h b/SystemConfiguration.fproj/SystemConfiguration.h index 5d74bbc..5ea4d25 100644 --- a/SystemConfiguration.fproj/SystemConfiguration.h +++ b/SystemConfiguration.fproj/SystemConfiguration.h @@ -29,25 +29,23 @@ /*! - @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 @@ -56,25 +54,22 @@ @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 */ @@ -88,13 +83,13 @@ enum { 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 */ @@ -103,7 +98,7 @@ enum { 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 */ }; @@ -118,6 +113,9 @@ enum { #include #include +/* network configuration */ +#include + /* store and preference scheme definitions */ #include @@ -130,17 +128,18 @@ __BEGIN_DECLS /*! @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); diff --git a/SystemConfiguration.fproj/VLANConfiguration.c b/SystemConfiguration.fproj/VLANConfiguration.c index 7072892..97367ce 100644 --- a/SystemConfiguration.fproj/VLANConfiguration.c +++ b/SystemConfiguration.fproj/VLANConfiguration.c @@ -33,19 +33,19 @@ #include #include +#include #include #include #include #include +#include #include -#define KERNEL_PRIVATE #include -#undef KERNEL_PRIVATE #include #include #include -#define KERNEL_PRIVATE 1 +#define KERNEL_PRIVATE #include #include #undef KERNEL_PRIVATE @@ -73,60 +73,9 @@ inet_dgram_socket() } -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; @@ -152,23 +101,25 @@ _VLANDevice_set(int s, CFStringRef interface, CFStringRef device, CFNumberRef ta 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; @@ -189,16 +140,13 @@ _VLANDevice_unset(int s, CFStringRef interface) 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 */ } @@ -217,7 +165,7 @@ IsVLANSupported(CFStringRef device) /* 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 } @@ -335,8 +283,6 @@ __VLANInterfaceDeallocate(CFTypeRef cf) { VLANInterfacePrivateRef vlanPrivate = (VLANInterfacePrivateRef)cf; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceDeallocate:")); - /* release resources */ CFRelease(vlanPrivate->ifname); @@ -430,8 +376,6 @@ __VLANInterfaceCreatePrivate(CFAllocatorRef allocator, VLANInterfacePrivateRef vlanPrivate; uint32_t size; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceCreatePrivate:")); - /* initialize runtime */ pthread_once(&vlanInterface_init, __VLANInterfaceInitialize); @@ -655,8 +599,6 @@ __VLANPreferencesDeallocate(CFTypeRef cf) { VLANPreferencesPrivateRef prefsPrivate = (VLANPreferencesPrivateRef)cf; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesDeallocate:")); - /* release resources */ pthread_mutex_destroy(&prefsPrivate->lock); @@ -736,7 +678,7 @@ _VLANPreferencesCopyActiveInterfaces() 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); @@ -854,8 +796,6 @@ VLANPreferencesCreate(CFAllocatorRef allocator) VLANPreferencesPrivateRef prefsPrivate; uint32_t size; - SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesCreate:")); - /* initialize runtime */ pthread_once(&vlanPreferences_init, __VLANPreferencesInitialize); @@ -865,7 +805,7 @@ VLANPreferencesCreate(CFAllocatorRef allocator) __kVLANPreferencesTypeID, size, NULL); - if (!prefsPrivate) { + if (prefsPrivate == NULL) { return NULL; } @@ -1099,6 +1039,9 @@ VLANPreferencesAddInterface(VLANPreferencesRef prefs, 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) { @@ -1112,9 +1055,6 @@ VLANPreferencesAddInterface(VLANPreferencesRef prefs, (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans); CFRelease(newVlans); - /* yes, we've change the configuration */ - setConfigurationChanged(prefs); - next_if : CFRelease(vlan_if); } @@ -1253,19 +1193,18 @@ VLANPreferencesUpdateInterface(VLANPreferencesRef prefs, 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 : @@ -1313,6 +1252,9 @@ VLANPreferencesRemoveInterface(VLANPreferencesRef prefs, goto done; } + /* yes, we're going to be changing the configuration */ + setConfigurationChanged(prefs); + /* remove the vlan */ allocator = CFGetAllocator(prefs); @@ -1322,9 +1264,6 @@ VLANPreferencesRemoveInterface(VLANPreferencesRef prefs, (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans); CFRelease(newVlans); - /* yes, we've change the configuration */ - setConfigurationChanged(prefs); - ok = TRUE; done : @@ -1433,8 +1372,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs) s = inet_dgram_socket(); } - ok = _VLAN_destroy(s, a_vlan_if); + ok = __destroyInterface(s, a_vlan_if); if (!ok) { + _SCErrorSet(kSCStatusFailed); goto done; } } @@ -1491,8 +1431,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs) } } 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; } } @@ -1509,8 +1450,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs) s = inet_dgram_socket(); } - ok = _VLAN_create(s, c_vlan_if); + ok = __createInterface(s, c_vlan_if); if (!ok) { + _SCErrorSet(kSCStatusFailed); goto done; } @@ -1563,8 +1505,6 @@ VLANPreferencesApplyChanges(VLANPreferencesRef prefs) goto done; } - ok = TRUE; - done : pthread_mutex_unlock(&prefsPrivate->lock); diff --git a/SystemConfiguration.fproj/VLANConfiguration.h b/SystemConfiguration.fproj/VLANConfiguration.h index bfa115e..9fa8c9b 100644 --- a/SystemConfiguration.fproj/VLANConfiguration.h +++ b/SystemConfiguration.fproj/VLANConfiguration.h @@ -24,6 +24,9 @@ #ifndef _VLANCONFIGURATION_H #define _VLANCONFIGURATION_H +/*! + @header VLANConfiguration +*/ #include #include diff --git a/SystemConfiguration.fproj/VLANConfigurationPrivate.h b/SystemConfiguration.fproj/VLANConfigurationPrivate.h index 811e616..bf0b405 100644 --- a/SystemConfiguration.fproj/VLANConfigurationPrivate.h +++ b/SystemConfiguration.fproj/VLANConfigurationPrivate.h @@ -29,6 +29,14 @@ #include +#include + + +/*! + @header VLANConfigurationPrivate + */ + + #define VLAN_PREFERENCES_ID CFSTR("VirtualNetworkInterfaces.plist") diff --git a/SystemConfiguration.fproj/config.defs b/SystemConfiguration.fproj/config.defs index b1ed4c8..fc9f340 100644 --- a/SystemConfiguration.fproj/config.defs +++ b/SystemConfiguration.fproj/config.defs @@ -66,6 +66,7 @@ type task_move_send_t = MACH_MSG_TYPE_MOVE_SEND routine configopen ( server : mach_port_t; name : xmlData; + options : xmlData; out session : mach_port_move_send_t; out status : int); diff --git a/SystemConfiguration.fproj/dy_framework.c b/SystemConfiguration.fproj/dy_framework.c index 33046cd..f31634d 100644 --- a/SystemConfiguration.fproj/dy_framework.c +++ b/SystemConfiguration.fproj/dy_framework.c @@ -61,7 +61,8 @@ __loadIOKit(void) { __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)); @@ -73,7 +74,8 @@ _IOBSDNameMatching(mach_port_t masterPort, unsigned int options, const char *bsd __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)); @@ -85,7 +87,8 @@ _IOIteratorNext(io_iterator_t iterator) __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)); @@ -94,10 +97,37 @@ _IOMasterPort(mach_port_t bootstrapPort, mach_port_t *masterPort) } +__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)); @@ -109,7 +139,8 @@ _IOObjectRelease(io_object_t object) __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)); @@ -121,7 +152,8 @@ _IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFA __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)); @@ -130,22 +162,50 @@ _IORegistryEntryCreateCFProperties(io_registry_entry_t entry, CFMutableDictionar } +__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)); @@ -154,10 +214,24 @@ _IORegistryEntryGetPath(io_registry_entry_t entry, const io_name_t plane, io_str } +__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)); @@ -169,7 +243,8 @@ _IOServiceGetMatchingServices(mach_port_t masterPort, CFDictionaryRef matching, __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)); @@ -201,7 +276,8 @@ __loadSecurity(void) { __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)); @@ -212,7 +288,8 @@ _SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, __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)); @@ -223,7 +300,8 @@ _SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *i __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)); diff --git a/SystemConfiguration.fproj/dy_framework.h b/SystemConfiguration.fproj/dy_framework.h index 6560839..e21bcb8 100644 --- a/SystemConfiguration.fproj/dy_framework.h +++ b/SystemConfiguration.fproj/dy_framework.h @@ -54,6 +54,20 @@ _IOMasterPort ( ); #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 @@ -78,6 +92,22 @@ _IORegistryEntryCreateCFProperties ( ); #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, @@ -94,6 +124,16 @@ _IORegistryEntryGetPath ( ); #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, diff --git a/SystemConfiguration.fproj/genSCPreferences.c b/SystemConfiguration.fproj/genSCPreferences.c index 49d96c4..9785c7a 100644 --- a/SystemConfiguration.fproj/genSCPreferences.c +++ b/SystemConfiguration.fproj/genSCPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,6 +31,11 @@ /* * 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 * @@ -54,7 +59,7 @@ 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" @@ -79,13 +84,16 @@ char copyright_string[] = 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" @@ -116,7 +124,7 @@ typedef enum { #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" @@ -127,14 +135,15 @@ typedef enum { #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" @@ -150,9 +159,9 @@ typedef enum { #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" @@ -161,6 +170,7 @@ typedef enum { #define DIALMODE "DialMode" #define DIALONDEMAND "DialOnDemand" #define DISCONNECTONANSWER "DisconnectOnAnswer" +#define DISCONNECTONFASTUSERSWITCH "DisconnectOnFastUserSwitch" #define DISCONNECTONIDLE "DisconnectOnIdle" #define DISCONNECTONIDLETIMER "DisconnectOnIdleTimer" #define DISCONNECTONLOGOUT "DisconnectOnLogout" @@ -169,39 +179,32 @@ typedef enum { #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" @@ -218,8 +221,7 @@ typedef enum { #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" @@ -227,9 +229,12 @@ typedef enum { #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" @@ -240,23 +245,25 @@ typedef enum { #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" @@ -264,13 +271,12 @@ typedef enum { #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" @@ -280,26 +286,20 @@ typedef enum { #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" @@ -309,13 +309,19 @@ typedef enum { #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" @@ -329,391 +335,434 @@ struct { 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 }, }; @@ -733,6 +782,8 @@ setmax(int *max, char **maxstr, char *str) enum { gen_header_e, + gen_comments_e, + gen_headerdoc_e, gen_hfile_e, gen_cfile_e, }; @@ -752,195 +803,205 @@ dump_names(int type) 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 \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; } @@ -967,13 +1028,22 @@ main(int argc, char * argv[]) printf("#ifndef _SCSCHEMADEFINITIONS_10_1_H\n#define _SCSCHEMADEFINITIONS_10_1_H\n\n"); - printf("#ifndef SCSTR\n"); - printf("#include \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 instead\n"); + printf("#warning of including this file directly.\n"); + printf("#include \n"); + printf("#endif\n\n"); + +// printf("#ifndef SCSTR\n"); +// printf("#include \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) { @@ -981,35 +1051,115 @@ main(int argc, char * argv[]) 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 \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 \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 \n"); - printf("#define " SC_SCHEMA_DECLARATION "(x)\textern const CFStringRef x\n"); - printf("#else\n"); - printf("#import \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 \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 \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 \n"); + printf(" #ifndef SCSTR\n"); + printf(" #include \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 \n"); + printf(" #define " SC_SCHEMA_DECLARATION "(k,q)\textern const CFStringRef k q\n"); + printf(" #else\n"); + printf(" #import \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 \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) { diff --git a/SystemConfiguration.fproj/h.template b/SystemConfiguration.fproj/h.template deleted file mode 100644 index f3c1b04..0000000 --- a/SystemConfiguration.fproj/h.template +++ /dev/null @@ -1,11 +0,0 @@ -$$ -/* $FILENAME$ created by $USERNAME$ on $DATE$ */ - -#import - -@interface $FILENAMESANSEXTENSION$ : NSObject -{ - -} - -@end diff --git a/SystemConfiguration.fproj/m.template b/SystemConfiguration.fproj/m.template deleted file mode 100644 index 1216fe5..0000000 --- a/SystemConfiguration.fproj/m.template +++ /dev/null @@ -1,18 +0,0 @@ -$$ 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 diff --git a/SystemConfiguration.fproj/ppp.c b/SystemConfiguration.fproj/ppp.c deleted file mode 100644 index 07b9ffc..0000000 --- a/SystemConfiguration.fproj/ppp.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * 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 - * - use ServiceID *or* LinkID - * - * Oct 25, 2002 Christophe Allie - * - use ServiceID instead of LinkID - * - * Feb 28, 2002 Christophe Allie - * - socket API fixes - * - * Feb 10, 2001 Allan Nathanson - * - cleanup API - * - * Feb 2000 Christophe Allie - * - initial revision - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#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; -} diff --git a/SystemConfiguration.fproj/ppp.h b/SystemConfiguration.fproj/ppp.h deleted file mode 100644 index c7135d5..0000000 --- a/SystemConfiguration.fproj/ppp.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 - * - use ServiceID *or* LinkID - * - * Feb 10, 2001 Allan Nathanson - * - cleanup API - * - * Feb 2000 Christophe Allie - * - initial revision (as ppplib.h) - */ - -#ifndef _PPP_H -#define _PPP_H - -#include -#include -#include - -__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 */ diff --git a/SystemConfiguration.fproj/pppcontroller.defs b/SystemConfiguration.fproj/pppcontroller.defs new file mode 100644 index 0000000..6c6985c --- /dev/null +++ b/SystemConfiguration.fproj/pppcontroller.defs @@ -0,0 +1,25 @@ +/* + * 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 diff --git a/configd.tproj/Makefile b/configd.tproj/Makefile deleted file mode 100644 index c6bcd09..0000000 --- a/configd.tproj/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# -# 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 diff --git a/configd.tproj/Makefile.postamble b/configd.tproj/Makefile.postamble deleted file mode 100644 index 0bd75f1..0000000 --- a/configd.tproj/Makefile.postamble +++ /dev/null @@ -1,106 +0,0 @@ -############################################################################### -# 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 - diff --git a/configd.tproj/Makefile.preamble b/configd.tproj/Makefile.preamble deleted file mode 100644 index ea74460..0000000 --- a/configd.tproj/Makefile.preamble +++ /dev/null @@ -1,143 +0,0 @@ -############################################################################### -# 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: <> -# 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 - diff --git a/configd.tproj/PB.project b/configd.tproj/PB.project deleted file mode 100644 index 3ceaa3c..0000000 --- a/configd.tproj/PB.project +++ /dev/null @@ -1,80 +0,0 @@ -{ - "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"; -} diff --git a/configd.tproj/_SCD.c b/configd.tproj/_SCD.c index a6a31da..061b514 100644 --- a/configd.tproj/_SCD.c +++ b/configd.tproj/_SCD.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,7 +32,11 @@ */ +#include + #include "configd.h" +#include "configd_server.h" +#include "session.h" __private_extern__ CFMutableDictionaryRef sessionData = NULL; @@ -133,7 +137,7 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) 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; @@ -164,7 +168,9 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) CFDictionarySetValue(storeData, watchedKey, newDict); CFRelease(newDict); +#ifdef DEBUG SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey); +#endif /* DEBUG */ return; } @@ -190,7 +196,9 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) 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); @@ -209,8 +217,10 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) 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); @@ -251,7 +261,159 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) } 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; } diff --git a/configd.tproj/_SCD.h b/configd.tproj/_SCD.h index 98cb81e..db03de8 100644 --- a/configd.tproj/_SCD.h +++ b/configd.tproj/_SCD.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -27,7 +27,7 @@ * June 1, 2001 Allan Nathanson * - public API conversion * - * June 2, 2000 Allan Nathanson + * June 2, 2000 Allan Nathanson * - initial revision */ @@ -119,12 +119,8 @@ __SCDynamicStoreCopyKeyList (SCDynamicStoreRef store, int __SCDynamicStoreAddValue (SCDynamicStoreRef store, CFStringRef key, - CFDataRef value); - -int -__SCDynamicStoreAddTemporaryValue (SCDynamicStoreRef store, - CFStringRef key, - CFDataRef value); + CFDataRef value, + Boolean internal); int __SCDynamicStoreCopyValue (SCDynamicStoreRef store, @@ -217,6 +213,9 @@ void _removeWatcher (CFNumberRef sessionNum, CFStringRef watchedKey); +void +pushNotifications (); + __END_DECLS #endif /* !_S_SCD_H */ diff --git a/configd.tproj/_configadd.c b/configd.tproj/_configadd.c index 5e0d501..792e57a 100644 --- a/configd.tproj/_configadd.c +++ b/configd.tproj/_configadd.c @@ -36,28 +36,23 @@ __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); } /* @@ -84,7 +79,9 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val 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; } @@ -96,7 +93,9 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val /* * 4. Release our lock. */ + done: + __SCDynamicStoreUnlock(store, TRUE); return sc_status; @@ -114,44 +113,102 @@ _configadd(mach_port_t server, 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; } diff --git a/configd.tproj/_configadd_s.c b/configd.tproj/_configadd_s.c deleted file mode 100644 index 7a690d7..0000000 --- a/configd.tproj/_configadd_s.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 - * - public API conversion - * - * October 17, 2000 Allan Nathanson - * - 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; -} diff --git a/configd.tproj/_configclose.c b/configd.tproj/_configclose.c index 6b3c72d..fbd48ab 100644 --- a/configd.tproj/_configclose.c +++ b/configd.tproj/_configclose.c @@ -102,14 +102,12 @@ __private_extern__ 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 */ @@ -177,14 +175,12 @@ __SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal) } /* - * 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); @@ -204,11 +200,6 @@ _configclose(mach_port_t server, int *sc_status) { 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; @@ -219,7 +210,6 @@ _configclose(mach_port_t server, int *sc_status) */ *sc_status = __SCDynamicStoreClose(&mySession->store, FALSE); if (*sc_status != kSCStatusOK) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreClose(): %s"), SCErrorString(*sc_status)); return KERN_SUCCESS; } diff --git a/configd.tproj/_configget.c b/configd.tproj/_configget.c index fa889fe..caeae32 100644 --- a/configd.tproj/_configget.c +++ b/configd.tproj/_configget.c @@ -41,11 +41,6 @@ __SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *v 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 */ } @@ -67,14 +62,6 @@ __SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *v /* 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; } @@ -89,41 +76,33 @@ _configget(mach_port_t server, 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 */ @@ -131,7 +110,7 @@ _configget(mach_port_t server, CFRelease(value); if (!ok) { *sc_status = kSCStatusFailed; - return KERN_SUCCESS; + goto done; } /* @@ -139,6 +118,9 @@ _configget(mach_port_t server, */ *newInstance = 1; + done : + + if (key) CFRelease(key); return KERN_SUCCESS; } @@ -202,12 +184,6 @@ __SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRe 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 */ } @@ -243,14 +219,6 @@ __SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRe /* 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; } @@ -271,23 +239,19 @@ _configget_m(mach_port_t server, 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; } } @@ -295,34 +259,33 @@ _configget_m(mach_port_t server, /* 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; } diff --git a/configd.tproj/_configlist.c b/configd.tproj/_configlist.c index a43e889..6591a99 100644 --- a/configd.tproj/_configlist.c +++ b/configd.tproj/_configlist.c @@ -48,31 +48,22 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is 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]; @@ -103,7 +94,7 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is 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; } @@ -126,7 +117,7 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is &preg, reErrBuf, sizeof(reErrBuf)); - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); + SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList regexec() failed: %s"), reErrBuf); break; } } @@ -153,8 +144,8 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is regfree(&preg); } - *subKeys = keyArray; - + *subKeys = CFArrayCreateCopy(NULL, keyArray); + CFRelease(keyArray); return kSCStatusOK; } @@ -170,15 +161,10 @@ _configlist(mach_port_t server, 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; @@ -186,25 +172,22 @@ _configlist(mach_port_t 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 = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys); - CFRelease(key); if (*sc_status != kSCStatusOK) { - return KERN_SUCCESS; + goto done; } /* serialize the list of keys */ @@ -212,8 +195,11 @@ _configlist(mach_port_t server, CFRelease(subKeys); if (!ok) { *sc_status = kSCStatusFailed; - return KERN_SUCCESS; + goto done; } + done : + + if (key) CFRelease(key); return KERN_SUCCESS; } diff --git a/configd.tproj/_configlock.c b/configd.tproj/_configlock.c index 02ecc71..c383da6 100644 --- a/configd.tproj/_configlock.c +++ b/configd.tproj/_configlock.c @@ -40,10 +40,8 @@ __private_extern__ 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 */ @@ -100,11 +98,6 @@ _configlock(mach_port_t server, int *sc_status) { 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; @@ -112,7 +105,6 @@ _configlock(mach_port_t server, int *sc_status) *sc_status = __SCDynamicStoreLock(mySession->store, FALSE); if (*sc_status != kSCStatusOK) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" SCDynamicStoreLock(): %s"), SCErrorString(*sc_status)); return KERN_SUCCESS; } diff --git a/configd.tproj/_confignotify.c b/configd.tproj/_confignotify.c index 892d542..e4e0dea 100644 --- a/configd.tproj/_confignotify.c +++ b/configd.tproj/_confignotify.c @@ -41,11 +41,6 @@ __SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key, Boolean in 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 */ } @@ -102,34 +97,29 @@ _confignotify(mach_port_t server, 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; } diff --git a/configd.tproj/_configopen.c b/configd.tproj/_configopen.c index 82630c9..facaf7e 100644 --- a/configd.tproj/_configopen.c +++ b/configd.tproj/_configopen.c @@ -39,11 +39,6 @@ __private_extern__ 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 */ @@ -85,41 +80,66 @@ kern_return_t _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 */ @@ -150,11 +170,19 @@ _configopen(mach_port_t server, } *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(), @@ -165,17 +193,18 @@ _configopen(mach_port_t server, 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. @@ -191,10 +220,13 @@ _configopen(mach_port_t server, &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; } diff --git a/configd.tproj/_configremove.c b/configd.tproj/_configremove.c index 0b0ad14..d3bcb00 100644 --- a/configd.tproj/_configremove.c +++ b/configd.tproj/_configremove.c @@ -44,11 +44,6 @@ __SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key, Boolean in 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 */ } @@ -141,34 +136,30 @@ _configremove(mach_port_t server, 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; } diff --git a/configd.tproj/_configset.c b/configd.tproj/_configset.c index 08747c3..2cd2ce5 100644 --- a/configd.tproj/_configset.c +++ b/configd.tproj/_configset.c @@ -49,24 +49,15 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val 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); } @@ -101,24 +92,91 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val 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); /* @@ -152,6 +210,8 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val */ CFSetAddValue(changedKeys, key); + done : + /* * 8. Release our lock. */ @@ -172,45 +232,39 @@ _configset(mach_port_t server, 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; } @@ -271,17 +325,6 @@ __SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet, 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 */ } @@ -349,24 +392,21 @@ _configset_m(mach_port_t server, 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; } } @@ -374,8 +414,12 @@ _configset_m(mach_port_t server, /* 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; } } @@ -383,17 +427,18 @@ _configset_m(mach_port_t server, /* 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; } diff --git a/configd.tproj/_configtouch.c b/configd.tproj/_configtouch.c index 8c62cf4..d358420 100644 --- a/configd.tproj/_configtouch.c +++ b/configd.tproj/_configtouch.c @@ -42,11 +42,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) 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 */ } @@ -74,7 +69,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) /* 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; @@ -85,13 +79,12 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) /* 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); @@ -99,7 +92,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key) break; } default : - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status)); goto done; } @@ -125,34 +117,29 @@ _configtouch(mach_port_t server, 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; } diff --git a/configd.tproj/_configunlock.c b/configd.tproj/_configunlock.c index c00fa5d..21d0815 100644 --- a/configd.tproj/_configunlock.c +++ b/configd.tproj/_configunlock.c @@ -218,7 +218,7 @@ _cleanupRemovedSessionKeys(const void *value, void *context) i = CFArrayGetFirstIndexOfValue(sessionKeys, CFRangeMake(0, CFArrayGetCount(sessionKeys)), key); - if (i == -1) { + if (i == kCFNotFound) { /* if this session key has already been removed */ goto done; } @@ -252,10 +252,8 @@ __private_extern__ 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 */ @@ -284,13 +282,6 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) 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. @@ -308,10 +299,6 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive) 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")); @@ -329,11 +316,6 @@ _configunlock(mach_port_t server, int *sc_status) { 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; @@ -341,7 +323,6 @@ _configunlock(mach_port_t server, int *sc_status) *sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE); if (*sc_status != kSCStatusOK) { - SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreUnlock(): %s"), SCErrorString(*sc_status)); return KERN_SUCCESS; } diff --git a/configd.tproj/_notifyadd.c b/configd.tproj/_notifyadd.c index 55a6ec2..27c6a88 100644 --- a/configd.tproj/_notifyadd.c +++ b/configd.tproj/_notifyadd.c @@ -60,12 +60,6 @@ __SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean 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 */ } @@ -131,35 +125,30 @@ _notifyadd(mach_port_t server, 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; } @@ -231,12 +220,6 @@ __SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CF 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 */ } @@ -292,15 +275,10 @@ _notifyset(mach_port_t server, 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)) { diff --git a/configd.tproj/_notifycancel.c b/configd.tproj/_notifycancel.c index 66673a3..06194ed 100644 --- a/configd.tproj/_notifycancel.c +++ b/configd.tproj/_notifycancel.c @@ -43,12 +43,6 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) { 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. */ @@ -61,7 +55,7 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store) * 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; } @@ -103,20 +97,11 @@ _notifycancel(mach_port_t server, { 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; } diff --git a/configd.tproj/_notifychanges.c b/configd.tproj/_notifychanges.c index 80be213..9b2c902 100644 --- a/configd.tproj/_notifychanges.c +++ b/configd.tproj/_notifychanges.c @@ -43,8 +43,6 @@ __SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store, CFArrayRef *notifierKe 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 */ } @@ -87,11 +85,6 @@ _notifychanges(mach_port_t server, 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; diff --git a/configd.tproj/_notifyremove.c b/configd.tproj/_notifyremove.c index 9463d39..adc4676 100644 --- a/configd.tproj/_notifyremove.c +++ b/configd.tproj/_notifyremove.c @@ -44,12 +44,6 @@ __SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boole 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 */ } @@ -107,38 +101,33 @@ _notifyremove(mach_port_t server, 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; } diff --git a/configd.tproj/_notifyviafd.c b/configd.tproj/_notifyviafd.c index 4f6b317..6a11e21 100644 --- a/configd.tproj/_notifyviafd.c +++ b/configd.tproj/_notifyviafd.c @@ -52,8 +52,6 @@ __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, 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 */ } @@ -64,7 +62,7 @@ __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef store, } 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; } @@ -100,31 +98,27 @@ _notifyviafd(mach_port_t server, 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; } @@ -134,10 +128,12 @@ _notifyviafd(mach_port_t server, 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 */ @@ -154,7 +150,7 @@ _notifyviafd(mach_port_t server, /* 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; @@ -162,18 +158,19 @@ _notifyviafd(mach_port_t server, 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; diff --git a/configd.tproj/_notifyviaport.c b/configd.tproj/_notifyviaport.c index a0d1f7b..4b7df81 100644 --- a/configd.tproj/_notifyviaport.c +++ b/configd.tproj/_notifyviaport.c @@ -44,8 +44,6 @@ __SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, 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 */ } @@ -92,20 +90,13 @@ _notifyviaport(mach_port_t server, 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); } diff --git a/configd.tproj/_notifyviasignal.c b/configd.tproj/_notifyviasignal.c index 7bd5553..28aea5a 100644 --- a/configd.tproj/_notifyviasignal.c +++ b/configd.tproj/_notifyviasignal.c @@ -31,6 +31,9 @@ * - initial revision */ +#include +#include + #include "configd.h" #include "configd_server.h" #include "session.h" @@ -43,8 +46,6 @@ __SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig) 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 */ } @@ -100,13 +101,6 @@ _notifyviasignal(mach_port_t server, 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 */ @@ -160,19 +154,21 @@ _notifyviasignal(mach_port_t server, 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; } diff --git a/configd.tproj/_snapshot.c b/configd.tproj/_snapshot.c index 60869d5..22b2326 100644 --- a/configd.tproj/_snapshot.c +++ b/configd.tproj/_snapshot.c @@ -78,7 +78,7 @@ _expandStore(CFDictionaryRef storeData) if (data) { CFPropertyListRef plist; - if (!_SCUnserialize(&plist, data, NULL, NULL)) { + if (!_SCUnserialize(&plist, data, NULL, 0)) { goto done; } @@ -130,8 +130,6 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; CFDataRef xmlData; - SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSnapshot:")); - /* check credentials */ mySession = getSession(storePrivate->server); @@ -151,7 +149,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) 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; } @@ -169,7 +167,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) 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; } @@ -187,7 +185,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store) 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; } @@ -205,17 +203,11 @@ _snapshot(mach_port_t server, int *sc_status) { 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; } diff --git a/configd.tproj/config.defs b/configd.tproj/config.defs deleted file mode 100644 index 3b28e89..0000000 --- a/configd.tproj/config.defs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 diff --git a/configd.tproj/configd.8 b/configd.tproj/configd.8 new file mode 100644 index 0000000..744dfe7 --- /dev/null +++ b/configd.tproj/configd.8 @@ -0,0 +1,150 @@ +.\" +.\" @(#)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. diff --git a/configd.tproj/configd.m b/configd.tproj/configd.m index af823c4..cc05916 100644 --- a/configd.tproj/configd.m +++ b/configd.tproj/configd.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,6 +24,9 @@ /* * Modification History * + * October 30, 2003 Allan Nathanson + * - add plugin "stop()" function support + * * June 1, 2001 Allan Nathanson * - public API conversion * @@ -46,6 +49,7 @@ #include "configd_server.h" #include "plugin_support.h" +__private_extern__ Boolean _configd_verbose = FALSE; /* TRUE if verbose logging enabled */ __private_extern__ @@ -60,7 +64,7 @@ CFMutableSetRef _plugins_verbose = NULL; /* bundle identifiers to enable verbos 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' }, @@ -75,7 +79,7 @@ static struct option longopts[] = { 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")); @@ -93,7 +97,7 @@ catcher(int signum) { switch (signum) { case SIGTERM : - if (termRequested) { + if (termRequested != NULL) { mach_msg_empty_send_t msg; mach_msg_option_t options; kern_return_t status; @@ -115,6 +119,11 @@ catcher(int signum) 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; } @@ -126,7 +135,17 @@ catcher(int signum) 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; } @@ -250,12 +269,15 @@ main(int argc, char * const argv[]) { 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; @@ -375,40 +397,33 @@ main(int argc, char * const argv[]) 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); diff --git a/configd.tproj/configd_server.c b/configd.tproj/configd_server.c index a55f400..adfe9a5 100644 --- a/configd.tproj/configd_server.c +++ b/configd.tproj/configd_server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,6 +24,9 @@ /* * Modification History * + * March 9, 2004 Allan Nathanson + * - add DNS configuration server + * * June 1, 2001 Allan Nathanson * - public API conversion * @@ -31,19 +34,27 @@ * - initial revision */ -#include #include +#include +#include +#include #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; @@ -70,14 +81,11 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) (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; @@ -86,30 +94,42 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply) } /* - * (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; } @@ -123,18 +143,26 @@ configdCallback(CFMachPortRef port, void *msg, CFIndex size, void *info) 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); } @@ -206,7 +234,6 @@ __private_extern__ boolean_t server_active(mach_port_t *restart_service_port) { - mach_port_t bootstrap_port; char *service_name; kern_return_t status; @@ -215,14 +242,6 @@ server_active(mach_port_t *restart_service_port) 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) { @@ -253,24 +272,17 @@ __private_extern__ 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; @@ -294,7 +306,7 @@ server_init(mach_port_t restart_service_port, Boolean enableRestart) 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 { @@ -303,13 +315,13 @@ server_init(mach_port_t restart_service_port, Boolean enableRestart) 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; @@ -318,22 +330,22 @@ server_init(mach_port_t restart_service_port, Boolean enableRestart) 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); } @@ -361,7 +373,7 @@ server_init(mach_port_t restart_service_port, Boolean enableRestart) __private_extern__ -void +int server_shutdown() { char *service_name; @@ -373,7 +385,7 @@ server_shutdown() * logging thread lock is held. */ if ((priv_bootstrap_port == MACH_PORT_NULL) || (configd_port == NULL)) { - return; + return EX_OK; } service_name = getenv("SCD_SERVER"); @@ -401,10 +413,10 @@ server_shutdown() fprintf(stderr, "bootstrap_register() failed: status=%d\n", status); fflush (stderr); } - exit (EX_UNAVAILABLE); + return EX_UNAVAILABLE; } - exit(EX_OK); + return EX_OK; } diff --git a/configd.tproj/configd_server.h b/configd.tproj/configd_server.h index af388a1..4784de9 100644 --- a/configd.tproj/configd_server.h +++ b/configd.tproj/configd_server.h @@ -36,9 +36,7 @@ #include #include - -#include -#include +#include __BEGIN_DECLS @@ -52,7 +50,7 @@ boolean_t server_active (mach_port_t *service_port); void server_init (mach_port_t service_port, Boolean enableRestart); -void server_shutdown (); +int server_shutdown (); void server_loop (); @@ -62,6 +60,8 @@ kern_return_t _snapshot (mach_port_t server, 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); diff --git a/configd.tproj/h.template b/configd.tproj/h.template deleted file mode 100644 index f3c1b04..0000000 --- a/configd.tproj/h.template +++ /dev/null @@ -1,11 +0,0 @@ -$$ -/* $FILENAME$ created by $USERNAME$ on $DATE$ */ - -#import - -@interface $FILENAMESANSEXTENSION$ : NSObject -{ - -} - -@end diff --git a/configd.tproj/m.template b/configd.tproj/m.template deleted file mode 100644 index 1216fe5..0000000 --- a/configd.tproj/m.template +++ /dev/null @@ -1,18 +0,0 @@ -$$ 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 diff --git a/configd.tproj/notify.c b/configd.tproj/notify.c deleted file mode 100644 index 7ebc7ab..0000000 --- a/configd.tproj/notify.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 - * - public API conversion - * - * March 31, 2000 Allan Nathanson - * - initial revision - */ - - -#include - -#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; -} diff --git a/configd.tproj/notify.h b/configd.tproj/notify.h deleted file mode 100644 index 014da25..0000000 --- a/configd.tproj/notify.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - * - initial revision - */ - -#ifndef _S_NOTIFY_H -#define _S_NOTIFY_H - -#include - -__BEGIN_DECLS - -void pushNotifications (); - -__END_DECLS - -#endif /* !_S_NOTIFY_H */ diff --git a/configd.tproj/notify_server.c b/configd.tproj/notify_server.c index b914891..1d490d8 100644 --- a/configd.tproj/notify_server.c +++ b/configd.tproj/notify_server.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,7 +30,6 @@ #include "configd.h" #include "session.h" -#include "notify.h" __private_extern__ boolean_t @@ -71,8 +70,8 @@ notify_server(mach_msg_header_t *request, mach_msg_header_t *reply) } 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; diff --git a/configd.tproj/pattern.c b/configd.tproj/pattern.c index fa3bf86..7244627 100644 --- a/configd.tproj/pattern.c +++ b/configd.tproj/pattern.c @@ -90,7 +90,7 @@ identifyKeyForPattern(const void *key, void *val, void *context) 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; } @@ -108,7 +108,7 @@ identifyKeyForPattern(const void *key, void *val, void *context) 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; } } @@ -173,12 +173,16 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error) (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); @@ -349,7 +353,7 @@ addKeyForPattern(const void *key, void *val, void *context) 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; } @@ -389,7 +393,7 @@ addKeyForPattern(const void *key, void *val, void *context) 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; } } @@ -432,7 +436,7 @@ removeKeyFromPattern(const void *key, void *val, void *context) } i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey); - if (i == -1) { + if (i == kCFNotFound) { /* if this key wasn't matched by this pattern */ return; } diff --git a/configd.tproj/plugin_support.c b/configd.tproj/plugin_support.c index 80e5b85..266220f 100644 --- a/configd.tproj/plugin_support.c +++ b/configd.tproj/plugin_support.c @@ -24,6 +24,9 @@ /* * Modification History * + * October 30, 2003 Allan Nathanson + * - add plugin "stop()" function support + * * June 11, 2001 Allan Nathanson * - start using CFBundle code * @@ -39,10 +42,12 @@ #include #include #include +#include #include #include #include "configd.h" +#include "configd_server.h" #include void _SCDPluginExecInit(); @@ -54,128 +59,149 @@ 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, @@ -192,137 +218,154 @@ shortBundleIdentifier(CFStringRef 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; } @@ -359,30 +402,209 @@ startBundle(const void *value, void *context) { 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 @@ -400,30 +622,30 @@ timerCallback(CFRunLoopTimerRef timer, void *info) 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; @@ -436,8 +658,8 @@ sortBundles(CFMutableArrayRef orig) 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--; @@ -446,7 +668,7 @@ sortBundles(CFMutableArrayRef orig) } if (count == 0) { /* all dependencies are met, append */ - CFArrayAppendValue(new, bundle1); + CFArrayAppendValue(new, bundleInfo1); CFArrayRemoveValueAtIndex(orig, i); inserted = TRUE; break; @@ -477,10 +699,10 @@ __private_extern__ 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(); @@ -493,7 +715,7 @@ plugin_exec(void *arg) * identify and load all bundles */ state = NSStartSearchPathEnumeration(NSLibraryDirectory, - NSLocalDomainMask|NSSystemDomainMask); + NSSystemDomainMask); while ((state = NSGetNextSearchPathEnumeration(state, path))) { CFArrayRef bundles; CFURLRef url; @@ -508,10 +730,17 @@ plugin_exec(void *arg) 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); } } @@ -529,17 +758,26 @@ plugin_exec(void *arg) 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 @@ -550,8 +788,8 @@ plugin_exec(void *arg) 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 @@ -568,7 +806,7 @@ plugin_exec(void *arg) SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle start() functions")); CFArrayApplyFunction(allBundles, CFRangeMake(0, CFArrayGetCount(allBundles)), - startBundle, + callStartFunction, NULL); /* @@ -580,7 +818,7 @@ plugin_exec(void *arg) SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle prime() functions")); CFArrayApplyFunction(allBundles, CFRangeMake(0, CFArrayGetCount(allBundles)), - primeBundle, + callPrimeFunction, NULL); #ifdef DEBUG @@ -608,8 +846,11 @@ plugin_exec(void *arg) * 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; } diff --git a/configd.tproj/plugin_support.h b/configd.tproj/plugin_support.h index 0891ca6..63d515a 100644 --- a/configd.tproj/plugin_support.h +++ b/configd.tproj/plugin_support.h @@ -37,6 +37,7 @@ __BEGIN_DECLS void plugin_init (); void plugin_exec (void *arg); +Boolean plugin_term (int *status); __END_DECLS diff --git a/configd.tproj/session.c b/configd.tproj/session.c index 6c299bb..94e4213 100644 --- a/configd.tproj/session.c +++ b/configd.tproj/session.c @@ -47,7 +47,7 @@ getSession(mach_port_t server) 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; } @@ -93,11 +93,11 @@ addSession(CFMachPortRef server) 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; diff --git a/configd.xcode/project.pbxproj b/configd.xcode/project.pbxproj new file mode 100644 index 0000000..8ef21cc --- /dev/null +++ b/configd.xcode/project.pbxproj @@ -0,0 +1,5704 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 39; + objects = { + 150607BD075A00A200B147BA = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCSchemaDefinitions.c; + refType = 4; + sourceTree = ""; + }; + 150607DE075A00A300B147BA = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCSchemaDefinitions.h; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 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 = ""; + }; + 1532629006281C9D00B1C10C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = dnsinfo_create.h; + path = dnsinfo/dnsinfo_create.h; + refType = 4; + sourceTree = ""; + }; + 154361E00752C81800A8EC6C = { + fileRef = 159D53AB07528B36004F8947; + isa = PBXBuildFile; + settings = { + }; + }; + 1543636A0752D03C00A8EC6C = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + name = IOKit.framework; + path = /System/Library/Frameworks/IOKit.framework; + refType = 0; + sourceTree = ""; + }; + 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 = ""; + }; + 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 = ""; + }; + 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 = ""; + }; + 1577253606EFBF3100D7B52B = { + children = ( + 1577252F06EFB96700D7B52B, + ); + isa = PBXVariantGroup; + name = NetworkInterface.strings; + path = ""; + refType = 4; + sourceTree = ""; + }; + 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 = " + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + KernelEventMonitor.bundle + CFBundleIdentifier + com.yourcompany.KernelEventMonitor_bundle + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CSResourcesFileMapped + yes + + +"; + 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 = ""; + }; + 1582B37205FD1A5B009C2750 = { + children = ( + 15B73F0905FD1B670096477F, + 1532629006281C9D00B1C10C, + 15B73F0C05FD1B670096477F, + 15B73F0E05FD1B670096477F, + ); + isa = PBXGroup; + name = Headers; + refType = 4; + sourceTree = ""; + }; + 1582B37905FD1A66009C2750 = { + children = ( + 15B73F0B05FD1B670096477F, + 15B73F0805FD1B670096477F, + 1521FC5C060F296A003B28F5, + 15B73F0D05FD1B670096477F, + ); + isa = PBXGroup; + name = Sources; + refType = 4; + sourceTree = ""; + }; + 158AD85B0754E38F00124717 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Info.plist; + refType = 4; + sourceTree = ""; + }; + 158AD8700754E3D400124717 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Info.plist; + refType = 4; + sourceTree = ""; + }; + 158AD8C00754E3EF00124717 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Info.plist; + refType = 4; + sourceTree = ""; + }; + 158AD9100754E40E00124717 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Info.plist; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 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 = ""; + }; + 158ADBFD0754ECB100124717 = { + children = ( + 15FD73400754DBDA001CC321, + 15FD73220754DB9F001CC321, + 159D53EC07528C61004F8947, + 15FD72A50754DA4C001CC321, + 159D53E507528C4A004F8947, + 15FD72970754DA2B001CC321, + 159D53D407528BDA004F8947, + 15828AE70753B5F900AD4710, + 159D53DE07528C2E004F8947, + 15FD71090754D628001CC321, + 159D53F307528C79004F8947, + 15FD72B50754DA69001CC321, + 159D53FA07528C95004F8947, + 15FD72C90754DA7E001CC321, + ); + isa = PBXGroup; + name = Plugins; + refType = 4; + sourceTree = ""; + }; + 158ADCA60754ECC800124717 = { + children = ( + 159D54D907529FFF004F8947, + ); + isa = PBXGroup; + name = "configd, scutil, scselect"; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 159D53A607528B36004F8947 = { + children = ( + 159D53A707528B36004F8947, + 159D53AA07528B36004F8947, + 159D53AB07528B36004F8947, + 159D53A807528B36004F8947, + 15FD743E0754DE7A001CC321, + ); + isa = PBXGroup; + name = IPMonitor; + path = Plugins/IPMonitor; + refType = 4; + sourceTree = ""; + }; + 159D53A707528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = ip_plugin.c; + refType = 4; + sourceTree = ""; + }; + 159D53A807528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Resolvers.plist; + refType = 4; + sourceTree = ""; + }; + 159D53AA07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = "dns-configuration.c"; + refType = 4; + sourceTree = ""; + }; + 159D53AB07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = "set-hostname.c"; + refType = 4; + sourceTree = ""; + }; + 159D53AC07528B36004F8947 = { + children = ( + 159D53AE07528B36004F8947, + 15FD73EE0754DE62001CC321, + ); + isa = PBXGroup; + name = InterfaceNamer; + path = Plugins/InterfaceNamer; + refType = 4; + sourceTree = ""; + }; + 159D53AE07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = ifnamer.c; + refType = 4; + sourceTree = ""; + }; + 159D53AF07528B36004F8947 = { + children = ( + 159D53B707528B36004F8947, + 159D53B607528B36004F8947, + 159D53B207528B36004F8947, + 159D53B807528B36004F8947, + 159D53BA07528B36004F8947, + 159D53B007528B36004F8947, + 159D53B907528B36004F8947, + 159D53B107528B36004F8947, + 159D53B307528B36004F8947, + 159D53B407528B36004F8947, + 158AD8700754E3D400124717, + ); + isa = PBXGroup; + name = KernelEventMonitor; + path = Plugins/KernelEventMonitor; + refType = 4; + sourceTree = ""; + }; + 159D53B007528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = eventmon.c; + refType = 4; + sourceTree = ""; + }; + 159D53B107528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = ev_dlil.c; + refType = 4; + sourceTree = ""; + }; + 159D53B207528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = ev_dlil.h; + refType = 4; + sourceTree = ""; + }; + 159D53B307528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = ev_ipv4.c; + refType = 4; + sourceTree = ""; + }; + 159D53B407528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = ev_ipv6.c; + refType = 4; + sourceTree = ""; + }; + 159D53B607528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = ev_appletalk.h; + refType = 4; + sourceTree = ""; + }; + 159D53B707528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = eventmon.h; + refType = 4; + sourceTree = ""; + }; + 159D53B807528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = ev_ipv4.h; + refType = 4; + sourceTree = ""; + }; + 159D53B907528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = ev_appletalk.c; + refType = 4; + sourceTree = ""; + }; + 159D53BA07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = ev_ipv6.h; + refType = 4; + sourceTree = ""; + }; + 159D53BB07528B36004F8947 = { + children = ( + 159D53BE07528B36004F8947, + 158AD85B0754E38F00124717, + 159D53BC07528B36004F8947, + 159D53BD07528B36004F8947, + ); + isa = PBXGroup; + name = Kicker; + path = Plugins/Kicker; + refType = 4; + sourceTree = ""; + }; + 159D53BC07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Kicker.xml; + refType = 4; + sourceTree = ""; + }; + 159D53BD07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.script.sh; + path = "enable-network"; + refType = 4; + sourceTree = ""; + }; + 159D53BE07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = kicker.c; + refType = 4; + sourceTree = ""; + }; + 159D53C007528B36004F8947 = { + children = ( + 159D53C107528B36004F8947, + 158AD8C00754E3EF00124717, + ); + isa = PBXGroup; + name = LinkConfiguration; + path = Plugins/LinkConfiguration; + refType = 4; + sourceTree = ""; + }; + 159D53C107528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = linkconfig.c; + refType = 4; + sourceTree = ""; + }; + 159D53C207528B36004F8947 = { + children = ( + 159D53C307528B36004F8947, + 158AD9100754E40E00124717, + ); + isa = PBXGroup; + name = PreferencesMonitor; + path = Plugins/PreferencesMonitor; + refType = 4; + sourceTree = ""; + }; + 159D53C307528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = prefsmon.c; + refType = 4; + sourceTree = ""; + }; + 159D53C407528B36004F8947 = { + children = ( + 159D53C507528B36004F8947, + 159D53C607528B36004F8947, + 159D53C707528B36004F8947, + 15FD73970754DE49001CC321, + ); + isa = PBXGroup; + name = ATconfig; + path = Plugins/ATconfig; + refType = 4; + sourceTree = ""; + }; + 159D53C507528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = cfManager.c; + refType = 4; + sourceTree = ""; + }; + 159D53C607528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = cfManager.h; + refType = 4; + sourceTree = ""; + }; + 159D53C707528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = atconfig.c; + refType = 4; + sourceTree = ""; + }; + 159D53C907528B36004F8947 = { + children = ( + 159D53CA07528B36004F8947, + 159D53CB07528B36004F8947, + ); + isa = PBXGroup; + name = common; + path = Plugins/common; + refType = 4; + sourceTree = ""; + }; + 159D53CA07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = cache.c; + refType = 4; + sourceTree = ""; + }; + 159D53CB07528B36004F8947 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = cache.h; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 15A509A406C2518F001F0AB7 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = net.h; + refType = 4; + sourceTree = ""; + }; + 15AD7A380670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCNetworkConfiguration.h; + refType = 4; + sourceTree = ""; + }; + 15AD7A390670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkConfigurationInternal.c; + refType = 4; + sourceTree = ""; + }; + 15AD7A3A0670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCNetworkConfigurationInternal.h; + refType = 4; + sourceTree = ""; + }; + 15AD7A3B0670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkInterface.c; + refType = 4; + sourceTree = ""; + }; + 15AD7A3C0670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkProtocol.c; + refType = 4; + sourceTree = ""; + }; + 15AD7A3D0670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkService.c; + refType = 4; + sourceTree = ""; + }; + 15AD7A3E0670A85900BFE03C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkSet.c; + refType = 4; + sourceTree = ""; + }; + 15B6861D0678B61900FF4023 = { + children = ( + 15B686220678B65C00FF4023, + 1577253606EFBF3100D7B52B, + 15CFC229068B222F00123568, + ); + isa = PBXGroup; + name = "Supporting Files"; + refType = 4; + sourceTree = ""; + }; + 15B686220678B65C00FF4023 = { + explicitFileType = text.xml; + fileEncoding = 4; + isa = PBXFileReference; + path = NetworkConfiguration.plist; + refType = 4; + sourceTree = ""; + }; + 15B73F0805FD1B670096477F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = dnsinfo_copy.c; + path = dnsinfo/dnsinfo_copy.c; + refType = 4; + sourceTree = ""; + }; + 15B73F0905FD1B670096477F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = dnsinfo.h; + path = dnsinfo/dnsinfo.h; + refType = 4; + sourceTree = ""; + }; + 15B73F0B05FD1B670096477F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = dnsinfo_private.c; + path = dnsinfo/dnsinfo_private.c; + refType = 4; + sourceTree = ""; + }; + 15B73F0C05FD1B670096477F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = dnsinfo_private.h; + path = dnsinfo/dnsinfo_private.h; + refType = 4; + sourceTree = ""; + }; + 15B73F0D05FD1B670096477F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = dnsinfo_server.c; + path = dnsinfo/dnsinfo_server.c; + refType = 4; + sourceTree = ""; + }; + 15B73F0E05FD1B670096477F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + name = dnsinfo_server.h; + path = dnsinfo/dnsinfo_server.h; + refType = 4; + sourceTree = ""; + }; + 15CB68FC05C072220099E85F = { + children = ( + 15CB6A8605C072500099E85F, + 15CB6A8305C072410099E85F, + 1582B36B05FD1A4D009C2750, + 15CB690705C0722A0099E85F, + 15CB69C205C0722B0099E85F, + 15CB6A2205C0722B0099E85F, + 15CB6A3705C0722B0099E85F, + 159D53A207528B06004F8947, + 1514D77D05C08AB700757DC9, + 15CB6A6E05C0722B0099E85F, + 15CB690F05C0722B0099E85F, + ); + isa = PBXGroup; + name = configd; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 15CB690705C0722A0099E85F = { + children = ( + 15CB691205C0722B0099E85F, + 15CB694F05C0722B0099E85F, + 15B6861D0678B61900FF4023, + ); + isa = PBXGroup; + name = SystemConfiguration; + path = SystemConfiguration.fproj; + refType = 4; + sourceTree = ""; + }; + 15CB690F05C0722B0099E85F = { + children = ( + 158ADBFD0754ECB100124717, + 158ADCA60754ECC800124717, + 1558476A0754FDCD0046C2E9, + 1558481D07550EC10046C2E9, + 15DAD5EE075913CE0084A6ED, + 15DAD6C807591A1A0084A6ED, + 15481BF8075A2B3900B32F56, + ); + isa = PBXGroup; + name = Products; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 15CB691305C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SystemConfiguration.h; + refType = 4; + sourceTree = ""; + }; + 15CB691505C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCPrivate.h; + refType = 4; + sourceTree = ""; + }; + 15CB691705C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDPlugin.h; + refType = 4; + sourceTree = ""; + }; + 15CB691B05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStoreInternal.h; + refType = 4; + sourceTree = ""; + }; + 15CB691D05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStore.h; + refType = 4; + sourceTree = ""; + }; + 15CB691F05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStorePrivate.h; + refType = 4; + sourceTree = ""; + }; + 15CB692105C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStoreKey.h; + refType = 4; + sourceTree = ""; + }; + 15CB692305C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStoreCopySpecific.h; + refType = 4; + sourceTree = ""; + }; + 15CB692505C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStoreCopySpecificPrivate.h; + refType = 4; + sourceTree = ""; + }; + 15CB692705C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStoreSetSpecificPrivate.h; + refType = 4; + sourceTree = ""; + }; + 15CB692905C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCPreferencesInternal.h; + refType = 4; + sourceTree = ""; + }; + 15CB692B05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCPreferences.h; + refType = 4; + sourceTree = ""; + }; + 15CB692D05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCPreferencesPrivate.h; + refType = 4; + sourceTree = ""; + }; + 15CB692F05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCPreferencesPath.h; + refType = 4; + sourceTree = ""; + }; + 15CB693105C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCPreferencesSetSpecific.h; + refType = 4; + sourceTree = ""; + }; + 15CB693305C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCNetwork.h; + refType = 4; + sourceTree = ""; + }; + 15CB693505C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCNetworkConnection.h; + refType = 4; + sourceTree = ""; + }; + 15CB693705C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCNetworkReachability.h; + refType = 4; + sourceTree = ""; + }; + 15CB693905C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCValidation.h; + refType = 4; + sourceTree = ""; + }; + 15CB693D05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = DHCPClientPreferences.h; + refType = 4; + sourceTree = ""; + }; + 15CB693F05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = SCDynamicStoreCopyDHCPInfo.h; + refType = 4; + sourceTree = ""; + }; + 15CB694105C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = moh_msg.h; + refType = 4; + sourceTree = ""; + }; + 15CB694305C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = moh.h; + refType = 4; + sourceTree = ""; + }; + 15CB694505C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = DeviceOnHold.h; + refType = 4; + sourceTree = ""; + }; + 15CB694705C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = LinkConfiguration.h; + refType = 4; + sourceTree = ""; + }; + 15CB694905C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = dy_framework.h; + refType = 4; + sourceTree = ""; + }; + 15CB694B05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = VLANConfiguration.h; + refType = 4; + sourceTree = ""; + }; + 15CB694D05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = VLANConfigurationPrivate.h; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 15CB695005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCD.c; + refType = 4; + sourceTree = ""; + }; + 15CB695205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDKeys.c; + refType = 4; + sourceTree = ""; + }; + 15CB695405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDPrivate.c; + refType = 4; + sourceTree = ""; + }; + 15CB695605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDPlugin.c; + refType = 4; + sourceTree = ""; + }; + 15CB695805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDOpen.c; + refType = 4; + sourceTree = ""; + }; + 15CB695A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDLock.c; + refType = 4; + sourceTree = ""; + }; + 15CB695C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDUnlock.c; + refType = 4; + sourceTree = ""; + }; + 15CB695E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDList.c; + refType = 4; + sourceTree = ""; + }; + 15CB696005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDAdd.c; + refType = 4; + sourceTree = ""; + }; + 15CB696405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDGet.c; + refType = 4; + sourceTree = ""; + }; + 15CB696605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDSet.c; + refType = 4; + sourceTree = ""; + }; + 15CB696805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDRemove.c; + refType = 4; + sourceTree = ""; + }; + 15CB696A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDTouch.c; + refType = 4; + sourceTree = ""; + }; + 15CB696C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotify.c; + refType = 4; + sourceTree = ""; + }; + 15CB696E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierSetKeys.c; + refType = 4; + sourceTree = ""; + }; + 15CB697005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierAdd.c; + refType = 4; + sourceTree = ""; + }; + 15CB697205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierRemove.c; + refType = 4; + sourceTree = ""; + }; + 15CB697405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierGetChanges.c; + refType = 4; + sourceTree = ""; + }; + 15CB697605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierWait.c; + refType = 4; + sourceTree = ""; + }; + 15CB697805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierInformViaCallback.c; + refType = 4; + sourceTree = ""; + }; + 15CB697A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierInformViaMachPort.c; + refType = 4; + sourceTree = ""; + }; + 15CB697C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierInformViaFD.c; + refType = 4; + sourceTree = ""; + }; + 15CB697E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierInformViaSignal.c; + refType = 4; + sourceTree = ""; + }; + 15CB698005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDNotifierCancel.c; + refType = 4; + sourceTree = ""; + }; + 15CB698205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDSnapshot.c; + refType = 4; + sourceTree = ""; + }; + 15CB698405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCP.c; + refType = 4; + sourceTree = ""; + }; + 15CB698605C0722B0099E85F = { + indentWidth = 8; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPOpen.c; + refType = 4; + sourceTree = ""; + tabWidth = 8; + }; + 15CB698805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPLock.c; + refType = 4; + sourceTree = ""; + }; + 15CB698A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPUnlock.c; + refType = 4; + sourceTree = ""; + }; + 15CB698C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPList.c; + refType = 4; + sourceTree = ""; + }; + 15CB698E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPGet.c; + refType = 4; + sourceTree = ""; + }; + 15CB699005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPAdd.c; + refType = 4; + sourceTree = ""; + }; + 15CB699205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPSet.c; + refType = 4; + sourceTree = ""; + }; + 15CB699405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPRemove.c; + refType = 4; + sourceTree = ""; + }; + 15CB699605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPCommit.c; + refType = 4; + sourceTree = ""; + }; + 15CB699805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPApply.c; + refType = 4; + sourceTree = ""; + }; + 15CB699A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCPPath.c; + refType = 4; + sourceTree = ""; + }; + 15CB699C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDConsoleUser.c; + refType = 4; + sourceTree = ""; + }; + 15CB699E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCDHostName.c; + refType = 4; + sourceTree = ""; + }; + 15CB69A005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCLocation.c; + refType = 4; + sourceTree = ""; + }; + 15CB69A205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetwork.c; + refType = 4; + sourceTree = ""; + }; + 15CB69A405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkConnection.c; + refType = 4; + sourceTree = ""; + }; + 15CB69A605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCNetworkReachability.c; + refType = 4; + sourceTree = ""; + }; + 15CB69A805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = SCProxies.c; + refType = 4; + sourceTree = ""; + }; + 15CB69AC05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = DHCP.c; + refType = 4; + sourceTree = ""; + }; + 15CB69AE05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = moh.c; + refType = 4; + sourceTree = ""; + }; + 15CB69B005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = DeviceOnHold.c; + refType = 4; + sourceTree = ""; + }; + 15CB69B205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = LinkConfiguration.c; + refType = 4; + sourceTree = ""; + }; + 15CB69B405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = dy_framework.c; + refType = 4; + sourceTree = ""; + }; + 15CB69B605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = VLANConfiguration.c; + refType = 4; + sourceTree = ""; + }; + 15CB69BE05C0722B0099E85F = { + explicitFileType = sourcecode.mig; + isa = PBXFileReference; + name = config.defs; + path = SystemConfiguration.fproj/config.defs; + refType = 4; + sourceTree = ""; + }; + 15CB69BF05C0722B0099E85F = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = genSCPreferences.c; + path = SystemConfiguration.fproj/genSCPreferences.c; + refType = 4; + sourceTree = ""; + }; + 15CB69C205C0722B0099E85F = { + children = ( + 15CB69CE05C0722B0099E85F, + 15CB69DF05C0722B0099E85F, + 15CB6A1805C0722B0099E85F, + ); + isa = PBXGroup; + name = configd; + path = configd.tproj; + refType = 4; + sourceTree = ""; + }; + 15CB69CE05C0722B0099E85F = { + children = ( + 15CB69CF05C0722B0099E85F, + 15CB69D105C0722B0099E85F, + 15CB69D305C0722B0099E85F, + 15CB69D505C0722B0099E85F, + 15CB69D705C0722B0099E85F, + 15CB69D905C0722B0099E85F, + 15CB69DB05C0722B0099E85F, + ); + isa = PBXGroup; + name = Headers; + refType = 4; + sourceTree = ""; + }; + 15CB69CF05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = configd.h; + refType = 4; + sourceTree = ""; + }; + 15CB69D105C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = _SCD.h; + refType = 4; + sourceTree = ""; + }; + 15CB69D305C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = configd_server.h; + refType = 4; + sourceTree = ""; + }; + 15CB69D505C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = notify_server.h; + refType = 4; + sourceTree = ""; + }; + 15CB69D705C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = plugin_support.h; + refType = 4; + sourceTree = ""; + }; + 15CB69D905C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = session.h; + refType = 4; + sourceTree = ""; + }; + 15CB69DB05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = pattern.h; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 15CB69E005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.objc; + path = configd.m; + refType = 4; + sourceTree = ""; + }; + 15CB69E205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _SCD.c; + refType = 4; + sourceTree = ""; + }; + 15CB69E405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = configd_server.c; + refType = 4; + sourceTree = ""; + }; + 15CB69E605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = notify_server.c; + refType = 4; + sourceTree = ""; + }; + 15CB69E805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = plugin_support.c; + refType = 4; + sourceTree = ""; + }; + 15CB69EA05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = session.c; + refType = 4; + sourceTree = ""; + }; + 15CB69EC05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = pattern.c; + refType = 4; + sourceTree = ""; + }; + 15CB69F005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configopen.c; + refType = 4; + sourceTree = ""; + }; + 15CB69F205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configclose.c; + refType = 4; + sourceTree = ""; + }; + 15CB69F405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configlock.c; + refType = 4; + sourceTree = ""; + }; + 15CB69F605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configunlock.c; + refType = 4; + sourceTree = ""; + }; + 15CB69F805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configlist.c; + refType = 4; + sourceTree = ""; + }; + 15CB69FA05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configadd.c; + refType = 4; + sourceTree = ""; + }; + 15CB69FE05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configget.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configset.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configremove.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _configtouch.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _confignotify.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifyadd.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifyremove.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifychanges.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A0E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifyviaport.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A1005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifyviafd.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A1205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifyviasignal.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A1405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _notifycancel.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A1605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = _snapshot.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A1805C0722B0099E85F = { + children = ( + 15CB6A1F05C0722B0099E85F, + 15CB6A2005C0722B0099E85F, + ); + isa = PBXGroup; + name = "Supporting Files"; + refType = 4; + sourceTree = ""; + }; + 15CB6A1F05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = configd.plist; + refType = 4; + sourceTree = ""; + }; + 15CB6A2005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = text; + path = configd.8; + refType = 4; + sourceTree = ""; + }; + 15CB6A2205C0722B0099E85F = { + children = ( + 15CB6A2D05C0722B0099E85F, + 15CB6A3005C0722B0099E85F, + ); + isa = PBXGroup; + name = scselect; + path = scselect.tproj; + refType = 4; + sourceTree = ""; + }; + 15CB6A2D05C0722B0099E85F = { + children = ( + 15CB6A2E05C0722B0099E85F, + ); + isa = PBXGroup; + name = Sources; + refType = 4; + sourceTree = ""; + }; + 15CB6A2E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = scselect.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A3005C0722B0099E85F = { + children = ( + 15CB6A3605C0722B0099E85F, + ); + isa = PBXGroup; + name = "Supporting Files"; + refType = 4; + sourceTree = ""; + }; + 15CB6A3605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = text; + path = scselect.8; + refType = 4; + sourceTree = ""; + }; + 15CB6A3705C0722B0099E85F = { + children = ( + 15CB6A4205C0722B0099E85F, + 15CB6A5305C0722B0099E85F, + 15CB6A6405C0722B0099E85F, + ); + isa = PBXGroup; + name = scutil; + path = scutil.tproj; + refType = 4; + sourceTree = ""; + }; + 15CB6A4205C0722B0099E85F = { + children = ( + 15CB6A4305C0722B0099E85F, + 15CB6A4505C0722B0099E85F, + 15CB6A4705C0722B0099E85F, + 15CB6A4905C0722B0099E85F, + 15CB6A4B05C0722B0099E85F, + 15CB6A4D05C0722B0099E85F, + 15CB6A4F05C0722B0099E85F, + 15CB6A5105C0722B0099E85F, + 15A509A406C2518F001F0AB7, + 15DC34680711D49400A3311C, + 15DC346A0711D49400A3311C, + 15DC346C0711D49400A3311C, + 15DC346E0711D49400A3311C, + ); + isa = PBXGroup; + name = Headers; + refType = 4; + sourceTree = ""; + }; + 15CB6A4305C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = scutil.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A4505C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = commands.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A4705C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = dictionary.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A4905C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = session.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A4B05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = cache.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A4D05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = notifications.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A4F05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = tests.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A5105C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = prefs.h; + refType = 4; + sourceTree = ""; + }; + 15CB6A5305C0722B0099E85F = { + children = ( + 15CB6A5405C0722B0099E85F, + 15CB6A5605C0722B0099E85F, + 15CB6A5805C0722B0099E85F, + 15CB6A5A05C0722B0099E85F, + 15CB6A5C05C0722B0099E85F, + 15CB6A5E05C0722B0099E85F, + 15CB6A6005C0722B0099E85F, + 15CB6A6205C0722B0099E85F, + 15A509A306C2518F001F0AB7, + 15DC34670711D49400A3311C, + 15DC34690711D49400A3311C, + 15DC346B0711D49400A3311C, + 15DC346D0711D49400A3311C, + ); + isa = PBXGroup; + name = Sources; + refType = 4; + sourceTree = ""; + }; + 15CB6A5405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = scutil.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A5605C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = commands.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A5805C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = dictionary.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A5A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = session.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A5C05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = cache.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A5E05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = notifications.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A6005C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = tests.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A6205C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = prefs.c; + refType = 4; + sourceTree = ""; + }; + 15CB6A6405C0722B0099E85F = { + children = ( + 15CB6A6A05C0722B0099E85F, + ); + isa = PBXGroup; + name = "Supporting Files"; + refType = 4; + sourceTree = ""; + }; + 15CB6A6A05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = text; + path = scutil.8; + refType = 4; + sourceTree = ""; + }; + 15CB6A6E05C0722B0099E85F = { + children = ( + 158AD9F80754EA2F00124717, + 15CB6A6F05C0722B0099E85F, + 1543636A0752D03C00A8EC6C, + 158ADABB0754EAAE00124717, + 15CB6A7405C0722B0099E85F, + 152CEED0070CF6640050F23C, + ); + isa = PBXGroup; + name = "External Frameworks and Libraries"; + refType = 4; + sourceTree = ""; + }; + 15CB6A6F05C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = wrapper.framework; + name = CoreFoundation.framework; + path = /System/Library/Frameworks/CoreFoundation.framework; + refType = 0; + sourceTree = ""; + }; + 15CB6A7405C0722B0099E85F = { + isa = PBXFileReference; + lastKnownFileType = "compiled.mach-o.dylib"; + name = libobjc.dylib; + path = /usr/lib/libobjc.A.dylib; + refType = 0; + sourceTree = ""; + }; + 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 = ""; + }; + 15CB6A8605C072500099E85F = { + children = ( + 15CB69BE05C0722B0099E85F, + 1514D76D05C08A5F00757DC9, + 15FCAAD005FD0EBF00CB79E6, + 15FCAACF05FD0EBF00CB79E6, + 23C1E2B8062DD45900835B54, + 23C1E2B4062DD2C700835B54, + ); + isa = PBXGroup; + name = MiG; + path = ""; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 15DC34680711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = net_interface.h; + refType = 4; + sourceTree = ""; + }; + 15DC34690711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = net_protocol.c; + refType = 4; + sourceTree = ""; + }; + 15DC346A0711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = net_protocol.h; + refType = 4; + sourceTree = ""; + }; + 15DC346B0711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = net_service.c; + refType = 4; + sourceTree = ""; + }; + 15DC346C0711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = net_service.h; + refType = 4; + sourceTree = ""; + }; + 15DC346D0711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + path = net_set.c; + refType = 4; + sourceTree = ""; + }; + 15DC346E0711D49400A3311C = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = net_set.h; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 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 = ""; + }; + 15FD73EE0754DE62001CC321 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Info.plist; + refType = 4; + sourceTree = ""; + }; + 15FD743E0754DE7A001CC321 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = text.xml; + path = Info.plist; + refType = 4; + sourceTree = ""; + }; +//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 = ""; + }; + 23C1E2B8062DD45900835B54 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.mig; + name = pppcontroller.defs; + path = SystemConfiguration.fproj/pppcontroller.defs; + refType = 4; + sourceTree = ""; + }; + 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 = ""; + }; + 9EE943F406AF409B00772EB5 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = BondConfiguration.h; + refType = 4; + sourceTree = ""; + }; + 9EE943F506AF409B00772EB5 = { + fileEncoding = 30; + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.h; + path = BondConfigurationPrivate.h; + refType = 4; + sourceTree = ""; + }; + }; + rootObject = 15CB6A7705C0722B0099E85F; +} diff --git a/dnsinfo/dnsinfo.h b/dnsinfo/dnsinfo.h new file mode 100644 index 0000000..e26da0e --- /dev/null +++ b/dnsinfo/dnsinfo.h @@ -0,0 +1,84 @@ +/* + * 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 +#include +#include +#include + +#include + + +#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__ diff --git a/dnsinfo/dnsinfo_copy.c b/dnsinfo/dnsinfo_copy.c new file mode 100644 index 0000000..882b697 --- /dev/null +++ b/dnsinfo/dnsinfo_copy.c @@ -0,0 +1,338 @@ +/* + * 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 + * - initial revision + */ + +#include +#include +#include + +#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; +} diff --git a/dnsinfo/dnsinfo_create.c b/dnsinfo/dnsinfo_create.c new file mode 100644 index 0000000..6ff9bb3 --- /dev/null +++ b/dnsinfo/dnsinfo_create.c @@ -0,0 +1,350 @@ +/* + * 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 +#include +#include +#include + +#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; +} diff --git a/dnsinfo/dnsinfo_create.h b/dnsinfo/dnsinfo_create.h new file mode 100644 index 0000000..fd2d6fb --- /dev/null +++ b/dnsinfo/dnsinfo_create.h @@ -0,0 +1,74 @@ +/* + * 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 +#include +#include +#include + +#include + + +#include + + +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__ diff --git a/dnsinfo/dnsinfo_private.c b/dnsinfo/dnsinfo_private.c new file mode 100644 index 0000000..6ada24f --- /dev/null +++ b/dnsinfo/dnsinfo_private.c @@ -0,0 +1,76 @@ +/* + * 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 + * - initial revision + */ + +#include +#include +#include +#include + +#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; +} + diff --git a/dnsinfo/dnsinfo_private.h b/dnsinfo/dnsinfo_private.h new file mode 100644 index 0000000..378787c --- /dev/null +++ b/dnsinfo/dnsinfo_private.h @@ -0,0 +1,184 @@ +/* + * 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 +#include +#include +#include +#include + +#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__ diff --git a/dnsinfo/dnsinfo_server.c b/dnsinfo/dnsinfo_server.c new file mode 100644 index 0000000..a87dd58 --- /dev/null +++ b/dnsinfo/dnsinfo_server.c @@ -0,0 +1,104 @@ +/* + * 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 + * - initial revision + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/dnsinfo/dnsinfo_server.h b/dnsinfo/dnsinfo_server.h new file mode 100644 index 0000000..9bddeb0 --- /dev/null +++ b/dnsinfo/dnsinfo_server.h @@ -0,0 +1,45 @@ +/* + * 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 +#include +#include + +#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 */ diff --git a/dnsinfo/shared_dns_info.defs b/dnsinfo/shared_dns_info.defs new file mode 100644 index 0000000..9f12a18 --- /dev/null +++ b/dnsinfo/shared_dns_info.defs @@ -0,0 +1,59 @@ +/* + * 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 + * - initial revision + */ + +#include +#include + +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); diff --git a/dnsinfo/shared_dns_info_types.h b/dnsinfo/shared_dns_info_types.h new file mode 100644 index 0000000..e4fe4b6 --- /dev/null +++ b/dnsinfo/shared_dns_info_types.h @@ -0,0 +1,51 @@ +/* + * 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 */ diff --git a/get-mobility-info b/get-mobility-info new file mode 100755 index 0000000..403b317 --- /dev/null +++ b/get-mobility-info @@ -0,0 +1,236 @@ +#!/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" diff --git a/preferences.xml b/preferences.xml index c4222c8..d25e57a 100644 --- a/preferences.xml +++ b/preferences.xml @@ -71,7 +71,7 @@ LCPEchoInterval 10 Logfile - /tmp/ppp.log + /var/log/ppp.log VerboseLogging 0 __INACTIVE__ diff --git a/scselect.tproj/Makefile b/scselect.tproj/Makefile deleted file mode 100644 index 9bf1aa4..0000000 --- a/scselect.tproj/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# -# 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 diff --git a/scselect.tproj/Makefile.postamble b/scselect.tproj/Makefile.postamble deleted file mode 100644 index 46b1c86..0000000 --- a/scselect.tproj/Makefile.postamble +++ /dev/null @@ -1,101 +0,0 @@ -############################################################################### -# 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. -# diff --git a/scselect.tproj/Makefile.preamble b/scselect.tproj/Makefile.preamble deleted file mode 100644 index 13efa5f..0000000 --- a/scselect.tproj/Makefile.preamble +++ /dev/null @@ -1,137 +0,0 @@ -############################################################################### -# 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: <> -# 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) diff --git a/scselect.tproj/PB.project b/scselect.tproj/PB.project deleted file mode 100644 index f5d4f31..0000000 --- a/scselect.tproj/PB.project +++ /dev/null @@ -1,36 +0,0 @@ -{ - 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"; -} diff --git a/scselect.tproj/h.template b/scselect.tproj/h.template deleted file mode 100644 index f3c1b04..0000000 --- a/scselect.tproj/h.template +++ /dev/null @@ -1,11 +0,0 @@ -$$ -/* $FILENAME$ created by $USERNAME$ on $DATE$ */ - -#import - -@interface $FILENAMESANSEXTENSION$ : NSObject -{ - -} - -@end diff --git a/scselect.tproj/m.template b/scselect.tproj/m.template deleted file mode 100644 index 1216fe5..0000000 --- a/scselect.tproj/m.template +++ /dev/null @@ -1,18 +0,0 @@ -$$ 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 diff --git a/scselect.tproj/scselect.8 b/scselect.tproj/scselect.8 new file mode 100644 index 0000000..c4c5645 --- /dev/null +++ b/scselect.tproj/scselect.8 @@ -0,0 +1,58 @@ +.\" +.\" @(#)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. diff --git a/scselect.tproj/scselect.c b/scselect.tproj/scselect.c index 04a241e..9dac36a 100644 --- a/scselect.tproj/scselect.c +++ b/scselect.tproj/scselect.c @@ -53,10 +53,10 @@ #include -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' }, @@ -76,31 +76,31 @@ usage(const char *command) 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; } @@ -141,17 +141,17 @@ _SessionGetInfo(SecuritySessionId session, SecuritySessionId *sessionId, Session 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; } @@ -166,7 +166,7 @@ main(int argc, char **argv) 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; @@ -200,8 +200,8 @@ main(int argc, char **argv) ? 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); } @@ -224,14 +224,14 @@ main(int argc, char **argv) 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; @@ -264,7 +264,7 @@ main(int argc, char **argv) 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; } @@ -324,12 +324,12 @@ main(int argc, char **argv) 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, @@ -337,19 +337,19 @@ main(int argc, char **argv) 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"), diff --git a/scutil.tproj/Makefile b/scutil.tproj/Makefile deleted file mode 100644 index bfd12a8..0000000 --- a/scutil.tproj/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# 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 diff --git a/scutil.tproj/Makefile.postamble b/scutil.tproj/Makefile.postamble deleted file mode 100644 index da52544..0000000 --- a/scutil.tproj/Makefile.postamble +++ /dev/null @@ -1,101 +0,0 @@ -############################################################################### -# 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. -# diff --git a/scutil.tproj/Makefile.preamble b/scutil.tproj/Makefile.preamble deleted file mode 100644 index b9f5238..0000000 --- a/scutil.tproj/Makefile.preamble +++ /dev/null @@ -1,137 +0,0 @@ -############################################################################### -# 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: <> -# 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) diff --git a/scutil.tproj/PB.project b/scutil.tproj/PB.project deleted file mode 100644 index 6c31b0e..0000000 --- a/scutil.tproj/PB.project +++ /dev/null @@ -1,56 +0,0 @@ -{ - "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"; -} diff --git a/scutil.tproj/cache.c b/scutil.tproj/cache.c index 8407454..74a7127 100644 --- a/scutil.tproj/cache.c +++ b/scutil.tproj/cache.c @@ -45,6 +45,7 @@ sort_keys(const void *p1, const void *p2, void *context) { } +__private_extern__ void do_list(int argc, char **argv) { @@ -56,7 +57,7 @@ do_list(int argc, char **argv) pattern = CFStringCreateWithCString(NULL, (argc >= 1) ? argv[0] : ".*", - kCFStringEncodingMacRoman); + kCFStringEncodingUTF8); list = SCDynamicStoreCopyKeyList(store, pattern); CFRelease(pattern); @@ -94,12 +95,13 @@ do_list(int argc, char **argv) } +__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)) { @@ -116,13 +118,14 @@ do_add(int argc, char **argv) } +__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) { @@ -139,12 +142,13 @@ do_get(int argc, char **argv) } +__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())); } @@ -153,13 +157,14 @@ do_set(int argc, char **argv) } +__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); @@ -183,12 +188,13 @@ do_show(int argc, char **argv) } +__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())); } @@ -197,12 +203,13 @@ do_remove(int argc, char **argv) } +__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())); } @@ -211,12 +218,13 @@ do_notify(int argc, char **argv) } +__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())); } diff --git a/scutil.tproj/commands.c b/scutil.tproj/commands.c index 561f15c..5a90465 100644 --- a/scutil.tproj/commands.c +++ b/scutil.tproj/commands.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -40,13 +40,15 @@ #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 */ @@ -56,6 +58,15 @@ const cmdInfo commands[] = { { "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, @@ -66,17 +77,17 @@ const cmdInfo commands[] = { { "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, @@ -89,13 +100,13 @@ const cmdInfo commands[] = { " 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" }, @@ -113,7 +124,7 @@ const cmdInfo commands[] = { " 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" }, @@ -139,15 +150,103 @@ const cmdInfo commands[] = { { "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 [ | ]\n" + " create protocol \n" + " create service [ | [ ]]\n" + " create set [setName]" }, + { "disable", 1, 2, do_net_disable, 5, 0, + " disable protocol [ ]\n" + " disable service [ | ]" }, + { "enable", 1, 2, do_net_enable, 4, 0, + " enable protocol [ ]\n" + " enable service [ | ]" }, + + { "remove", 1, 2, do_net_remove, 6, 0, + " remove protocol [ ]\n" + " remove service [ | ]\n" + " remove set [ | ]" }, + + { "select", 2, 2, do_net_select, 7, 0, + " select interface | | $child | $service\n" + " select protocol \n" + " select service | \n" + " select 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 ] [ order new-order ]\n" + " set set [ name setName ]" }, + + { "show", 1, 2, do_net_show, 9, 0, + " show interfaces\n" + " show interface [ | ]\n" + " show protocols\n" + " show protocol [ ]\n" + " show services [ all ]\n" + " show service [ | ]\n" + " show sets\n\n" + " show 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) { @@ -169,7 +268,7 @@ 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; } } @@ -179,6 +278,7 @@ do_command(int argc, char **argv) } +__private_extern__ void do_help(int argc, char **argv) { @@ -187,6 +287,10 @@ 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 */ } @@ -206,6 +310,7 @@ do_help(int argc, char **argv) } +__private_extern__ void do_readFile(int argc, char **argv) { @@ -236,3 +341,12 @@ do_readFile(int argc, char **argv) return; } + + +__private_extern__ +void +do_quit(int argc, char **argv) +{ + termRequested = TRUE; + return; +} diff --git a/scutil.tproj/commands.h b/scutil.tproj/commands.h index a0a0821..f1fd332 100644 --- a/scutil.tproj/commands.h +++ b/scutil.tproj/commands.h @@ -42,18 +42,26 @@ typedef struct { 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 diff --git a/scutil.tproj/dictionary.c b/scutil.tproj/dictionary.c index 8507dda..234c4e2 100644 --- a/scutil.tproj/dictionary.c +++ b/scutil.tproj/dictionary.c @@ -39,6 +39,7 @@ //#include +__private_extern__ void do_dictInit(int argc, char **argv) { @@ -56,6 +57,7 @@ do_dictInit(int argc, char **argv) } +__private_extern__ void do_dictShow(int argc, char **argv) { @@ -70,6 +72,7 @@ do_dictShow(int argc, char **argv) } +__private_extern__ void do_dictSetKey(int argc, char **argv) { @@ -94,7 +97,7 @@ 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) { @@ -161,7 +164,7 @@ do_dictSetKey(int argc, char **argv) return; } } else { - val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman); + val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8); } if (doArray) { @@ -183,6 +186,7 @@ do_dictSetKey(int argc, char **argv) } +__private_extern__ void do_dictRemoveKey(int argc, char **argv) { @@ -203,7 +207,7 @@ 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); diff --git a/scutil.tproj/h.template b/scutil.tproj/h.template deleted file mode 100644 index f3c1b04..0000000 --- a/scutil.tproj/h.template +++ /dev/null @@ -1,11 +0,0 @@ -$$ -/* $FILENAME$ created by $USERNAME$ on $DATE$ */ - -#import - -@interface $FILENAMESANSEXTENSION$ : NSObject -{ - -} - -@end diff --git a/scutil.tproj/m.template b/scutil.tproj/m.template deleted file mode 100644 index 1216fe5..0000000 --- a/scutil.tproj/m.template +++ /dev/null @@ -1,18 +0,0 @@ -$$ 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 diff --git a/scutil.tproj/net.c b/scutil.tproj/net.c new file mode 100644 index 0000000..c28dd55 --- /dev/null +++ b/scutil.tproj/net.c @@ -0,0 +1,899 @@ +/* + * 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 + * - 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 + + +__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 +#include +__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; +} diff --git a/scutil.tproj/net.h b/scutil.tproj/net.h new file mode 100644 index 0000000..ad4a56a --- /dev/null +++ b/scutil.tproj/net.h @@ -0,0 +1,133 @@ +/* + * 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 + * - initial revision + */ + +#ifndef _NET_H +#define _NET_H + +#include + +#include +#include + + +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 */ diff --git a/scutil.tproj/net_interface.c b/scutil.tproj/net_interface.c new file mode 100644 index 0000000..a7bb46c --- /dev/null +++ b/scutil.tproj/net_interface.c @@ -0,0 +1,1186 @@ +/* + * 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 + * - initial revision + */ + + +#include "scutil.h" +#include "net.h" + +#include + + +/* -------------------- */ + + +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; +} diff --git a/scutil.tproj/net_interface.h b/scutil.tproj/net_interface.h new file mode 100644 index 0000000..780a84c --- /dev/null +++ b/scutil.tproj/net_interface.h @@ -0,0 +1,49 @@ +/* + * 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 + * - initial revision + */ + +#ifndef _NET_INTERFACE_H +#define _NET_INTERFACE_H + +#include + +__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 */ diff --git a/scutil.tproj/net_protocol.c b/scutil.tproj/net_protocol.c new file mode 100644 index 0000000..49a3329 --- /dev/null +++ b/scutil.tproj/net_protocol.c @@ -0,0 +1,1700 @@ +/* + * 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 + * - initial revision + */ + + +#include "scutil.h" +#include "net.h" +#include "net_protocol.h" + + +#include +#include +#include +#include +#include + + +/* -------------------- */ + + +__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; +} diff --git a/scutil.tproj/net_protocol.h b/scutil.tproj/net_protocol.h new file mode 100644 index 0000000..30b650e --- /dev/null +++ b/scutil.tproj/net_protocol.h @@ -0,0 +1,52 @@ +/* + * 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 + * - initial revision + */ + +#ifndef _NET_PROTOCOL_H +#define _NET_PROTOCOL_H + +#include + +__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 */ diff --git a/scutil.tproj/net_service.c b/scutil.tproj/net_service.c new file mode 100644 index 0000000..30c00b3 --- /dev/null +++ b/scutil.tproj/net_service.c @@ -0,0 +1,972 @@ +/* + * 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 + * - 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; +} diff --git a/scutil.tproj/net_service.h b/scutil.tproj/net_service.h new file mode 100644 index 0000000..d346ada --- /dev/null +++ b/scutil.tproj/net_service.h @@ -0,0 +1,51 @@ +/* + * 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 + * - initial revision + */ + +#ifndef _NET_SERVICE_H +#define _NET_SERVICE_H + +#include + +__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 */ diff --git a/scutil.tproj/net_set.c b/scutil.tproj/net_set.c new file mode 100644 index 0000000..0e0082e --- /dev/null +++ b/scutil.tproj/net_set.c @@ -0,0 +1,642 @@ +/* + * 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 + * - 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; +} diff --git a/scutil.tproj/net_set.h b/scutil.tproj/net_set.h new file mode 100644 index 0000000..d8f7215 --- /dev/null +++ b/scutil.tproj/net_set.h @@ -0,0 +1,47 @@ +/* + * 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 + * - initial revision + */ + +#ifndef _NET_SET_H +#define _NET_SET_H + +#include + +__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 */ diff --git a/scutil.tproj/notifications.c b/scutil.tproj/notifications.c new file mode 100644 index 0000000..aa3715d --- /dev/null +++ b/scutil.tproj/notifications.c @@ -0,0 +1,504 @@ +/* + * 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 + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + +#include +#include +#include +#include +#include + +#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; +} diff --git a/scutil.tproj/notifications.h b/scutil.tproj/notifications.h new file mode 100644 index 0000000..a0f4735 --- /dev/null +++ b/scutil.tproj/notifications.h @@ -0,0 +1,58 @@ +/* + * 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 + * - public API conversion + * + * November 9, 2000 Allan Nathanson + * - initial revision + */ + +#ifndef _NOTIFICATIONS_H +#define _NOTIFICATIONS_H + +#include + +__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 */ diff --git a/scutil.tproj/notify.c b/scutil.tproj/notify.c deleted file mode 100644 index 9b0d9cc..0000000 --- a/scutil.tproj/notify.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * 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 - * - public API conversion - * - * November 9, 2000 Allan Nathanson - * - initial revision - */ - -#include -#include -#include -#include -#include - -#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; -} diff --git a/scutil.tproj/notify.h b/scutil.tproj/notify.h deleted file mode 100644 index 72bf1f2..0000000 --- a/scutil.tproj/notify.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 - * - public API conversion - * - * November 9, 2000 Allan Nathanson - * - initial revision - */ - -#ifndef _NOTIFY_H -#define _NOTIFY_H - -#include - -__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 */ diff --git a/scutil.tproj/prefs.c b/scutil.tproj/prefs.c index f522a42..633556b 100644 --- a/scutil.tproj/prefs.c +++ b/scutil.tproj/prefs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -37,10 +37,8 @@ static SCPreferencesRef _open() { - SCPreferencesRef prefs; - prefs = SCPreferencesCreate(NULL, CFSTR("scutil"), NULL); - if (!prefs) { + if (prefs == NULL) { SCPrint(TRUE, stdout, CFSTR("SCPreferencesCreate() failed: %s\n"), @@ -150,7 +148,6 @@ set_ComputerName(int argc, char **argv) { CFStringEncoding encoding; CFStringRef hostname; - SCPreferencesRef prefs; if (argc == 0) { hostname = _copyStringFromSTDIN(); @@ -175,6 +172,67 @@ set_ComputerName(int argc, char **argv) } +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) { @@ -210,7 +268,6 @@ static void set_LocalHostName(int argc, char **argv) { CFStringRef hostname = NULL; - SCPreferencesRef prefs; if (argc == 0) { hostname = _copyStringFromSTDIN(); @@ -235,24 +292,26 @@ set_LocalHostName(int argc, char **argv) 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; } } @@ -261,6 +320,7 @@ findPref(char *pref) } +__private_extern__ void do_getPref(char *pref, int argc, char **argv) { @@ -268,12 +328,13 @@ 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) { @@ -281,7 +342,7 @@ 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; } diff --git a/scutil.tproj/scutil.8 b/scutil.tproj/scutil.8 new file mode 100644 index 0000000..215ec8f --- /dev/null +++ b/scutil.tproj/scutil.8 @@ -0,0 +1,153 @@ +.\" +.\" @(#)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. diff --git a/scutil.tproj/scutil.c b/scutil.tproj/scutil.c index b538711..09b6f0a 100644 --- a/scutil.tproj/scutil.c +++ b/scutil.tproj/scutil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,6 +24,9 @@ /* * Modification History * + * August 4, 2004 Allan Nathanson + * - added network configuration (prefs) support + * * September 25, 2002 Allan Nathanson * - added command line history & editing * @@ -56,8 +59,10 @@ #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" @@ -65,25 +70,30 @@ #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 } }; @@ -127,7 +137,7 @@ getLine(char *buf, int len, InputRef src) } -char * +static char * getString(char **line) { char *s, *e, c, *string; @@ -178,13 +188,18 @@ getString(char **line) } +__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; @@ -192,39 +207,37 @@ process_line(InputRef src) 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); @@ -246,6 +259,19 @@ usage(const char *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); } @@ -260,11 +286,14 @@ prompt(EditLine *el) 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; @@ -299,9 +328,18 @@ main(int argc, char * const argv[]) 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++; @@ -334,6 +372,12 @@ main(int argc, char * const argv[]) /* 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) { @@ -343,6 +387,12 @@ main(int argc, char * const argv[]) /* 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) { @@ -352,8 +402,25 @@ main(int argc, char * const argv[]) /* 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); diff --git a/scutil.tproj/scutil.h b/scutil.tproj/scutil.h index 794530b..cf01256 100644 --- a/scutil.tproj/scutil.h +++ b/scutil.tproj/scutil.h @@ -49,9 +49,11 @@ typedef struct { } 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; diff --git a/scutil.tproj/session.c b/scutil.tproj/session.c index 9c5d2cb..0cba63e 100644 --- a/scutil.tproj/session.c +++ b/scutil.tproj/session.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -33,8 +33,9 @@ #include "scutil.h" #include "session.h" -#include "notify.h" +#include "notifications.h" +__private_extern__ void do_open(int argc, char **argv) { @@ -44,8 +45,24 @@ 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; } @@ -57,11 +74,12 @@ do_open(int argc, char **argv) } +__private_extern__ void do_close(int argc, char **argv) { if (notifyRls) { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode); + CFRunLoopSourceInvalidate(notifyRls); CFRelease(notifyRls); notifyRls = NULL; } @@ -83,6 +101,7 @@ do_close(int argc, char **argv) } +__private_extern__ void do_lock(int argc, char **argv) { @@ -93,6 +112,7 @@ do_lock(int argc, char **argv) } +__private_extern__ void do_unlock(int argc, char **argv) { diff --git a/scutil.tproj/tests.c b/scutil.tproj/tests.c index 74a4049..51c9a8b 100644 --- a/scutil.tproj/tests.c +++ b/scutil.tproj/tests.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -44,7 +44,9 @@ #include #include +#include +__private_extern__ void do_checkReachability(int argc, char **argv) { @@ -161,6 +163,90 @@ 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) { @@ -185,6 +271,7 @@ waitTimeout(int sigraised) } +__private_extern__ void do_wait(char *waitKey, int timeout) { @@ -193,14 +280,14 @@ 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)) { @@ -225,7 +312,7 @@ do_wait(char *waitKey, int timeout) } CFRelease(key); - if (waitTimeout > 0) { + if (timeout > 0) { signal(SIGALRM, waitTimeout); bzero(&itv, sizeof(itv)); itv.it_value.tv_sec = timeout; diff --git a/scutil.tproj/tests.h b/scutil.tproj/tests.h index c13c99f..236e90f 100644 --- a/scutil.tproj/tests.h +++ b/scutil.tproj/tests.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -40,9 +40,11 @@ __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