]> git.saurik.com Git - apple/configd.git/commitdiff
configd-130.tar.gz mac-os-x-104 mac-os-x-1041 mac-os-x-1042 v130
authorApple <opensource@apple.com>
Mon, 11 Apr 2005 05:37:04 +0000 (05:37 +0000)
committerApple <opensource@apple.com>
Mon, 11 Apr 2005 05:37:04 +0000 (05:37 +0000)
234 files changed:
APPLE_LICENSE [new file with mode: 0644]
Makefile [deleted file]
Makefile.postamble [deleted file]
Makefile.preamble [deleted file]
PB.project [deleted file]
Plugins/ATconfig/Info.plist [new file with mode: 0644]
Plugins/ATconfig/atconfig.c [new file with mode: 0644]
Plugins/ATconfig/cfManager.c [new file with mode: 0644]
Plugins/ATconfig/cfManager.h [new file with mode: 0644]
Plugins/IPMonitor/Info.plist [new file with mode: 0644]
Plugins/IPMonitor/Resolvers.plist [new file with mode: 0644]
Plugins/IPMonitor/dns-configuration.c [new file with mode: 0644]
Plugins/IPMonitor/ip_plugin.c [new file with mode: 0644]
Plugins/IPMonitor/set-hostname.c [new file with mode: 0644]
Plugins/InterfaceNamer/Info.plist [new file with mode: 0644]
Plugins/InterfaceNamer/ifnamer.c [new file with mode: 0644]
Plugins/KernelEventMonitor/Info.plist [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_appletalk.c [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_appletalk.h [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_dlil.c [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_dlil.h [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_ipv4.c [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_ipv4.h [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_ipv6.c [new file with mode: 0644]
Plugins/KernelEventMonitor/ev_ipv6.h [new file with mode: 0644]
Plugins/KernelEventMonitor/eventmon.c [new file with mode: 0644]
Plugins/KernelEventMonitor/eventmon.h [new file with mode: 0644]
Plugins/Kicker/Info.plist [new file with mode: 0644]
Plugins/Kicker/Kicker.xml [new file with mode: 0644]
Plugins/Kicker/enable-network [new file with mode: 0755]
Plugins/Kicker/kicker.c [new file with mode: 0644]
Plugins/LinkConfiguration/Info.plist [new file with mode: 0644]
Plugins/LinkConfiguration/linkconfig.c [new file with mode: 0644]
Plugins/PreferencesMonitor/Info.plist [new file with mode: 0644]
Plugins/PreferencesMonitor/prefsmon.c [new file with mode: 0644]
Plugins/common/cache.c [new file with mode: 0644]
Plugins/common/cache.h [new file with mode: 0644]
SystemConfiguration.fproj/BondConfiguration.c [new file with mode: 0644]
SystemConfiguration.fproj/BondConfiguration.h [new file with mode: 0644]
SystemConfiguration.fproj/BondConfigurationPrivate.h [new file with mode: 0644]
SystemConfiguration.fproj/CustomInfo.plist [deleted file]
SystemConfiguration.fproj/DHCP.c
SystemConfiguration.fproj/DHCPClientPreferences.h
SystemConfiguration.fproj/DeviceOnHold.c
SystemConfiguration.fproj/DeviceOnHold.h
SystemConfiguration.fproj/English.lproj/NetworkInterface.strings [new file with mode: 0644]
SystemConfiguration.fproj/Info.plist [new file with mode: 0644]
SystemConfiguration.fproj/LinkConfiguration.c
SystemConfiguration.fproj/LinkConfiguration.h
SystemConfiguration.fproj/Makefile
SystemConfiguration.fproj/Makefile.postamble [deleted file]
SystemConfiguration.fproj/Makefile.preamble [deleted file]
SystemConfiguration.fproj/NetworkConfiguration.plist [new file with mode: 0644]
SystemConfiguration.fproj/PB.project [deleted file]
SystemConfiguration.fproj/SCD.c
SystemConfiguration.fproj/SCDAdd.c
SystemConfiguration.fproj/SCDAddSession.c [deleted file]
SystemConfiguration.fproj/SCDConsoleUser.c
SystemConfiguration.fproj/SCDGet.c
SystemConfiguration.fproj/SCDHostName.c
SystemConfiguration.fproj/SCDList.c
SystemConfiguration.fproj/SCDLock.c
SystemConfiguration.fproj/SCDNotifierAdd.c
SystemConfiguration.fproj/SCDNotifierCancel.c
SystemConfiguration.fproj/SCDNotifierGetChanges.c
SystemConfiguration.fproj/SCDNotifierInformViaCallback.c
SystemConfiguration.fproj/SCDNotifierInformViaFD.c
SystemConfiguration.fproj/SCDNotifierInformViaMachPort.c
SystemConfiguration.fproj/SCDNotifierInformViaSignal.c
SystemConfiguration.fproj/SCDNotifierRemove.c
SystemConfiguration.fproj/SCDNotifierSetKeys.c
SystemConfiguration.fproj/SCDNotifierWait.c
SystemConfiguration.fproj/SCDNotify.c
SystemConfiguration.fproj/SCDOpen.c
SystemConfiguration.fproj/SCDPlugin.c
SystemConfiguration.fproj/SCDPlugin.h
SystemConfiguration.fproj/SCDPrivate.c
SystemConfiguration.fproj/SCDRemove.c
SystemConfiguration.fproj/SCDSet.c
SystemConfiguration.fproj/SCDSnapshot.c
SystemConfiguration.fproj/SCDTouch.c
SystemConfiguration.fproj/SCDUnlock.c
SystemConfiguration.fproj/SCDynamicStore.h
SystemConfiguration.fproj/SCDynamicStoreCopyDHCPInfo.h
SystemConfiguration.fproj/SCDynamicStoreCopySpecific.h
SystemConfiguration.fproj/SCDynamicStoreCopySpecificPrivate.h
SystemConfiguration.fproj/SCDynamicStoreInternal.h
SystemConfiguration.fproj/SCDynamicStoreKey.h
SystemConfiguration.fproj/SCDynamicStorePrivate.h
SystemConfiguration.fproj/SCDynamicStoreSetSpecificPrivate.h
SystemConfiguration.fproj/SCLocation.c
SystemConfiguration.fproj/SCNetwork.c
SystemConfiguration.fproj/SCNetwork.h
SystemConfiguration.fproj/SCNetworkConfiguration.h [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkConfigurationInternal.c [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkConfigurationInternal.h [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkConnection.c
SystemConfiguration.fproj/SCNetworkConnection.h
SystemConfiguration.fproj/SCNetworkInterface.c [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkProtocol.c [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkReachability.c
SystemConfiguration.fproj/SCNetworkReachability.h
SystemConfiguration.fproj/SCNetworkService.c [new file with mode: 0644]
SystemConfiguration.fproj/SCNetworkSet.c [new file with mode: 0644]
SystemConfiguration.fproj/SCP.c
SystemConfiguration.fproj/SCPAdd.c
SystemConfiguration.fproj/SCPApply.c
SystemConfiguration.fproj/SCPCommit.c
SystemConfiguration.fproj/SCPGet.c
SystemConfiguration.fproj/SCPList.c
SystemConfiguration.fproj/SCPLock.c
SystemConfiguration.fproj/SCPOpen.c
SystemConfiguration.fproj/SCPPath.c
SystemConfiguration.fproj/SCPRemove.c
SystemConfiguration.fproj/SCPSet.c
SystemConfiguration.fproj/SCPUnlock.c
SystemConfiguration.fproj/SCPreferences.h
SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h [new file with mode: 0644]
SystemConfiguration.fproj/SCPreferencesInternal.h
SystemConfiguration.fproj/SCPreferencesPath.h
SystemConfiguration.fproj/SCPreferencesPathKey.c [new file with mode: 0644]
SystemConfiguration.fproj/SCPreferencesPathKey.h [new file with mode: 0644]
SystemConfiguration.fproj/SCPreferencesPrivate.h
SystemConfiguration.fproj/SCPreferencesSetSpecific.h
SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h [new file with mode: 0644]
SystemConfiguration.fproj/SCPrivate.h
SystemConfiguration.fproj/SCProxies.c
SystemConfiguration.fproj/SCSchemaDefinitions.c [new file with mode: 0644]
SystemConfiguration.fproj/SCSchemaDefinitions.h [new file with mode: 0644]
SystemConfiguration.fproj/SystemConfiguration.h
SystemConfiguration.fproj/VLANConfiguration.c
SystemConfiguration.fproj/VLANConfiguration.h
SystemConfiguration.fproj/VLANConfigurationPrivate.h
SystemConfiguration.fproj/config.defs
SystemConfiguration.fproj/dy_framework.c
SystemConfiguration.fproj/dy_framework.h
SystemConfiguration.fproj/genSCPreferences.c
SystemConfiguration.fproj/h.template [deleted file]
SystemConfiguration.fproj/m.template [deleted file]
SystemConfiguration.fproj/ppp.c [deleted file]
SystemConfiguration.fproj/ppp.h [deleted file]
SystemConfiguration.fproj/pppcontroller.defs [new file with mode: 0644]
configd.tproj/Makefile [deleted file]
configd.tproj/Makefile.postamble [deleted file]
configd.tproj/Makefile.preamble [deleted file]
configd.tproj/PB.project [deleted file]
configd.tproj/_SCD.c
configd.tproj/_SCD.h
configd.tproj/_configadd.c
configd.tproj/_configadd_s.c [deleted file]
configd.tproj/_configclose.c
configd.tproj/_configget.c
configd.tproj/_configlist.c
configd.tproj/_configlock.c
configd.tproj/_confignotify.c
configd.tproj/_configopen.c
configd.tproj/_configremove.c
configd.tproj/_configset.c
configd.tproj/_configtouch.c
configd.tproj/_configunlock.c
configd.tproj/_notifyadd.c
configd.tproj/_notifycancel.c
configd.tproj/_notifychanges.c
configd.tproj/_notifyremove.c
configd.tproj/_notifyviafd.c
configd.tproj/_notifyviaport.c
configd.tproj/_notifyviasignal.c
configd.tproj/_snapshot.c
configd.tproj/config.defs [deleted file]
configd.tproj/configd.8 [new file with mode: 0644]
configd.tproj/configd.m
configd.tproj/configd_server.c
configd.tproj/configd_server.h
configd.tproj/h.template [deleted file]
configd.tproj/m.template [deleted file]
configd.tproj/notify.c [deleted file]
configd.tproj/notify.h [deleted file]
configd.tproj/notify_server.c
configd.tproj/pattern.c
configd.tproj/plugin_support.c
configd.tproj/plugin_support.h
configd.tproj/session.c
configd.xcode/project.pbxproj [new file with mode: 0644]
dnsinfo/dnsinfo.h [new file with mode: 0644]
dnsinfo/dnsinfo_copy.c [new file with mode: 0644]
dnsinfo/dnsinfo_create.c [new file with mode: 0644]
dnsinfo/dnsinfo_create.h [new file with mode: 0644]
dnsinfo/dnsinfo_private.c [new file with mode: 0644]
dnsinfo/dnsinfo_private.h [new file with mode: 0644]
dnsinfo/dnsinfo_server.c [new file with mode: 0644]
dnsinfo/dnsinfo_server.h [new file with mode: 0644]
dnsinfo/shared_dns_info.defs [new file with mode: 0644]
dnsinfo/shared_dns_info_types.h [new file with mode: 0644]
get-mobility-info [new file with mode: 0755]
preferences.xml
scselect.tproj/Makefile [deleted file]
scselect.tproj/Makefile.postamble [deleted file]
scselect.tproj/Makefile.preamble [deleted file]
scselect.tproj/PB.project [deleted file]
scselect.tproj/h.template [deleted file]
scselect.tproj/m.template [deleted file]
scselect.tproj/scselect.8 [new file with mode: 0644]
scselect.tproj/scselect.c
scutil.tproj/Makefile [deleted file]
scutil.tproj/Makefile.postamble [deleted file]
scutil.tproj/Makefile.preamble [deleted file]
scutil.tproj/PB.project [deleted file]
scutil.tproj/cache.c
scutil.tproj/commands.c
scutil.tproj/commands.h
scutil.tproj/dictionary.c
scutil.tproj/h.template [deleted file]
scutil.tproj/m.template [deleted file]
scutil.tproj/net.c [new file with mode: 0644]
scutil.tproj/net.h [new file with mode: 0644]
scutil.tproj/net_interface.c [new file with mode: 0644]
scutil.tproj/net_interface.h [new file with mode: 0644]
scutil.tproj/net_protocol.c [new file with mode: 0644]
scutil.tproj/net_protocol.h [new file with mode: 0644]
scutil.tproj/net_service.c [new file with mode: 0644]
scutil.tproj/net_service.h [new file with mode: 0644]
scutil.tproj/net_set.c [new file with mode: 0644]
scutil.tproj/net_set.h [new file with mode: 0644]
scutil.tproj/notifications.c [new file with mode: 0644]
scutil.tproj/notifications.h [new file with mode: 0644]
scutil.tproj/notify.c [deleted file]
scutil.tproj/notify.h [deleted file]
scutil.tproj/prefs.c
scutil.tproj/scutil.8 [new file with mode: 0644]
scutil.tproj/scutil.c
scutil.tproj/scutil.h
scutil.tproj/session.c
scutil.tproj/tests.c
scutil.tproj/tests.h

diff --git a/APPLE_LICENSE b/APPLE_LICENSE
new file mode 100644 (file)
index 0000000..fe81a60
--- /dev/null
@@ -0,0 +1,367 @@
+APPLE PUBLIC SOURCE LICENSE
+Version 2.0 - August 6, 2003
+
+Please read this License carefully before downloading this software.
+By downloading or using this software, you are agreeing to be bound by
+the terms of this License. If you do not or cannot agree to the terms
+of this License, please do not download or use the software.
+
+1. General; Definitions. This License applies to any program or other
+work which Apple Computer, Inc. ("Apple") makes publicly available and
+which contains a notice placed by Apple identifying such program or
+work as "Original Code" and stating that it is subject to the terms of
+this Apple Public Source License version 2.0 ("License"). As used in
+this License:
+
+1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
+the grantor of rights, (i) claims of patents that are now or hereafter
+acquired, owned by or assigned to Apple and (ii) that cover subject
+matter contained in the Original Code, but only to the extent
+necessary to use, reproduce and/or distribute the Original Code
+without infringement; and (b) in the case where You are the grantor of
+rights, (i) claims of patents that are now or hereafter acquired,
+owned by or assigned to You and (ii) that cover subject matter in Your
+Modifications, taken alone or in combination with Original Code.
+
+1.2 "Contributor" means any person or entity that creates or
+contributes to the creation of Modifications.
+
+1.3 "Covered Code" means the Original Code, Modifications, the
+combination of Original Code and any Modifications, and/or any
+respective portions thereof.
+
+1.4 "Externally Deploy" means: (a) to sublicense, distribute or
+otherwise make Covered Code available, directly or indirectly, to
+anyone other than You; and/or (b) to use Covered Code, alone or as
+part of a Larger Work, in any way to provide a service, including but
+not limited to delivery of content, through electronic communication
+with a client other than You.
+
+1.5 "Larger Work" means a work which combines Covered Code or portions
+thereof with code not governed by the terms of this License.
+
+1.6 "Modifications" mean any addition to, deletion from, and/or change
+to, the substance and/or structure of the Original Code, any previous
+Modifications, the combination of Original Code and any previous
+Modifications, and/or any respective portions thereof. When code is
+released as a series of files, a Modification is: (a) any addition to
+or deletion from the contents of a file containing Covered Code;
+and/or (b) any new file or other representation of computer program
+statements that contains any part of Covered Code.
+
+1.7 "Original Code" means (a) the Source Code of a program or other
+work as originally made available by Apple under this License,
+including the Source Code of any updates or upgrades to such programs
+or works made available by Apple under this License, and that has been
+expressly identified by Apple as such in the header file(s) of such
+work; and (b) the object code compiled from such Source Code and
+originally made available by Apple under this License.
+
+1.8 "Source Code" means the human readable form of a program or other
+work that is suitable for making modifications to it, including all
+modules it contains, plus any associated interface definition files,
+scripts used to control compilation and installation of an executable
+(object code).
+
+1.9 "You" or "Your" means an individual or a legal entity exercising
+rights under this License. For legal entities, "You" or "Your"
+includes any entity which controls, is controlled by, or is under
+common control with, You, where "control" means (a) the power, direct
+or indirect, to cause the direction or management of such entity,
+whether by contract or otherwise, or (b) ownership of fifty percent
+(50%) or more of the outstanding shares or beneficial ownership of
+such entity.
+
+2. Permitted Uses; Conditions & Restrictions. Subject to the terms
+and conditions of this License, Apple hereby grants You, effective on
+the date You accept this License and download the Original Code, a
+world-wide, royalty-free, non-exclusive license, to the extent of
+Apple's Applicable Patent Rights and copyrights covering the Original
+Code, to do the following:
+
+2.1 Unmodified Code. You may use, reproduce, display, perform,
+internally distribute within Your organization, and Externally Deploy
+verbatim, unmodified copies of the Original Code, for commercial or
+non-commercial purposes, provided that in each instance:
+
+(a) You must retain and reproduce in all copies of Original Code the
+copyright and other proprietary notices and disclaimers of Apple as
+they appear in the Original Code, and keep intact all notices in the
+Original Code that refer to this License; and
+
+(b) You must include a copy of this License with every copy of Source
+Code of Covered Code and documentation You distribute or Externally
+Deploy, and You may not offer or impose any terms on such Source Code
+that alter or restrict this License or the recipients' rights
+hereunder, except as permitted under Section 6.
+
+2.2 Modified Code. You may modify Covered Code and use, reproduce,
+display, perform, internally distribute within Your organization, and
+Externally Deploy Your Modifications and Covered Code, for commercial
+or non-commercial purposes, provided that in each instance You also
+meet all of these conditions:
+
+(a) You must satisfy all the conditions of Section 2.1 with respect to
+the Source Code of the Covered Code;
+
+(b) You must duplicate, to the extent it does not already exist, the
+notice in Exhibit A in each file of the Source Code of all Your
+Modifications, and cause the modified files to carry prominent notices
+stating that You changed the files and the date of any change; and
+
+(c) If You Externally Deploy Your Modifications, You must make
+Source Code of all Your Externally Deployed Modifications either
+available to those to whom You have Externally Deployed Your
+Modifications, or publicly available. Source Code of Your Externally
+Deployed Modifications must be released under the terms set forth in
+this License, including the license grants set forth in Section 3
+below, for as long as you Externally Deploy the Covered Code or twelve
+(12) months from the date of initial External Deployment, whichever is
+longer. You should preferably distribute the Source Code of Your
+Externally Deployed Modifications electronically (e.g. download from a
+web site).
+
+2.3 Distribution of Executable Versions. In addition, if You
+Externally Deploy Covered Code (Original Code and/or Modifications) in
+object code, executable form only, You must include a prominent
+notice, in the code itself as well as in related documentation,
+stating that Source Code of the Covered Code is available under the
+terms of this License with information on how and where to obtain such
+Source Code.
+
+2.4 Third Party Rights. You expressly acknowledge and agree that
+although Apple and each Contributor grants the licenses to their
+respective portions of the Covered Code set forth herein, no
+assurances are provided by Apple or any Contributor that the Covered
+Code does not infringe the patent or other intellectual property
+rights of any other entity. Apple and each Contributor disclaim any
+liability to You for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a
+condition to exercising the rights and licenses granted hereunder, You
+hereby assume sole responsibility to secure any other intellectual
+property rights needed, if any. For example, if a third party patent
+license is required to allow You to distribute the Covered Code, it is
+Your responsibility to acquire that license before distributing the
+Covered Code.
+
+3. Your Grants. In consideration of, and as a condition to, the
+licenses granted to You under this License, You hereby grant to any
+person or entity receiving or distributing Covered Code under this
+License a non-exclusive, royalty-free, perpetual, irrevocable license,
+under Your Applicable Patent Rights and other intellectual property
+rights (other than patent) owned or controlled by You, to use,
+reproduce, display, perform, modify, sublicense, distribute and
+Externally Deploy Your Modifications of the same scope and extent as
+Apple's licenses under Sections 2.1 and 2.2 above.
+
+4. Larger Works. You may create a Larger Work by combining Covered
+Code with other code not governed by the terms of this License and
+distribute the Larger Work as a single product. In each such instance,
+You must make sure the requirements of this License are fulfilled for
+the Covered Code or any portion thereof.
+
+5. Limitations on Patent License. Except as expressly stated in
+Section 2, no other patent rights, express or implied, are granted by
+Apple herein. Modifications and/or Larger Works may require additional
+patent licenses from Apple which Apple may grant in its sole
+discretion.
+
+6. Additional Terms. You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations and/or other
+rights consistent with the scope of the license granted herein
+("Additional Terms") to one or more recipients of Covered Code.
+However, You may do so only on Your own behalf and as Your sole
+responsibility, and not on behalf of Apple or any Contributor. You
+must obtain the recipient's agreement that any such Additional Terms
+are offered by You alone, and You hereby agree to indemnify, defend
+and hold Apple and every Contributor harmless for any liability
+incurred by or claims asserted against Apple or such Contributor by
+reason of any such Additional Terms.
+
+7. Versions of the License. Apple may publish revised and/or new
+versions of this License from time to time. Each version will be given
+a distinguishing version number. Once Original Code has been published
+under a particular version of this License, You may continue to use it
+under the terms of that version. You may also choose to use such
+Original Code under the terms of any subsequent version of this
+License published by Apple. No one other than Apple has the right to
+modify the terms applicable to Covered Code created under this
+License.
+
+8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
+part pre-release, untested, or not fully tested works. The Covered
+Code may contain errors that could cause failures or loss of data, and
+may be incomplete or contain inaccuracies. You expressly acknowledge
+and agree that use of the Covered Code, or any portion thereof, is at
+Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
+WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
+APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
+PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
+ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
+MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
+PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
+PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
+INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
+FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
+THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
+ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
+ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
+AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
+You acknowledge that the Covered Code is not intended for use in the
+operation of nuclear facilities, aircraft navigation, communication
+systems, or air traffic control machines in which case the failure of
+the Covered Code could lead to death, personal injury, or severe
+physical or environmental damage.
+
+9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
+TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
+ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
+TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
+APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
+REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
+TO YOU. In no event shall Apple's total liability to You for all
+damages (other than as may be required by applicable law) under this
+License exceed the amount of fifty dollars ($50.00).
+
+10. Trademarks. This License does not grant any rights to use the
+trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
+"QuickTime", "QuickTime Streaming Server" or any other trademarks,
+service marks, logos or trade names belonging to Apple (collectively
+"Apple Marks") or to any trademark, service mark, logo or trade name
+belonging to any Contributor. You agree not to use any Apple Marks in
+or as part of the name of products derived from the Original Code or
+to endorse or promote products derived from the Original Code other
+than as expressly permitted by and in strict compliance at all times
+with Apple's third party trademark usage guidelines which are posted
+at http://www.apple.com/legal/guidelinesfor3rdparties.html.
+
+11. Ownership. Subject to the licenses granted under this License,
+each Contributor retains all rights, title and interest in and to any
+Modifications made by such Contributor. Apple retains all rights,
+title and interest in and to the Original Code and any Modifications
+made by or on behalf of Apple ("Apple Modifications"), and such Apple
+Modifications will not be automatically subject to this License. Apple
+may, at its sole discretion, choose to license such Apple
+Modifications under this License, or on different terms from those
+contained in this License or may choose not to license them at all.
+
+12. Termination.
+
+12.1 Termination. This License and the rights granted hereunder will
+terminate:
+
+(a) automatically without notice from Apple if You fail to comply with
+any term(s) of this License and fail to cure such breach within 30
+days of becoming aware of such breach;
+
+(b) immediately in the event of the circumstances described in Section
+13.5(b); or
+
+(c) automatically without notice from Apple if You, at any time during
+the term of this License, commence an action for patent infringement
+against Apple; provided that Apple did not first commence
+an action for patent infringement against You in that instance.
+
+12.2 Effect of Termination. Upon termination, You agree to immediately
+stop any further use, reproduction, modification, sublicensing and
+distribution of the Covered Code. All sublicenses to the Covered Code
+which have been properly granted prior to termination shall survive
+any termination of this License. Provisions which, by their nature,
+should remain in effect beyond the termination of this License shall
+survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
+12.2 and 13. No party will be liable to any other for compensation,
+indemnity or damages of any sort solely as a result of terminating
+this License in accordance with its terms, and termination of this
+License will be without prejudice to any other right or remedy of
+any party.
+
+13. Miscellaneous.
+
+13.1 Government End Users. The Covered Code is a "commercial item" as
+defined in FAR 2.101. Government software and technical data rights in
+the Covered Code include only those rights customarily provided to the
+public as defined in this License. This customary commercial license
+in technical data and software is provided in accordance with FAR
+12.211 (Technical Data) and 12.212 (Computer Software) and, for
+Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
+Commercial Items) and 227.7202-3 (Rights in Commercial Computer
+Software or Computer Software Documentation). Accordingly, all U.S.
+Government End Users acquire Covered Code with only those rights set
+forth herein.
+
+13.2 Relationship of Parties. This License will not be construed as
+creating an agency, partnership, joint venture or any other form of
+legal association between or among You, Apple or any Contributor, and
+You will not represent to the contrary, whether expressly, by
+implication, appearance or otherwise.
+
+13.3 Independent Development. Nothing in this License will impair
+Apple's right to acquire, license, develop, have others develop for
+it, market and/or distribute technology or products that perform the
+same or similar functions as, or otherwise compete with,
+Modifications, Larger Works, technology or products that You may
+develop, produce, market or distribute.
+
+13.4 Waiver; Construction. Failure by Apple or any Contributor to
+enforce any provision of this License will not be deemed a waiver of
+future enforcement of that or any other provision. Any law or
+regulation which provides that the language of a contract shall be
+construed against the drafter will not apply to this License.
+
+13.5 Severability. (a) If for any reason a court of competent
+jurisdiction finds any provision of this License, or portion thereof,
+to be unenforceable, that provision of the License will be enforced to
+the maximum extent permissible so as to effect the economic benefits
+and intent of the parties, and the remainder of this License will
+continue in full force and effect. (b) Notwithstanding the foregoing,
+if applicable law prohibits or restricts You from fully and/or
+specifically complying with Sections 2 and/or 3 or prevents the
+enforceability of either of those Sections, this License will
+immediately terminate and You must immediately discontinue any use of
+the Covered Code and destroy all copies of it that are in your
+possession or control.
+
+13.6 Dispute Resolution. Any litigation or other dispute resolution
+between You and Apple relating to this License shall take place in the
+Northern District of California, and You and Apple hereby consent to
+the personal jurisdiction of, and venue in, the state and federal
+courts within that District with respect to this License. The
+application of the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded.
+
+13.7 Entire Agreement; Governing Law. This License constitutes the
+entire agreement between the parties with respect to the subject
+matter hereof. This License shall be governed by the laws of the
+United States and the State of California, except that body of
+California law concerning conflicts of law.
+
+Where You are located in the province of Quebec, Canada, the following
+clause applies: The parties hereby confirm that they have requested
+that this License and all related documents be drafted in English. Les
+parties ont exige que le present contrat et tous les documents
+connexes soient rediges en anglais.
+
+EXHIBIT A.
+
+"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
+Reserved.
+
+This file contains Original Code and/or Modifications of Original Code
+as defined in and that are subject to the Apple Public Source License
+Version 2.0 (the 'License'). You may not use this file except in
+compliance with the License. Please obtain a copy of the License at
+http://www.opensource.apple.com/apsl/ and read it before using this
+file.
+
+The Original Code and all software distributed under the License are
+distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+Please see the License for the specific language governing rights and
+limitations under the License."
diff --git a/Makefile b/Makefile
deleted file mode 100644 (file)
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 (file)
index 8198896..0000000
+++ /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 (file)
index 480f47f..0000000
+++ /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: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
-AFTER_INSTALL = install_extra
diff --git a/PB.project b/PB.project
deleted file mode 100644 (file)
index 2890710..0000000
+++ /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 (file)
index 0000000..048a8f9
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>ATconfig</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.ATconfig</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Requires</key>
+       <array>
+               <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+               <string>com.apple.SystemConfiguration.KernelEventMonitor</string>
+               <string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+       </array>
+</dict>
+</plist>
diff --git a/Plugins/ATconfig/atconfig.c b/Plugins/ATconfig/atconfig.c
new file mode 100644 (file)
index 0000000..7bf129e
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - startup/shutdown AT networking without Kicker's help and
+ *   publish the state information after the configuration is
+ *   active.
+ *
+ * April 29, 2002              Allan Nathanson <ajn@apple.com>
+ * - add global state information (primary service, interface)
+ *
+ * June 24, 2001               Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * July 7, 2000                        Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <netat/appletalk.h>
+#include <netat/at_var.h>
+#include <AppleTalk/at_paths.h>
+#include <AppleTalk/at_proto.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCDPlugin.h>
+#include <SystemConfiguration/SCValidation.h>
+
+#include "cache.h"
+#include "cfManager.h"
+
+#define HOSTCONFIG     "/etc/hostconfig"
+
+static SCDynamicStoreRef       store           = NULL;
+static CFRunLoopSourceRef      storeRls        = NULL;
+
+static int                     curState        = 0;    // abs(state) == sequence #, < 0 == stop, > 0 == start
+static CFMutableDictionaryRef  curGlobals      = NULL;
+static CFMutableArrayRef       curConfigFile   = NULL;
+static CFMutableDictionaryRef  curDefaults     = NULL;
+static CFMutableDictionaryRef  curStartup      = NULL;
+
+static Boolean                 _verbose        = FALSE;
+
+
+static void    stopAppleTalk (CFRunLoopTimerRef timer, void *info);
+static void    startAppleTalk(CFRunLoopTimerRef timer, void *info);
+
+
+static void
+updateDefaults(const void *key, const void *val, void *context)
+{
+       CFStringRef             ifName          = (CFStringRef)key;
+       CFDictionaryRef         oldDict;
+       CFDictionaryRef         newDict         = (CFDictionaryRef)val;
+       CFNumberRef             defaultNode;
+       CFNumberRef             defaultNetwork;
+       CFStringRef             defaultZone;
+
+       if (!CFDictionaryGetValueIfPresent(curDefaults, ifName, (const void **)&oldDict) ||
+           !CFEqual(oldDict, newDict)) {
+               char            ifr_name[IFNAMSIZ+1];
+
+               bzero(&ifr_name, sizeof(ifr_name));
+               if (!_SC_cfstring_to_cstring(ifName, ifr_name, sizeof(ifr_name), kCFStringEncodingASCII)) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("could not convert interface name to C string"));
+                       return;
+               }
+
+               /*
+                * Set preferred Network and Node ID
+                */
+               if (CFDictionaryGetValueIfPresent(newDict,
+                                                 kSCPropNetAppleTalkNetworkID,
+                                                 (const void **)&defaultNetwork) &&
+                   CFDictionaryGetValueIfPresent(newDict,
+                                                 kSCPropNetAppleTalkNodeID,
+                                                 (const void **)&defaultNode)
+                   ) {
+                       struct at_addr  init_address;
+                       int             status;
+
+                       /*
+                        * set the default node and network
+                        */
+                       CFNumberGetValue(defaultNetwork, kCFNumberShortType, &init_address.s_net);
+                       CFNumberGetValue(defaultNode,    kCFNumberCharType,  &init_address.s_node);
+                       status = at_setdefaultaddr(ifr_name, &init_address);
+                       if (status == -1) {
+                               SCLog(TRUE, LOG_ERR, CFSTR("at_setdefaultaddr() failed"));
+                               return;
+                       }
+               }
+
+               /*
+                * Set default zone
+                */
+               if (CFDictionaryGetValueIfPresent(newDict,
+                                                 kSCPropNetAppleTalkDefaultZone,
+                                                 (const void **)&defaultZone)
+                   ) {
+                       int             status;
+                       at_nvestr_t     zone;
+
+                       /*
+                        * set the "default zone" for this interface
+                        */
+                       bzero(&zone, sizeof(zone));
+                       if (!_SC_cfstring_to_cstring(defaultZone, zone.str, sizeof(zone.str), kCFStringEncodingASCII)) {
+                               SCLog(TRUE, LOG_ERR, CFSTR("could not convert default zone to C string"));
+                               return;
+                       }
+
+                       zone.len = strlen(zone.str);
+                       status = at_setdefaultzone(ifr_name, &zone);
+                       if (status == -1) {
+                               SCLog(TRUE, LOG_ERR, CFSTR("at_setdefaultzone() failed"));
+                               return;
+                       }
+               }
+       }
+
+       return;
+}
+
+
+static void
+addZoneToPorts(const void *key, const void *val, void *context)
+{
+       CFStringRef             zone            = (CFStringRef)key;
+       CFArrayRef              ifArray         = (CFArrayRef)val;
+       CFMutableArrayRef       zones           = (CFMutableArrayRef)context;
+       CFStringRef             ifList;
+       CFStringRef             configInfo;
+
+       ifList = CFStringCreateByCombiningStrings(NULL, ifArray, CFSTR(":"));
+       configInfo = CFStringCreateWithFormat(NULL, NULL, CFSTR(":%@:%@"), zone, ifList);
+       CFArrayAppendValue(zones, configInfo);
+       CFRelease(configInfo);
+       CFRelease(ifList);
+       return;
+}
+
+
+/*
+ * Function: parse_component
+ * Purpose:
+ *   Given a string 'key' and a string prefix 'prefix',
+ *   return the next component in the slash '/' separated
+ *   key.
+ *
+ * Examples:
+ * 1. key = "a/b/c" prefix = "a/"
+ *    returns "b"
+ * 2. key = "a/b/c" prefix = "a/b/"
+ *    returns "c"
+ */
+static CFStringRef
+parse_component(CFStringRef key, CFStringRef prefix)
+{
+       CFMutableStringRef      comp;
+       CFRange                 range;
+
+       if (CFStringHasPrefix(key, prefix) == FALSE) {
+               return NULL;
+       }
+       comp = CFStringCreateMutableCopy(NULL, 0, key);
+       CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
+       range = CFStringFind(comp, CFSTR("/"), 0);
+       if (range.location == kCFNotFound) {
+               return comp;
+       }
+       range.length = CFStringGetLength(comp) - range.location;
+       CFStringDelete(comp, range);
+       return comp;
+}
+
+
+static CFDictionaryRef
+entity_one(SCDynamicStoreRef store, CFStringRef key)
+{
+       CFDictionaryRef         ent_dict        = NULL;
+       CFDictionaryRef         if_dict         = NULL;
+       CFStringRef             if_key          = NULL;
+       CFStringRef             if_port;
+       CFMutableDictionaryRef  new_dict        = NULL;
+       static CFStringRef      pre             = NULL;
+       CFStringRef             serviceID       = NULL;
+       CFStringRef             serviceType;
+
+       if (!pre) {
+               pre = SCDynamicStoreKeyCreate(NULL,
+                                             CFSTR("%@/%@/%@/"),
+                                             kSCDynamicStoreDomainSetup,
+                                             kSCCompNetwork,
+                                             kSCCompService);
+       }
+
+       /*
+        * get entity dictionary for service
+        */
+       ent_dict = cache_SCDynamicStoreCopyValue(store, key);
+       if (!isA_CFDictionary(ent_dict)) {
+               goto done;
+       }
+
+       /*
+        * get interface dictionary for service
+        */
+       serviceID = parse_component(key, pre);
+       if (!serviceID) {
+               goto done;
+       }
+
+       if_key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                            kSCDynamicStoreDomainSetup,
+                                                            serviceID,
+                                                            kSCEntNetInterface);
+       if_dict = cache_SCDynamicStoreCopyValue(store, if_key);
+       CFRelease(if_key);
+       if (!isA_CFDictionary(if_dict)) {
+               goto done;
+       }
+
+       /* check the interface type */
+       serviceType = CFDictionaryGetValue(if_dict,
+                                          kSCPropNetInterfaceType);
+       if (!isA_CFString(serviceType) ||
+           !CFEqual(serviceType, kSCValNetInterfaceTypeEthernet)) {
+               /* sorry, no AT networking on this interface */
+               goto done;
+       }
+
+       /*
+        * get port name (from interface dictionary).
+        */
+       if_port = CFDictionaryGetValue(if_dict, kSCPropNetInterfaceDeviceName);
+       if (!isA_CFString(if_port)) {
+               goto done;
+       }
+
+       /*
+        * add ServiceID and interface port name to entity dictionary.
+        */
+       new_dict = CFDictionaryCreateMutableCopy(NULL, 0, ent_dict);
+       CFDictionarySetValue(new_dict, CFSTR("ServiceID"), serviceID);
+       CFDictionarySetValue(new_dict, kSCPropNetInterfaceDeviceName, if_port);
+
+    done:
+
+       if (ent_dict)   CFRelease(ent_dict);
+       if (if_dict)    CFRelease(if_dict);
+       if (serviceID)  CFRelease(serviceID);
+       return (CFDictionaryRef)new_dict;
+}
+
+
+static CFArrayRef
+entity_all(SCDynamicStoreRef store, CFStringRef entity, CFArrayRef order)
+{
+       CFMutableArrayRef       defined = NULL;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFMutableArrayRef       ordered = NULL;
+       CFStringRef             pattern;
+
+       ordered = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCDynamicStoreDomainSetup,
+                                                             kSCCompAnyRegex,
+                                                             entity);
+       defined = (CFMutableArrayRef)SCDynamicStoreCopyKeyList(store, pattern);
+       CFRelease(pattern);
+       if (defined && (CFArrayGetCount(defined) > 0)) {
+               CFArrayRef      tmp;
+
+               tmp = defined;
+               defined = CFArrayCreateMutableCopy(NULL, 0, tmp);
+               CFRelease(tmp);
+       } else {
+               goto done;
+       }
+
+       n = order ? CFArrayGetCount(order) : 0;
+       for (i = 0; i < n; i++) {
+               CFDictionaryRef dict;
+               CFStringRef     key;
+               CFIndex         j;
+               CFStringRef     service;
+
+               service = CFArrayGetValueAtIndex(order, i);
+               if (!isA_CFString(service)) {
+                       continue;
+               }
+
+               key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                 kSCDynamicStoreDomainSetup,
+                                                                 service,
+                                                                 entity);
+               dict = entity_one(store, key);
+               if (dict) {
+                       CFArrayAppendValue(ordered, dict);
+                       CFRelease(dict);
+               }
+
+               j = CFArrayGetFirstIndexOfValue(defined,
+                                               CFRangeMake(0, CFArrayGetCount(defined)),
+                                               key);
+               if (j != kCFNotFound) {
+                       CFArrayRemoveValueAtIndex(defined, j);
+               }
+
+               CFRelease(key);
+       }
+
+       n = CFArrayGetCount(defined);
+       for (i = 0; i < n; i++) {
+               CFDictionaryRef dict;
+               CFStringRef     key;
+
+               key  = CFArrayGetValueAtIndex(defined, i);
+               dict = entity_one(store, key);
+               if (dict) {
+                       CFArrayAppendValue(ordered, dict);
+                       CFRelease(dict);
+               }
+       }
+
+    done:
+
+       if (defined)    CFRelease(defined);
+       if (CFArrayGetCount(ordered) == 0) {
+               CFRelease(ordered);
+               ordered = NULL;
+       }
+       return ordered;
+}
+
+
+static void
+encodeName(CFStringRef                 name,
+          CFStringEncoding             encoding,
+          CFMutableDictionaryRef       startup,
+          CFMutableDictionaryRef       globals)
+{
+       CFDataRef               bytes;
+       CFMutableStringRef      encodedName = NULL;
+       CFIndex                 len;
+
+       if (!isA_CFString(name)) {
+               return;
+       }
+
+       if (encoding == kCFStringEncodingASCII) {
+               encodedName = (CFMutableStringRef)CFStringCreateCopy(NULL, name);
+               goto done;
+       }
+
+       /*
+        * encode the potentially non-printable string
+        */
+       bytes = CFStringCreateExternalRepresentation(NULL,
+                                                    name,
+                                                    encoding,
+                                                    0);
+       if (bytes) {
+               unsigned char   *byte;
+               CFIndex         i;
+
+               /*
+                * check if the MacRoman string can be represented as ASCII
+                */
+               if (encoding == kCFStringEncodingMacRoman) {
+                       CFDataRef       ascii;
+
+                       ascii = CFStringCreateExternalRepresentation(NULL,
+                                                                    name,
+                                                                    kCFStringEncodingASCII,
+                                                                    0);
+                       if (ascii) {
+                               CFRelease(ascii);
+                               CFRelease(bytes);
+                               encodedName = (CFMutableStringRef)CFStringCreateCopy(NULL, name);
+                               goto done;
+                       }
+               }
+
+               encodedName = CFStringCreateMutable(NULL, 0);
+
+               len  = CFDataGetLength(bytes);
+               byte = (unsigned char *)CFDataGetBytePtr(bytes);
+               for (i = 0; i < len; i++, byte++) {
+                       CFStringAppendFormat(encodedName,
+                                            NULL,
+                                            CFSTR("%02x"),
+                                            *byte);
+               }
+
+               /*
+                * add "encoded string" markers
+                */
+               CFStringInsert(encodedName, 0, CFSTR("*"));
+               CFStringAppend(encodedName,    CFSTR("*"));
+
+               CFRelease(bytes);
+       }
+
+    done :
+
+       if (encodedName) {
+               if (startup) {
+                       /* update "startup" dictionary */
+                       CFDictionaryAddValue(startup, CFSTR("APPLETALK_HOSTNAME"), encodedName);
+               }
+
+               if (globals) {
+                       CFNumberRef     num;
+
+                       /* update "global" dictionary */
+                       num = CFNumberCreate(NULL, kCFNumberIntType, &encoding);
+                       CFDictionaryAddValue(globals, kSCPropNetAppleTalkComputerName,         name);
+                       CFDictionaryAddValue(globals, kSCPropNetAppleTalkComputerNameEncoding, num);
+                       CFRelease(num);
+               }
+
+               CFRelease(encodedName);
+       }
+
+       return;
+}
+
+
+static boolean_t
+updateConfiguration(int *newState)
+{
+       boolean_t               changed                 = FALSE;
+       CFStringRef             computerName;
+       CFStringEncoding        computerNameEncoding;
+       CFArrayRef              configuredServices      = NULL;
+       CFDictionaryRef         dict;
+       CFIndex                 i;
+       CFIndex                 ifCount                 = 0;
+       CFMutableArrayRef       info                    = NULL;
+       CFArrayRef              interfaces              = NULL;
+       CFStringRef             key;
+       CFArrayRef              keys;
+       CFIndex                 n;
+       CFMutableArrayRef       newConfigFile;
+       CFMutableDictionaryRef  newDefaults;
+       CFMutableDictionaryRef  newDict;
+       CFMutableDictionaryRef  newGlobals;
+       CFMutableDictionaryRef  newGlobalsX;                    /* newGlobals without ServiceID */
+       CFMutableDictionaryRef  newStartup;
+       CFMutableDictionaryRef  newZones;
+       CFNumberRef             num;
+       CFMutableDictionaryRef  curGlobalsX;                    /* curGlobals without ServiceID */
+       CFStringRef             pattern;
+       boolean_t               postGlobals             = FALSE;
+       CFStringRef             primaryPort             = NULL; /* primary interface */
+       CFStringRef             primaryZone             = NULL;
+       CFArrayRef              serviceOrder            = NULL;
+       CFDictionaryRef         setGlobals              = NULL;
+
+       cache_open();
+
+       /*
+        * establish the "new" AppleTalk configuration
+        */
+       *newState     = curState;
+       newConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       newGlobals    = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+       newDefaults   = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+       newStartup    = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+       newZones      = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+
+       /* initialize overall state */
+       CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-NO-"));
+
+       /*
+        * get the global settings (ServiceOrder, ComputerName, ...)
+        */
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainSetup,
+                                                        kSCEntNetAppleTalk);
+       setGlobals = cache_SCDynamicStoreCopyValue(store, key);
+       CFRelease(key);
+       if (setGlobals) {
+               if (isA_CFDictionary(setGlobals)) {
+                       /* get service order */
+                       serviceOrder = CFDictionaryGetValue(setGlobals,
+                                                           kSCPropNetServiceOrder);
+                       serviceOrder = isA_CFArray(serviceOrder);
+                       if (serviceOrder) {
+                               CFRetain(serviceOrder);
+                       }
+               } else {
+                       CFRelease(setGlobals);
+                       setGlobals = NULL;
+               }
+       }
+
+       /*
+        * if we don't have an AppleTalk ServiceOrder, use IPv4's (if defined)
+        */
+       if (!serviceOrder) {
+               key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                                kSCDynamicStoreDomainSetup,
+                                                                kSCEntNetIPv4);
+               dict = cache_SCDynamicStoreCopyValue(store, key);
+               CFRelease(key);
+               if (dict) {
+                       if (isA_CFDictionary(dict)) {
+                               serviceOrder = CFDictionaryGetValue(dict,
+                                                                   kSCPropNetServiceOrder);
+                               serviceOrder = isA_CFArray(serviceOrder);
+                               if (serviceOrder) {
+                                       CFRetain(serviceOrder);
+                               }
+                       }
+                       CFRelease(dict);
+               }
+       }
+
+       /*
+        * get the list of ALL configured services
+        */
+       configuredServices = entity_all(store, kSCEntNetAppleTalk, serviceOrder);
+       if (configuredServices) {
+               ifCount = CFArrayGetCount(configuredServices);
+       }
+
+       if (serviceOrder)       CFRelease(serviceOrder);
+
+       /*
+        * get the list of ALL active interfaces
+        */
+       key  = SCDynamicStoreKeyCreateNetworkInterface(NULL, kSCDynamicStoreDomainState);
+       dict = cache_SCDynamicStoreCopyValue(store, key);
+       CFRelease(key);
+       if (dict) {
+               if (isA_CFDictionary(dict)) {
+                       interfaces = CFDictionaryGetValue(dict,
+                                                         kSCDynamicStorePropNetInterfaces);
+                       interfaces = isA_CFArray(interfaces);
+                       if (interfaces) {
+                               CFRetain(interfaces);
+                       }
+               }
+               CFRelease(dict);
+       }
+
+       /*
+        * get the list of previously configured services
+        */
+       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCDynamicStoreDomainState,
+                                                             kSCCompAnyRegex,
+                                                             kSCEntNetAppleTalk);
+       keys = SCDynamicStoreCopyKeyList(store, pattern);
+       CFRelease(pattern);
+       if (keys) {
+               info = CFArrayCreateMutableCopy(NULL, 0, keys);
+               CFRelease(keys);
+       }
+
+       /*
+        * iterate over each configured service to establish the new
+        * configuration.
+        */
+       for (i = 0; i < ifCount; i++) {
+               CFDictionaryRef         service;
+               CFStringRef             ifName;
+               CFStringRef             configMethod;
+               CFMutableStringRef      portConfig      = NULL;
+               CFArrayRef              networkRange;   /* for seed ports, CFArray[2] of CFNumber (lo, hi) */
+               int                     sNetwork;
+               int                     eNetwork;
+               CFArrayRef              zoneList;       /* for seed ports, CFArray[] of CFString (zones names) */
+               CFIndex                 zCount;
+               CFIndex                 j;
+               CFMutableDictionaryRef  ifDefaults      = NULL;
+               CFNumberRef             defaultNetwork;
+               CFNumberRef             defaultNode;
+               CFStringRef             defaultZone;
+
+               /* get AppleTalk service dictionary */
+               service = CFArrayGetValueAtIndex(configuredServices, i);
+
+               /* get interface name */
+               ifName  = CFDictionaryGetValue(service, kSCPropNetInterfaceDeviceName);
+
+               /* check inteface availability */
+               if (!interfaces ||
+                   !CFArrayContainsValue(interfaces, CFRangeMake(0, CFArrayGetCount(interfaces)), ifName)) {
+                       /* if interface not available */
+                       goto nextIF;
+               }
+
+               /* check interface link status */
+               key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                   kSCDynamicStoreDomainState,
+                                                                   ifName,
+                                                                   kSCEntNetLink);
+               dict = cache_SCDynamicStoreCopyValue(store, key);
+               CFRelease(key);
+               if (dict) {
+                       Boolean linkStatus      = TRUE;  /* assume the link is "up" */
+                       Boolean ifDetaching     = FALSE; /* assume link is not detaching */
+
+                       /* the link key for this interface is available */
+                       if (isA_CFDictionary(dict)) {
+                               CFBooleanRef    bVal;
+
+                               bVal = CFDictionaryGetValue(dict, kSCPropNetLinkActive);
+                               if (isA_CFBoolean(bVal)) {
+                                       linkStatus = CFBooleanGetValue(bVal);
+                               }
+
+                               /* check if interface is detaching - value
+                                  doesn't really matter, only that it exists */
+                               ifDetaching = CFDictionaryContainsKey(dict, kSCPropNetLinkDetaching);
+                       }
+                       CFRelease(dict);
+
+                       if (!linkStatus || ifDetaching) {
+                               /* if link status down or the interface is detaching */
+                               goto nextIF;
+                       }
+               }
+
+               /*
+                * Determine configuration method for this service
+                */
+               configMethod = CFDictionaryGetValue(service, kSCPropNetAppleTalkConfigMethod);
+               if (!isA_CFString(configMethod)) {
+                       /* if no ConfigMethod */
+                       goto nextIF;
+               }
+
+               if (!CFEqual(configMethod, kSCValNetAppleTalkConfigMethodNode      ) &&
+                   !CFEqual(configMethod, kSCValNetAppleTalkConfigMethodRouter    ) &&
+                   !CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+                       /* if not one of the expected values, disable */
+                       SCLog(TRUE, LOG_NOTICE,
+                             CFSTR("Unexpected AppleTalk ConfigMethod: %@"),
+                             configMethod);
+                       goto nextIF;
+               }
+
+               /*
+                * the first service to be defined will always be "primary"
+                */
+               if (CFArrayGetCount(newConfigFile) == 0) {
+                       CFDictionaryRef active;
+
+                       CFDictionarySetValue(newGlobals,
+                                            kSCDynamicStorePropNetPrimaryService,
+                                            CFDictionaryGetValue(service, CFSTR("ServiceID")));
+                       CFDictionarySetValue(newGlobals,
+                                            kSCDynamicStorePropNetPrimaryInterface,
+                                            ifName);
+
+                       /* and check if AT newtorking is active on the primary interface */
+                       key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                           kSCDynamicStoreDomainState,
+                                                                           ifName,
+                                                                           kSCEntNetAppleTalk);
+                       active = cache_SCDynamicStoreCopyValue(store, key);
+                       CFRelease(key);
+                       if (active) {
+                               if (isA_CFDictionary(active)) {
+                                       postGlobals = TRUE;
+                               }
+                               CFRelease(active);
+                       }
+               }
+
+               /*
+                * define the port
+                */
+               portConfig = CFStringCreateMutable(NULL, 0);
+               CFStringAppendFormat(portConfig, NULL, CFSTR("%@:"), ifName);
+
+               if (CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+                       CFNumberRef     num;
+
+                       /*
+                        * we have been asked to configure this interface as a
+                        * seed port. Ensure that we have been provided at least
+                        * one network number, have been provided with at least
+                        * one zonename, ...
+                        */
+
+                       networkRange = CFDictionaryGetValue(service,
+                                                           kSCPropNetAppleTalkSeedNetworkRange);
+                       if (!isA_CFArray(networkRange) || (CFArrayGetCount(networkRange) == 0)) {
+                               SCLog(TRUE, LOG_NOTICE,
+                                     CFSTR("AppleTalk configuration error (%@)"),
+                                     kSCPropNetAppleTalkSeedNetworkRange);
+                               goto nextIF;
+                       }
+
+                       /*
+                        * establish the starting and ending network numbers
+                        */
+                       num = CFArrayGetValueAtIndex(networkRange, 0);
+                       if (!isA_CFNumber(num)) {
+                               SCLog(TRUE, LOG_NOTICE,
+                                     CFSTR("AppleTalk configuration error (%@)"),
+                                     kSCPropNetAppleTalkSeedNetworkRange);
+                               goto nextIF;
+                       }
+                       CFNumberGetValue(num, kCFNumberIntType, &sNetwork);
+                       eNetwork = sNetwork;
+
+                       if (CFArrayGetCount(networkRange) > 1) {
+                               num = CFArrayGetValueAtIndex(networkRange, 1);
+                               if (!isA_CFNumber(num)) {
+                                       SCLog(TRUE, LOG_NOTICE,
+                                             CFSTR("AppleTalk configuration error (%@)"),
+                                             kSCPropNetAppleTalkSeedNetworkRange);
+                                       goto nextIF;
+                               }
+                               CFNumberGetValue(num, kCFNumberIntType, &eNetwork);
+                       }
+                       CFStringAppendFormat(portConfig, NULL, CFSTR("%d:%d:"), sNetwork, eNetwork);
+
+                       /*
+                        * establish the zones associated with this port
+                        */
+                       zoneList = CFDictionaryGetValue(service,
+                                                       kSCPropNetAppleTalkSeedZones);
+                       if (!isA_CFArray(zoneList)) {
+                               SCLog(TRUE, LOG_NOTICE,
+                                     CFSTR("AppleTalk configuration error (%@)"),
+                                     kSCPropNetAppleTalkSeedZones);
+                               goto nextIF;
+                       }
+
+                       zCount = CFArrayGetCount(zoneList);
+                       for (j = 0; j < zCount; j++) {
+                               CFStringRef             zone;
+                               CFArrayRef              ifList;
+                               CFMutableArrayRef       newIFList;
+
+                               zone = CFArrayGetValueAtIndex(zoneList, j);
+                               if (!isA_CFString(zone)) {
+                                       continue;
+                               }
+
+                               if (CFDictionaryGetValueIfPresent(newZones, zone, (const void **)&ifList)) {
+                                       /* known zone */
+                                       newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+                               } else {
+                                       /* new zone */
+                                       newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                               }
+                               CFArrayAppendValue(newIFList, ifName);
+                               CFArraySortValues(newIFList,
+                                                 CFRangeMake(0, CFArrayGetCount(newIFList)),
+                                                 (CFComparatorFunction)CFStringCompare,
+                                                 NULL);
+                               CFDictionarySetValue(newZones, zone, newIFList);
+                               CFRelease(newIFList);
+
+                               /*
+                                * flag the default zone
+                                */
+                               if (!primaryZone) {
+                                       primaryZone = CFRetain(zone);
+                               }
+                       }
+                       if (!primaryZone) {
+                               SCLog(TRUE, LOG_NOTICE,
+                                     CFSTR("AppleTalk configuration error (%@)"),
+                                     kSCPropNetAppleTalkSeedZones);
+                               goto nextIF;
+                       }
+               }
+
+               /* get the (per-interface) "Computer Name" */
+               computerName = CFDictionaryGetValue(service,
+                                                   kSCPropNetAppleTalkComputerName);
+               if (CFDictionaryGetValueIfPresent(service,
+                                                 kSCPropNetAppleTalkComputerNameEncoding,
+                                                 (const void **)&num) &&
+                   isA_CFNumber(num)) {
+                       CFNumberGetValue(num, kCFNumberIntType, &computerNameEncoding);
+               } else {
+                       computerNameEncoding = CFStringGetSystemEncoding();
+               }
+               encodeName(computerName, computerNameEncoding, newStartup, newGlobals);
+
+               /*
+                * declare the first configured AppleTalk service / interface
+                * as the "home port".
+                */
+               if (CFArrayGetCount(newConfigFile) == 0) {
+                       CFStringAppend(portConfig, CFSTR("*"));
+                       primaryPort = CFRetain(ifName);
+               }
+               CFArrayAppendValue(newConfigFile, portConfig);
+
+               /*
+                * get the per-interface defaults
+                */
+               ifDefaults = CFDictionaryCreateMutable(NULL,
+                                                      0,
+                                                      &kCFTypeDictionaryKeyCallBacks,
+                                                      &kCFTypeDictionaryValueCallBacks);
+
+               defaultNetwork = CFDictionaryGetValue(service, kSCPropNetAppleTalkNetworkID);
+               defaultNode    = CFDictionaryGetValue(service, kSCPropNetAppleTalkNodeID);
+               if (isA_CFNumber(defaultNetwork) && isA_CFNumber(defaultNode)) {
+                       /*
+                        * set the default node and network
+                        */
+                       CFDictionarySetValue(ifDefaults,
+                                            kSCPropNetAppleTalkNetworkID,
+                                            defaultNetwork);
+                       CFDictionarySetValue(ifDefaults,
+                                            kSCPropNetAppleTalkNodeID,
+                                            defaultNode);
+               }
+
+               if ((CFDictionaryGetValueIfPresent(service,
+                                                  kSCPropNetAppleTalkDefaultZone,
+                                                  (const void **)&defaultZone) == TRUE)) {
+                       /*
+                        * set the default zone for this interface
+                        */
+                       CFDictionarySetValue(ifDefaults,
+                                            kSCPropNetAppleTalkDefaultZone,
+                                            defaultZone);
+               }
+
+               CFDictionarySetValue(newDefaults, ifName, ifDefaults);
+               CFRelease(ifDefaults);
+
+               switch (CFArrayGetCount(newConfigFile)) {
+                       case 1:
+                               /*
+                                * first AppleTalk interface
+                                */
+                               CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), ifName);
+                               break;
+                       case 2:
+                               /* second AppleTalk interface */
+                               if (!CFEqual(CFDictionaryGetValue(newStartup, CFSTR("APPLETALK")),
+                                            CFSTR("-ROUTER-"))) {
+                                       /*
+                                        * if not routing (yet), configure as multi-home
+                                        */
+                                       CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-MULTIHOME-"));
+                               }
+                               break;
+               }
+
+               if (CFEqual(configMethod, kSCValNetAppleTalkConfigMethodRouter) ||
+                   CFEqual(configMethod, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+                       /* if not a simple node, enable routing */
+                       CFDictionarySetValue(newStartup, CFSTR("APPLETALK"), CFSTR("-ROUTER-"));
+               }
+
+               /*
+                * establish the State:/Network/Service/nnn/AppleTalk key info
+                */
+               key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                                 kSCDynamicStoreDomainState,
+                                                                 CFDictionaryGetValue(service, CFSTR("ServiceID")),
+                                                                 kSCEntNetAppleTalk);
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+               CFDictionaryAddValue(newDict, kSCPropInterfaceName, ifName);
+               cache_SCDynamicStoreSetValue(store, key, newDict);
+               CFRelease(newDict);
+               if (info) {
+                       j = CFArrayGetFirstIndexOfValue(info,
+                                                       CFRangeMake(0, CFArrayGetCount(info)),
+                                                       key);
+                       if (j != kCFNotFound) {
+                               CFArrayRemoveValueAtIndex(info, j);
+                       }
+               }
+               CFRelease(key);
+
+           nextIF :
+
+               if (portConfig) CFRelease(portConfig);
+       }
+
+       if (primaryZone) {
+               CFArrayRef              ifList;
+               CFMutableArrayRef       newIFList;
+
+               ifList = CFDictionaryGetValue(newZones, primaryZone);
+               if (CFArrayContainsValue(ifList,
+                                        CFRangeMake(0, CFArrayGetCount(ifList)),
+                                        primaryPort)) {
+                       newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+                       CFArrayAppendValue(newIFList, CFSTR("*"));
+                       CFDictionarySetValue(newZones, primaryZone, newIFList);
+                       CFRelease(newIFList);
+               }
+               CFRelease(primaryZone);
+       }
+       if (primaryPort) {
+               CFRelease(primaryPort);
+       }
+
+       /* sort the ports */
+       i = CFArrayGetCount(newConfigFile);
+       CFArraySortValues(newConfigFile,
+                         CFRangeMake(0, i),
+                         (CFComparatorFunction)CFStringCompare,
+                         NULL);
+
+       /* add the zones to the configuration */
+       CFDictionaryApplyFunction(newZones, addZoneToPorts, newConfigFile);
+       CFRelease(newZones);
+
+       /* sort the zones */
+       CFArraySortValues(newConfigFile,
+                         CFRangeMake(i, CFArrayGetCount(newConfigFile)-i),
+                         (CFComparatorFunction)CFStringCompare,
+                         NULL);
+
+       /* ensure that the last line of the configuration file is terminated */
+       CFArrayAppendValue(newConfigFile, CFSTR(""));
+
+       /*
+        * Check if we have a "ComputerName" and look elsewhere if we don't have
+        * one yet.
+        */
+       if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME")) &&
+           (setGlobals != NULL)) {
+               computerName = CFDictionaryGetValue(setGlobals,
+                                                   kSCPropNetAppleTalkComputerName);
+               if (CFDictionaryGetValueIfPresent(setGlobals,
+                                                 kSCPropNetAppleTalkComputerNameEncoding,
+                                                 (const void **)&num) &&
+                   isA_CFNumber(num)) {
+                       CFNumberGetValue(num, kCFNumberIntType, &computerNameEncoding);
+               } else {
+                       computerNameEncoding = CFStringGetSystemEncoding();
+               }
+               encodeName(computerName, computerNameEncoding, newStartup, newGlobals);
+       }
+       if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME"))) {
+               computerName = SCDynamicStoreCopyComputerName(store, &computerNameEncoding);
+               if (computerName) {
+                       encodeName(computerName, computerNameEncoding, newStartup, newGlobals);
+                       CFRelease(computerName);
+               }
+       }
+       if (!CFDictionaryContainsKey(newStartup, CFSTR("APPLETALK_HOSTNAME"))) {
+               struct utsname  name;
+
+               if (uname(&name) == 0) {
+                       computerName = CFStringCreateWithCString(NULL, name.nodename, kCFStringEncodingASCII);
+                       if (computerName) {
+                               encodeName(computerName, kCFStringEncodingASCII, NULL, newGlobals);
+                               CFRelease(computerName);
+                       }
+               }
+       }
+
+       /* compare the previous and current configurations */
+
+       curGlobalsX = CFDictionaryCreateMutableCopy(NULL, 0, curGlobals);
+       CFDictionaryRemoveValue(curGlobalsX, kSCDynamicStorePropNetPrimaryService);
+
+       newGlobalsX = CFDictionaryCreateMutableCopy(NULL, 0, newGlobals);
+       CFDictionaryRemoveValue(newGlobalsX, kSCDynamicStorePropNetPrimaryService);
+
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetAppleTalk);
+
+       if (CFEqual(curGlobalsX   , newGlobalsX   ) &&
+           CFEqual(curConfigFile , newConfigFile) &&
+           CFEqual(curDefaults   , newDefaults  ) &&
+           CFEqual(curStartup    , newStartup   )
+           ) {
+               /*
+                * the configuration has not changed.
+                */
+
+               if (postGlobals) {
+                       /*
+                        * the requested configuration hasn't changed but we
+                        * now need to tell everyone that AppleTalk is active.
+                        */
+                       if (!SCDynamicStoreSetValue(store, key, newGlobals)) {
+                               SCLog(TRUE,
+                                     LOG_ERR,
+                                     CFSTR("SCDynamicStoreSetValue() failed: %s"),
+                                     SCErrorString(SCError()));
+                       }
+               }
+
+               CFRelease(newGlobals);
+               CFRelease(newConfigFile);
+               CFRelease(newDefaults);
+               CFRelease(newStartup);
+       } else if (CFArrayGetCount(newConfigFile) <= 1) {
+               /*
+                * the configuration has changed but there are no
+                * longer any interfaces configured for AppleTalk
+                * networking.
+                */
+
+               /*
+                * remove the global (State:/Network/Global/AppleTalk) key.
+                *
+                * Note: it will be restored later after AT networking has
+                *       been activated.
+                */
+
+               /* remove the (/etc/appletalk.cfg) configuration file */
+               (void)unlink(AT_CFG_FILE);
+
+               /*
+                * update the per-service (and global) state
+                */
+               cache_SCDynamicStoreRemoveValue(store, key);    // remove State:/Network/Global/AppleTalk
+               n = CFArrayGetCount(info);
+               for (i = 0; i < n; i++) {
+                       CFStringRef     xKey    = CFArrayGetValueAtIndex(info, i);
+
+                       cache_SCDynamicStoreRemoveValue(store, xKey);
+               }
+               cache_write(store);
+
+               /* flag this as a new configuration */
+               *newState = -(abs(curState) + 1);
+               changed = TRUE;
+       } else {
+               /*
+                * the configuration has changed.
+                */
+
+               /* update the (/etc/appletalk.cfg) configuration file */
+               configWrite(AT_CFG_FILE, newConfigFile);
+
+               /*
+                * update the per-service (and global) state
+                *
+                * Note: if present, we remove any existing global state key and allow it
+                *       to be restored after the stack has been re-started.
+                */
+               CFDictionaryApplyFunction(newDefaults, updateDefaults, NULL);
+               cache_SCDynamicStoreRemoveValue(store, key);    // remove State:/Network/Global/AppleTalk
+               n = CFArrayGetCount(info);
+               for (i = 0; i < n; i++) {
+                       CFStringRef     xKey    = CFArrayGetValueAtIndex(info, i);
+
+                       cache_SCDynamicStoreRemoveValue(store, xKey);
+               }
+               cache_write(store);
+
+               /* flag this as a new configuration */
+               *newState = abs(curState) + 1;
+               changed = TRUE;
+       }
+
+       CFRelease(curGlobalsX);
+       CFRelease(newGlobalsX);
+       CFRelease(key);
+
+       if (changed) {
+               CFRelease(curGlobals);
+               curGlobals    = newGlobals;
+               CFRelease(curConfigFile);
+               curConfigFile = newConfigFile;
+               CFRelease(curDefaults);
+               curDefaults   = newDefaults;
+               CFRelease(curStartup);
+               curStartup    = newStartup;
+       }
+
+       if (info)               CFRelease(info);
+       if (interfaces)         CFRelease(interfaces);
+       if (configuredServices) CFRelease(configuredServices);
+       if (setGlobals)         CFRelease(setGlobals);
+
+       cache_close();
+
+       return changed;
+}
+
+
+#include <sysexits.h>
+#define AT_CMD_SUCCESS         EX_OK   /* success */
+#define AT_CMD_ALREADY_RUNNING EX__MAX + 10
+#define AT_CMD_NOT_RUNNING     EX__MAX + 11
+
+
+static int
+stackState()
+{
+       int             ret;
+       int             sock;
+       at_state_t      state;
+
+       sock = socket(AF_APPLETALK, SOCK_RAW, 0);
+       ret  = ioctl(sock, AIOCGETSTATE, (caddr_t)&state);
+       (void)close(sock);
+       if (ret == -1) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("ioctl(AIOCGETSTATE) failed: %s"), strerror(errno));
+               return FALSE;
+       }
+
+       if (state.flags & AT_ST_STARTED) {
+               return abs(curState);
+       } else {
+               return -(abs(curState));
+       }
+}
+
+
+static pid_t   execCommand     = 0;
+static int     execRetry;
+
+
+static void
+stopComplete(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+       execCommand = 0;
+
+       if (WIFEXITED(status)) {
+               switch (WEXITSTATUS(status)) {
+                       case AT_CMD_SUCCESS :
+                       case AT_CMD_NOT_RUNNING :
+                               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown complete"));
+                               if (curState > 0) {
+                                       // the stack is down but we really want it up
+                                       startAppleTalk(NULL, (void *)curState);
+                               }
+                               return;
+                       default :
+                               break;
+               }
+       }
+
+       SCLog(TRUE, LOG_ERR,
+             CFSTR("AppleTalk shutdown failed, status = %d%s"),
+             WEXITSTATUS(status),
+             (execRetry > 1) ? " (retrying)" : "");
+
+       // shutdown failed, retry
+       if (--execRetry > 0) {
+               CFRunLoopTimerContext   timerContext    = { 0, (void *)curState, NULL, NULL, NULL };
+               CFRunLoopTimerRef       timer;
+
+               timer = CFRunLoopTimerCreate(NULL,
+                                            CFAbsoluteTimeGetCurrent() + 1.0,
+                                            0.0,
+                                            0,
+                                            0,
+                                            stopAppleTalk,
+                                            &timerContext);
+               CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
+               CFRelease(timer);
+               return;
+       } else {
+               // we weren't able to stop
+               curState = stackState();
+       }
+
+       return;
+}
+
+
+static void
+stopAppleTalk(CFRunLoopTimerRef timer, void *info)
+{
+       char    *argv[] = { "appletalk",
+                           "-d",
+                           NULL };
+
+       if (execCommand == 0) {
+               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown"));
+       } else {
+               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk shutdown skipped, transition in progress"));
+               return;
+       }
+
+       execCommand = _SCDPluginExecCommand(stopComplete,               // callback
+                                           info,                       // context
+                                           0,                          // uid
+                                           0,                          // gid
+                                           "/usr/sbin/appletalk",      // path
+                                           argv);                      // argv
+
+       if (!timer) {
+               execRetry = 5;  // initialize retry count
+       }
+
+       return;
+}
+
+
+static void
+startComplete(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+       execCommand = 0;
+
+       if (WIFEXITED(status)) {
+               switch (WEXITSTATUS(status)) {
+                       case AT_CMD_SUCCESS :
+                               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup complete"));
+                               if ((curState < 0) || (curState > (int)context)) {
+                                       // the stack is now up but we really want it down
+                                       stopAppleTalk(NULL, (void *)curState);
+                               }
+                               return;
+                       case AT_CMD_ALREADY_RUNNING :
+                               // the stack is already up but we're not sure
+                               // if the configuration is correct, restart
+                               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk already running, restarting"));
+                               stopAppleTalk(NULL, (void *)curState);
+                               return;
+                       default :
+                               break;
+               }
+       }
+
+       SCLog(TRUE, LOG_ERR,
+             CFSTR("AppleTalk startup failed, status = %d%s"),
+             WEXITSTATUS(status),
+             (execRetry > 1) ? " (retrying)" : "");
+
+       // startup failed, retry
+       if (--execRetry > 0) {
+               CFRunLoopTimerContext   timerContext    = { 0, (void *)curState, NULL, NULL, NULL };
+               CFRunLoopTimerRef       timer;
+
+               timer = CFRunLoopTimerCreate(NULL,
+                                            CFAbsoluteTimeGetCurrent() + 1.0,
+                                            0.0,
+                                            0,
+                                            0,
+                                            startAppleTalk,
+                                            &timerContext);
+               CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
+               CFRelease(timer);
+               return;
+       } else {
+               // we weren't able to start
+               curState = stackState();
+       }
+
+       return;
+}
+
+
+static void
+startAppleTalk(CFRunLoopTimerRef timer, void *info)
+{
+       int             argc            = 0;
+       char            *argv[8];
+       char            *computerName   = NULL;
+       char            *interface      = NULL;
+       CFStringRef     mode            = CFDictionaryGetValue(curStartup, CFSTR("APPLETALK"));
+       CFStringRef     name            = CFDictionaryGetValue(curStartup, CFSTR("APPLETALK_HOSTNAME"));
+
+       if (execCommand == 0) {
+               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup"));
+       } else {
+               SCLog(TRUE, LOG_NOTICE, CFSTR("AppleTalk startup skipped, transition in progress"));
+               return;
+       }
+
+       if (!mode) {
+               // Huh?
+               return;
+       }
+
+       // set command name
+       argv[argc++] = "appletalk";
+
+       // set hostname
+       if (name) {
+               computerName = _SC_cfstring_to_cstring(name, NULL, 0, kCFStringEncodingASCII);
+               if (computerName) {
+                       argv[argc++] = "-C";
+                       argv[argc++] = computerName;
+               } else {
+                       // could not convert name
+                       goto done;
+               }
+       }
+
+       // set mode
+       if (CFEqual(mode, CFSTR("-ROUTER-"))) {
+               argv[argc++] = "-r";
+       } else if (CFEqual(mode, CFSTR("-MULTIHOME-"))) {
+               argv[argc++] = "-x";
+       } else {
+               interface = _SC_cfstring_to_cstring(mode, NULL, 0, kCFStringEncodingASCII);
+               if (interface) {
+                       argv[argc++] = "-u";
+                       argv[argc++] = interface;
+               } else {
+                       // could not convert interface
+                       goto done;
+               }
+       }
+
+       // set non-interactive
+       argv[argc++] = "-q";
+
+       // close argument list
+       argv[argc++] = NULL;
+
+       execCommand = _SCDPluginExecCommand(startComplete,              // callback
+                                           info,                       // context
+                                           0,                          // uid
+                                           0,                          // gid
+                                           "/usr/sbin/appletalk",      // path
+                                           argv);                      // argv
+
+       if (!timer) {
+               execRetry = 5;  // initialize retry count
+       }
+
+    done :
+
+       if (computerName)       CFAllocatorDeallocate(NULL, computerName);
+       if (interface)          CFAllocatorDeallocate(NULL, interface);
+
+       return;
+}
+
+
+static void
+atConfigChangedCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg)
+{
+       boolean_t       configChanged;
+       int             newState;
+
+       configChanged = updateConfiguration(&newState);
+
+       if (configChanged && (execCommand == 0)) {
+               // if the configuration has changed and we're not already transitioning
+               if (newState > 0) {
+                       if (curState > 0) {
+                               // already running, restart [with new configuration]
+                               stopAppleTalk(NULL, (void *)newState);
+                       } else {
+                               startAppleTalk(NULL, (void *)newState);
+                       }
+               } else {
+                       if (curState > 0) {
+                               stopAppleTalk(NULL, (void *)newState);
+                       }
+               }
+       }
+
+       curState = newState;
+
+       return;
+}
+
+
+void
+stop_ATconfig(CFRunLoopSourceRef stopRls)
+{
+       // cleanup
+
+       if (storeRls != NULL) {
+               CFRunLoopSourceInvalidate(storeRls);
+               CFRelease(storeRls);
+               storeRls = NULL;
+       }
+
+       if (store != NULL) {
+               CFRelease(store);
+               store = NULL;
+               CFRelease(curGlobals);
+               CFRelease(curConfigFile);
+               CFRelease(curDefaults);
+               CFRelease(curStartup);
+       }
+
+       CFRunLoopSourceSignal(stopRls);
+       return;
+}
+
+
+void
+load_ATconfig(CFBundleRef bundle, Boolean bundleVerbose)
+{
+       CFStringRef             key;
+       CFMutableArrayRef       keys            = NULL;
+       CFStringRef             pattern;
+       CFMutableArrayRef       patterns        = NULL;
+
+       if (bundleVerbose) {
+               _verbose = TRUE;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+       SCLog(_verbose, LOG_DEBUG, CFSTR("  bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+       /* initialize a few globals */
+
+       curGlobals    = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+       curConfigFile = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       curDefaults   = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+       curStartup    = CFDictionaryCreateMutable(NULL,
+                                                 0,
+                                                 &kCFTypeDictionaryKeyCallBacks,
+                                                 &kCFTypeDictionaryValueCallBacks);
+
+       /* open a "configd" store to allow cache updates */
+       store = SCDynamicStoreCreate(NULL,
+                                    CFSTR("AppleTalk Configuraton plug-in"),
+                                    atConfigChangedCallback,
+                                    NULL);
+       if (!store) {
+               SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreCreate() failed: %s"), SCErrorString(SCError()));
+               goto error;
+       }
+
+       /* establish notification keys and patterns */
+
+       keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       /* ...watch for (global) AppleTalk configuration changes */
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainSetup,
+                                                        kSCEntNetAppleTalk);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       /* ...watch for (per-service) AppleTalk configuration changes */
+       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                             kSCDynamicStoreDomainSetup,
+                                                             kSCCompAnyRegex,
+                                                             kSCEntNetAppleTalk);
+       CFArrayAppendValue(patterns, pattern);
+       CFRelease(pattern);
+
+       /* ...watch for network interface link status changes */
+       pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                               kSCDynamicStoreDomainState,
+                                                               kSCCompAnyRegex,
+                                                               kSCEntNetLink);
+       CFArrayAppendValue(patterns, pattern);
+       CFRelease(pattern);
+
+       /* ...watch for (per-interface) AppleTalk configuration changes */
+       pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                               kSCDynamicStoreDomainState,
+                                                               kSCCompAnyRegex,
+                                                               kSCEntNetAppleTalk);
+       CFArrayAppendValue(patterns, pattern);
+       CFRelease(pattern);
+
+       /* ...watch for computer name changes */
+       key = SCDynamicStoreKeyCreateComputerName(NULL);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       /* register the keys/patterns */
+       if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+       CFRelease(keys);
+       CFRelease(patterns);
+
+       storeRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+       if (!storeRls) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRls, kCFRunLoopDefaultMode);
+
+       return;
+
+    error :
+
+       if (curGlobals)         CFRelease(curGlobals);
+       if (curConfigFile)      CFRelease(curConfigFile);
+       if (curDefaults)        CFRelease(curDefaults);
+       if (curStartup)         CFRelease(curStartup);
+       if (store)              CFRelease(store);
+       if (keys)               CFRelease(keys);
+       if (patterns)           CFRelease(patterns);
+       return;
+}
+
+
+#ifdef MAIN
+#include "cfManager.c"
+int
+main(int argc, char **argv)
+{
+       _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+       load_ATconfig(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+       CFRunLoopRun();
+       /* not reached */
+       exit(0);
+       return 0;
+}
+#endif
diff --git a/Plugins/ATconfig/cfManager.c b/Plugins/ATconfig/cfManager.c
new file mode 100644 (file)
index 0000000..73bcd59
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "cfManager.h"
+
+
+#ifdef NOTNOW
+/*
+ * Opens a configuration file and returns a CFArrayRef consisting
+ * of a CFStringRef for each line.
+ */
+__private_extern__
+CFArrayRef
+configRead(const char *path)
+{
+       int                     fd;
+       struct stat             statBuf;
+       CFMutableDataRef        data;
+       CFStringRef             str;
+       CFArrayRef              config  = NULL;
+
+       fd = open(path, O_RDONLY, 0644);
+       if (fd < 0) {
+               goto done;
+       }
+       if (fstat(fd, &statBuf) < 0) {
+               goto done;
+       }
+       if ((statBuf.st_mode & S_IFMT) != S_IFREG) {
+               goto done;
+       }
+
+       data = CFDataCreateMutable(NULL, statBuf.st_size);
+       CFDataSetLength(data, statBuf.st_size);
+       if(read(fd, (void *)CFDataGetMutableBytePtr(data), statBuf.st_size) != statBuf.st_size) {
+               CFRelease(data);
+               goto done;
+       }
+
+       str = CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingMacRoman);
+       CFRelease(data);
+
+       config = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR("\n"));
+       CFRelease(str);
+
+    done:
+
+       if (fd >= 0) {
+               close(fd);
+       }
+       if (config == NULL) {
+               CFMutableArrayRef       emptyConfig;
+
+               /* pretend that we found an empty file */
+               emptyConfig = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+               CFArrayAppendValue(emptyConfig, CFSTR(""));
+               config = (CFArrayRef)emptyConfig;
+       }
+       return config;
+}
+#endif /* NOTNOW */
+
+/*
+ * Writes a new configuration file with the contents of a CFArrayRef. Each
+ * element of the array is a CFStringRef.
+ */
+__private_extern__
+void
+configWrite(const char *path, CFArrayRef config)
+{
+       CFStringRef     str;
+       CFDataRef       data;
+       int             fd = -1;
+       int             len;
+
+       str  = CFStringCreateByCombiningStrings(NULL, config, CFSTR("\n"));
+       data = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingMacRoman, '.');
+       CFRelease(str);
+
+       fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+       if (fd < 0) {
+               goto done;
+       }
+
+       len = CFDataGetLength(data);
+       if (len) {
+               (void)write(fd, CFDataGetBytePtr(data), len);
+       }
+
+    done:
+
+       if (fd >= 0)
+               close(fd);
+       CFRelease(data);
+       return;
+}
+
+
+#ifdef NOTNOW
+__private_extern__
+void
+configSet(CFMutableArrayRef config, CFStringRef key, CFStringRef value)
+{
+       CFMutableStringRef      pref;
+       CFIndex                 configLen       = CFArrayGetCount(config);
+       CFIndex                 i;
+       CFIndex                 n;
+       CFMutableStringRef      newValue;
+       CFRange                 range;
+       CFStringRef             specialChars    = CFSTR(" \"'$!|\\<>`{}[]");
+       boolean_t               mustQuote       = FALSE;
+
+       /* create search prefix */
+       pref = CFStringCreateMutableCopy(NULL, 0, key);
+       CFStringAppend(pref, CFSTR("="));
+
+       /*
+        * create new / replacement value
+        *
+        * Note: Since the configuration file may be processed by a
+        *       shell script we need to ensure that, if needed, the
+        *       string is properly quoted.
+        */
+       newValue = CFStringCreateMutableCopy(NULL, 0, value);
+
+       n = CFStringGetLength(specialChars);
+       for (i = 0; i < n; i++) {
+               CFStringRef     specialChar;
+
+               specialChar = CFStringCreateWithSubstring(NULL, specialChars, CFRangeMake(i, 1));
+               range = CFStringFind(newValue, specialChar, 0);
+               CFRelease(specialChar);
+               if (range.location != kCFNotFound) {
+                       /* this string has at least one special character */
+                       mustQuote = TRUE;
+                       break;
+               }
+       }
+
+       if (mustQuote) {
+               CFStringRef     charsToQuote    = CFSTR("\\\"$`");
+
+               /*
+                * in addition to quoting the entire string we also need to escape the
+                * space " " and backslash "\" characters
+                */
+               n = CFStringGetLength(charsToQuote);
+               for (i = 0; i < n; i++) {
+                       CFStringRef     quoteChar;
+                       CFArrayRef      matches;
+
+                       quoteChar = CFStringCreateWithSubstring(NULL, charsToQuote, CFRangeMake(i, 1));
+                       range     = CFRangeMake(0, CFStringGetLength(newValue));
+                       matches   = CFStringCreateArrayWithFindResults(NULL,
+                                                                      newValue,
+                                                                      quoteChar,
+                                                                      range,
+                                                                      0);
+                       CFRelease(quoteChar);
+
+                       if (matches) {
+                               CFIndex j = CFArrayGetCount(matches);
+
+                               while (--j >= 0) {
+                                       const CFRange   *range;
+
+                                       range = CFArrayGetValueAtIndex(matches, j);
+                                       CFStringInsert(newValue, range->location, CFSTR("\\"));
+                               }
+                               CFRelease(matches);
+                       }
+               }
+
+               CFStringInsert(newValue, 0, CFSTR("\""));
+               CFStringAppend(newValue, CFSTR("\""));
+       }
+
+       /* locate existing key */
+       for (i = 0; i < configLen; i++) {
+               if (CFStringHasPrefix(CFArrayGetValueAtIndex(config, i), pref)) {
+                       break;
+               }
+       }
+
+       CFStringAppend(pref, newValue);
+       CFRelease(newValue);
+       if (i < configLen) {
+               /* if replacing an existing entry */
+               CFArraySetValueAtIndex(config, i, pref);
+       } else {
+               /*
+                * if new entry, insert it just prior to the last (emtpy)
+                * array element.
+                */
+               CFArrayInsertValueAtIndex(config, configLen-1, pref);
+       }
+       CFRelease(pref);
+
+       return;
+}
+
+
+__private_extern__
+void
+configRemove(CFMutableArrayRef config, CFStringRef key)
+{
+       CFMutableStringRef      pref;
+       CFIndex                 configLen = CFArrayGetCount(config);
+       CFIndex                 i;
+
+       /* create search prefix */
+       pref = CFStringCreateMutableCopy(NULL, 0, key);
+       CFStringAppend(pref, CFSTR("="));
+
+       /* locate existing key */
+       for (i = 0; i < configLen; i++) {
+               if (CFStringHasPrefix(CFArrayGetValueAtIndex(config, i), pref)) {
+                       /* entry found, remove it */
+                       CFArrayRemoveValueAtIndex(config, i);
+                       break;
+               }
+       }
+
+       CFRelease(pref);
+       return;
+}
+#endif /* NOTNOW */
diff --git a/Plugins/ATconfig/cfManager.h b/Plugins/ATconfig/cfManager.h
new file mode 100644 (file)
index 0000000..373c371
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef __CFMANAGER_H
+#define __CFMANAGER_H
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <sys/cdefs.h>
+
+
+__BEGIN_DECLS
+
+#ifdef NOTNOW
+CFArrayRef     configRead      __P((const char *path));
+#endif /* NOTNOW */
+void           configWrite     __P((const char *path, CFArrayRef config));
+#ifdef NOTNOW
+void           configSet       __P((CFMutableArrayRef config, CFStringRef key, CFStringRef value));
+void           configRemove    __P((CFMutableArrayRef config, CFStringRef key));
+#endif /* NOTNOW */
+
+__END_DECLS
+
+
+#endif /* __CFMANAGER_H */
diff --git a/Plugins/IPMonitor/Info.plist b/Plugins/IPMonitor/Info.plist
new file mode 100644 (file)
index 0000000..bb883e4
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>IPMonitor</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.IPMonitor</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Requires</key>
+       <array>
+               <string>com.apple.SystemConfiguration.IPConfiguration</string>
+               <string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+       </array>
+       <key>Builtin</key>
+       <true/>
+</dict>
+</plist>
diff --git a/Plugins/IPMonitor/Resolvers.plist b/Plugins/IPMonitor/Resolvers.plist
new file mode 100644 (file)
index 0000000..c59cf4d
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+       <dict>
+               <key>Options</key>
+               <string>attempts:4</string>
+               <key>ServerAddresses</key>
+               <array>
+                       <string>224.0.0.251</string>
+                       <string>ff02::fb</string>
+               </array>
+               <key>ServerPort</key>
+               <integer>5353</integer>
+               <key>ServerTimeout</key>
+               <integer>2</integer>
+               <key>SupplementalMatchDomains</key>
+               <array>
+                       <string>local</string>
+                       <string>254.169.in-addr.arpa</string>
+                       <string>0.8.e.f.ip6.arpa</string>
+               </array>
+       </dict>
+</array>
+</plist>
diff --git a/Plugins/IPMonitor/dns-configuration.c b/Plugins/IPMonitor/dns-configuration.c
new file mode 100644 (file)
index 0000000..bcbae5a
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+#include <dnsinfo.h>
+#include <dnsinfo_create.h>
+
+
+/* pre-defined (supplemental) resolver configurations */
+static  CFArrayRef      S_predefined  = NULL;
+
+
+static void
+add_supplemental(CFMutableArrayRef supplemental, CFDictionaryRef dns, uint32_t defaultOrder)
+{
+       CFArrayRef      domains;
+       CFIndex         i;
+       CFIndex         n_domains;
+       CFArrayRef      orders;
+
+
+       domains = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchDomains);
+       n_domains = isA_CFArray(domains) ? CFArrayGetCount(domains) : 0;
+       if (n_domains == 0) {
+               return;
+       }
+
+       orders = CFDictionaryGetValue(dns, kSCPropNetDNSSupplementalMatchOrders);
+       if (orders != NULL) {
+               if (!isA_CFArray(orders) || (n_domains != CFArrayGetCount(orders))) {
+                       return;
+               }
+       }
+
+       /*
+        * yes, this is a "supplemental" resolver configuration, expand
+        * the match domains and add each to the supplemental list.
+        */
+       for (i = 0; i < n_domains; i++) {
+               CFIndex                 j;
+               CFStringRef             match_domain;
+               CFNumberRef             match_order;
+               uint32_t                match_order_val = 0;
+               CFMutableDictionaryRef  match_resolver;
+               CFIndex                 n_supplemental;
+
+               match_domain = CFArrayGetValueAtIndex(domains, i);
+               if (!isA_CFString(match_domain)) {
+                       continue;
+               }
+
+               match_order = (orders != NULL) ? CFArrayGetValueAtIndex(orders, i) : NULL;
+
+               match_resolver = CFDictionaryCreateMutableCopy(NULL, 0, dns);
+               CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSupplementalMatchDomains);
+               CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSupplementalMatchOrders);
+               CFDictionaryRemoveValue(match_resolver, kSCPropNetDNSSearchDomains);
+               CFDictionarySetValue(match_resolver, kSCPropNetDNSDomainName, match_domain);
+               if (isA_CFNumber(match_order)) {
+                       CFDictionarySetValue(match_resolver, kSCPropNetDNSSearchOrder, match_order);
+               } else if (!CFDictionaryContainsKey(match_resolver, kSCPropNetDNSSearchOrder)) {
+                       CFNumberRef     num;
+
+                       num = CFNumberCreate(NULL, kCFNumberIntType, &defaultOrder);
+                       CFDictionarySetValue(match_resolver, kSCPropNetDNSSearchOrder, num);
+                       CFRelease(num);
+               }
+
+               match_order = CFDictionaryGetValue(match_resolver, kSCPropNetDNSSearchOrder);
+               if (!isA_CFNumber(match_order) ||
+                   !CFNumberGetValue(match_order, kCFNumberIntType, &match_order_val)) {
+                       match_order     = NULL;
+                       match_order_val = 0;
+               }
+
+               n_supplemental = CFArrayGetCount(supplemental);
+               for (j = 0; j < n_supplemental; j++) {
+                       CFMutableDictionaryRef  compare;
+                       Boolean                 match;
+                       CFDictionaryRef         supplemental_resolver;
+
+                       supplemental_resolver = CFArrayGetValueAtIndex(supplemental, j);
+                       if (CFEqual(match_resolver, supplemental_resolver)) {
+                               // a real duplicate
+                               CFRelease(match_resolver);
+                               match_resolver = NULL;
+                               break;
+                       }
+
+                       compare = CFDictionaryCreateMutableCopy(NULL, 0, supplemental_resolver);
+                       if (match_order != NULL) {
+                               CFDictionarySetValue(compare, kSCPropNetDNSSearchOrder, match_order);
+                       }
+                       match = CFEqual(match_resolver, compare);
+                       CFRelease(compare);
+
+                       if (match) {
+                               CFNumberRef     supplemental_order;
+                               uint32_t        supplemental_order_val  = 0;
+
+                               // if only the search order's are different
+                               supplemental_order = CFDictionaryGetValue(supplemental_resolver, kSCPropNetDNSSearchOrder);
+                               if (!isA_CFNumber(supplemental_order) ||
+                                   !CFNumberGetValue(supplemental_order, kCFNumberIntType, &supplemental_order_val)) {
+                                       supplemental_order_val = 0;
+                               }
+
+                               if (match_order_val < supplemental_order_val ) {
+                                       // if we should prefer this match resolver, else just skip it
+                                       CFArraySetValueAtIndex(supplemental, j, match_resolver);
+                               }
+
+                               CFRelease(match_resolver);
+                               match_resolver = NULL;
+                               break;
+                       }
+               }
+
+               if (match_resolver != NULL) {
+                       CFArrayAppendValue(supplemental, match_resolver);
+                       CFRelease(match_resolver);
+               }
+       }
+
+       return;
+}
+
+
+static void
+add_predefined_resolvers(CFMutableArrayRef supplemental)
+{
+       CFIndex i;
+       CFIndex n;
+
+       if (S_predefined == NULL) {
+               return;
+       }
+
+       n = CFArrayGetCount(S_predefined);
+       for (i = 0; i < n; i++) {
+               uint32_t        defaultOrder;
+               CFDictionaryRef dns;
+
+               dns = CFArrayGetValueAtIndex(S_predefined, i);
+               if (!isA_CFDictionary(dns)) {
+                       continue;
+               }
+
+               defaultOrder = DEFAULT_SEARCH_ORDER +
+                              (DEFAULT_SEARCH_ORDER / 2) +
+                              ((DEFAULT_SEARCH_ORDER / 1000) * i);
+               add_supplemental(supplemental, dns, defaultOrder);
+       }
+
+       return;
+}
+
+
+#define        N_QUICK 32
+
+
+static void
+add_supplemental_resolvers(CFMutableArrayRef supplemental, CFDictionaryRef services, CFArrayRef service_order)
+{
+       const void *            keys_q[N_QUICK];
+       const void **           keys    = keys_q;
+       CFIndex                 i;
+       CFIndex                 n_order;
+       CFIndex                 n_services;
+       const void *            vals_q[N_QUICK];
+       const void **           vals    = vals_q;
+
+       n_services = isA_CFDictionary(services) ? CFDictionaryGetCount(services) : 0;
+       if (n_services == 0) {
+               return;         // if no services
+       }
+
+       if (n_services > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+               keys = CFAllocatorAllocate(NULL, n_services * sizeof(CFTypeRef), 0);
+               vals = CFAllocatorAllocate(NULL, n_services * sizeof(CFTypeRef), 0);
+       }
+
+       n_order = isA_CFArray(service_order) ? CFArrayGetCount(service_order) : 0;
+
+       CFDictionaryGetKeysAndValues(services, keys, vals);
+       for (i = 0; i < n_services; i++) {
+               uint32_t        defaultOrder;
+               CFDictionaryRef dns;
+               CFDictionaryRef service = (CFDictionaryRef)vals[i];
+
+               if (!isA_CFDictionary(service)) {
+                       continue;
+               }
+
+               dns = CFDictionaryGetValue(service, kSCEntNetDNS);
+               if (!isA_CFDictionary(dns)) {
+                       continue;
+               }
+
+               defaultOrder = DEFAULT_SEARCH_ORDER -
+                              (DEFAULT_SEARCH_ORDER / 2) +
+                              ((DEFAULT_SEARCH_ORDER / 1000) * i);
+               if ((n_order > 0) &&
+                   !CFArrayContainsValue(service_order, CFRangeMake(0, n_order), keys[i])) {
+                       // push out services not specified in service order
+                       defaultOrder += (DEFAULT_SEARCH_ORDER / 1000) * n_services;
+               }
+
+               add_supplemental(supplemental, dns, defaultOrder);
+       }
+
+       if (keys != keys_q) {
+               CFAllocatorDeallocate(NULL, keys);
+               CFAllocatorDeallocate(NULL, vals);
+       }
+
+       return;
+}
+
+
+static CFComparisonResult
+compareBySearchOrder(const void *val1, const void *val2, void *context)
+{
+       CFDictionaryRef dns1    = (CFDictionaryRef)val1;
+       CFDictionaryRef dns2    = (CFDictionaryRef)val2;
+       CFNumberRef     num;
+       uint32_t        order1  = DEFAULT_SEARCH_ORDER;
+       uint32_t        order2  = DEFAULT_SEARCH_ORDER;
+
+       num = CFDictionaryGetValue(dns1, kSCPropNetDNSSearchOrder);
+       if (!isA_CFNumber(num) ||
+           !CFNumberGetValue(num, kCFNumberIntType, &order1)) {
+               order1 = DEFAULT_SEARCH_ORDER;
+       }
+
+       num = CFDictionaryGetValue(dns2, kSCPropNetDNSSearchOrder);
+       if (!isA_CFNumber(num) ||
+           !CFNumberGetValue(num, kCFNumberIntType, &order2)) {
+               order2 = DEFAULT_SEARCH_ORDER;
+       }
+
+       if (order1 == order2) {
+               return kCFCompareEqualTo;
+       }
+
+       return (order1 < order2) ? kCFCompareLessThan : kCFCompareGreaterThan;
+}
+
+
+static void
+update_search_domains(CFMutableDictionaryRef *defaultDomain, CFArrayRef supplemental)
+{
+       CFStringRef             defaultDomainName       = NULL;
+       uint32_t                defaultOrder            = DEFAULT_SEARCH_ORDER;
+       CFArrayRef              defaultSearchDomains    = NULL;
+       CFIndex                 defaultSearchIndex      = 0;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFMutableArrayRef       mySearchDomains;
+       CFMutableArrayRef       mySupplemental          = (CFMutableArrayRef)supplemental;
+       Boolean                 searchDomainAdded       = FALSE;
+
+       n = CFArrayGetCount(supplemental);
+       if (n == 0) {
+               // if no supplemental domains
+               return;
+       }
+
+       if (*defaultDomain != NULL) {
+               CFNumberRef     num;
+
+               num = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSSearchOrder);
+               if (!isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberIntType, &defaultOrder)) {
+                       defaultOrder = DEFAULT_SEARCH_ORDER;
+               }
+
+               defaultDomainName    = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSDomainName);
+               defaultSearchDomains = CFDictionaryGetValue(*defaultDomain, kSCPropNetDNSSearchDomains);
+       }
+
+       if (isA_CFArray(defaultSearchDomains)) {
+               mySearchDomains = CFArrayCreateMutableCopy(NULL, 0, defaultSearchDomains);
+       } else {
+               mySearchDomains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+               if (isA_CFString(defaultDomainName)) {
+                       char    *domain;
+                       int     domain_parts    = 1;
+                       char    *dp;
+
+                       domain = _SC_cfstring_to_cstring(defaultDomainName,
+                                                        NULL,
+                                                        0,
+                                                        kCFStringEncodingUTF8);
+
+                       for (dp = domain; *dp != '\0'; dp++) {
+                               if (*dp == '.') {
+                                       domain_parts++;
+                               }
+                       }
+
+                       dp = domain;
+                       for (i = LOCALDOMAINPARTS; i <= domain_parts; i++) {
+                               CFStringRef    searchDomain;
+
+                               searchDomain = CFStringCreateWithCString(NULL,
+                                                                        dp,
+                                                                        kCFStringEncodingUTF8);
+                               CFArrayAppendValue(mySearchDomains, searchDomain);
+                               CFRelease(searchDomain);
+
+                               dp = strchr(dp, '.') + 1;
+                       }
+
+                       CFAllocatorDeallocate(NULL, domain);
+               }
+       }
+
+       if (n > 1) {
+               mySupplemental = CFArrayCreateMutableCopy(NULL, 0, supplemental);
+               CFArraySortValues(mySupplemental,
+                                 CFRangeMake(0, n),
+                                 compareBySearchOrder,
+                                 NULL);
+       }
+
+       for (i = 0; i < n; i++) {
+               CFDictionaryRef dns;
+               CFNumberRef     num;
+               CFStringRef     supplementalDomain;
+               uint32_t        supplementalOrder;
+
+               dns = CFArrayGetValueAtIndex(mySupplemental, i);
+
+               supplementalDomain = CFDictionaryGetValue(dns, kSCPropNetDNSDomainName);
+               if (CFArrayContainsValue(mySearchDomains,
+                                        CFRangeMake(0, CFArrayGetCount(mySearchDomains)),
+                                        supplementalDomain)) {
+                       // if supplemental domain is already in the search list
+                       continue;
+               }
+
+               num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
+               if (!isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberIntType, &supplementalOrder)) {
+                       supplementalOrder = DEFAULT_SEARCH_ORDER;
+               }
+
+               if (supplementalOrder < defaultOrder) {
+                       CFArrayInsertValueAtIndex(mySearchDomains,
+                                                 defaultSearchIndex,
+                                                 supplementalDomain);
+                       defaultSearchIndex++;
+               } else {
+                       CFArrayAppendValue(mySearchDomains, supplementalDomain);
+               }
+
+               searchDomainAdded = TRUE;
+       }
+
+       if (searchDomainAdded) {
+               if (*defaultDomain == NULL) {
+                       *defaultDomain = CFDictionaryCreateMutable(NULL,
+                                                                  0,
+                                                                  &kCFTypeDictionaryKeyCallBacks,
+                                                                  &kCFTypeDictionaryValueCallBacks);
+               }
+               CFDictionarySetValue(*defaultDomain, kSCPropNetDNSSearchDomains, mySearchDomains);
+       }
+
+       CFRelease(mySearchDomains);
+       if (mySupplemental != supplemental) CFRelease(mySupplemental);
+       return;
+}
+
+
+static dns_create_resolver_t
+create_resolver(CFDictionaryRef dns)
+{
+       CFArrayRef              list;
+       CFNumberRef             num;
+       dns_create_resolver_t   _resolver;
+       CFStringRef             str;
+
+       _resolver = _dns_resolver_create();
+
+       // process domain
+       str = CFDictionaryGetValue(dns, kSCPropNetDNSDomainName);
+       if (isA_CFString(str)) {
+               char    domain[NS_MAXDNAME];
+
+               if (_SC_cfstring_to_cstring(str, domain, sizeof(domain), kCFStringEncodingUTF8) != NULL) {
+                       _dns_resolver_set_domain(&_resolver, domain);
+               }
+       }
+
+       // process search domains
+       list = CFDictionaryGetValue(dns, kSCPropNetDNSSearchDomains);
+       if (isA_CFArray(list)) {
+               CFIndex i;
+               CFIndex n       = CFArrayGetCount(list);
+
+               // add "search" domains
+               for (i = 0; i < n; i++) {
+                       str = CFArrayGetValueAtIndex(list, i);
+                       if (isA_CFString(str)) {
+                               char    search[NS_MAXDNAME];
+
+                               if (_SC_cfstring_to_cstring(str, search, sizeof(search), kCFStringEncodingUTF8) != NULL) {
+                                       _dns_resolver_add_search(&_resolver, search);
+                               }
+                       }
+               }
+       }
+
+       // process nameserver addresses
+       list = CFDictionaryGetValue(dns, kSCPropNetDNSServerAddresses);
+       if (isA_CFArray(list)) {
+               CFIndex i;
+               CFIndex n       = CFArrayGetCount(list);
+
+               for (i = 0; i < n; i++) {
+                       union {
+                               struct sockaddr         sa;
+                               struct sockaddr_in      sin;
+                               struct sockaddr_in6     sin6;
+                       } addr;
+                       char    buf[128];
+
+                       str = CFArrayGetValueAtIndex(list, i);
+                       if (!isA_CFString(str)) {
+                               continue;
+                       }
+
+                       if (_SC_cfstring_to_cstring(str, buf, sizeof(buf), kCFStringEncodingASCII) == NULL) {
+                               continue;
+                       }
+
+                       bzero(&addr, sizeof(addr));
+                       if (inet_aton(buf, &addr.sin.sin_addr) == 1) {
+                               /* if IPv4 address */
+                               addr.sin.sin_len    = sizeof(addr.sin);
+                               addr.sin.sin_family = AF_INET;
+                               _dns_resolver_add_nameserver(&_resolver, &addr.sa);
+                       } else if (inet_pton(AF_INET6, buf, &addr.sin6.sin6_addr) == 1) {
+                               /* if IPv6 address */
+                               char    *p;
+
+                               p = strchr(buf, '%');
+                               if (p != NULL) {
+                                       addr.sin6.sin6_scope_id = if_nametoindex(p+1);
+                               }
+
+                               addr.sin6.sin6_len    = sizeof(addr.sin6);
+                               addr.sin6.sin6_family = AF_INET6;
+                               _dns_resolver_add_nameserver(&_resolver, &addr.sa);
+                       } else {
+                               continue;
+                       }
+               }
+       }
+
+       // process search order
+       num = CFDictionaryGetValue(dns, kSCPropNetDNSSearchOrder);
+       if (isA_CFNumber(num)) {
+               uint32_t        order;
+
+               if (CFNumberGetValue(num, kCFNumberIntType, &order)) {
+                       _dns_resolver_set_order(&_resolver, order);
+               }
+       }
+
+       // process port
+       num = CFDictionaryGetValue(dns, kSCPropNetDNSServerPort);
+       if (isA_CFNumber(num)) {
+               int     port;
+
+               if (CFNumberGetValue(num, kCFNumberIntType, &port)) {
+                       _dns_resolver_set_port(&_resolver, (uint16_t)port);
+               }
+       }
+
+       // process timeout
+       num = CFDictionaryGetValue(dns, kSCPropNetDNSServerTimeout);
+       if (isA_CFNumber(num)) {
+               int     timeout;
+
+               if (CFNumberGetValue(num, kCFNumberIntType, &timeout)) {
+                       _dns_resolver_set_timeout(&_resolver, (uint32_t)timeout);
+               }
+       }
+
+       // process options
+       str = CFDictionaryGetValue(dns, kSCPropNetDNSOptions);
+       if (isA_CFString(str)) {
+               char    *options;
+
+               options = _SC_cfstring_to_cstring(str, NULL, 0, kCFStringEncodingUTF8);
+               if (options != NULL) {
+                       _dns_resolver_set_options(&_resolver, options);
+                       CFAllocatorDeallocate(NULL, options);
+               }
+       }
+
+       return _resolver;
+}
+
+
+__private_extern__
+void
+dns_configuration_set(CFDictionaryRef   defaultResolver,
+                     CFDictionaryRef   services,
+                     CFArrayRef        serviceOrder)
+{
+       CFIndex                 i;
+       CFMutableDictionaryRef  myDefault;
+       CFStringRef             myDomain        = NULL;
+       uint32_t                myOrder         = DEFAULT_SEARCH_ORDER;
+       Boolean                 myOrderAdded    = FALSE;
+       CFIndex                 n_supplemental;
+       CFNumberRef             order;
+       dns_create_resolver_t   resolver;
+       CFArrayRef              search;
+       CFMutableArrayRef       supplemental;
+
+       if (defaultResolver == NULL) {
+               myDefault = CFDictionaryCreateMutable(NULL,
+                                                     0,
+                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                     &kCFTypeDictionaryValueCallBacks);
+       } else {
+               myDefault = CFDictionaryCreateMutableCopy(NULL, 0, defaultResolver);
+
+               // ensure that the default resolver has a search order
+
+               order = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchOrder);
+               if (!isA_CFNumber(order) ||
+                   !CFNumberGetValue(order, kCFNumberIntType, &myOrder)) {
+                       myOrderAdded = TRUE;
+                       myOrder = DEFAULT_SEARCH_ORDER;
+                       order = CFNumberCreate(NULL, kCFNumberIntType, &myOrder);
+                       CFDictionarySetValue(myDefault, kSCPropNetDNSSearchOrder, order);
+                       CFRelease(order);
+               }
+       }
+
+       // establish list of supplemental resolvers
+
+       supplemental = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       // identify search[] list and/or domain name
+
+       search = CFDictionaryGetValue(myDefault, kSCPropNetDNSSearchDomains);
+       if (isA_CFArray(search) && (CFArrayGetCount(search) > 0)) {
+               myDomain = CFArrayGetValueAtIndex(search, 0);
+               myDomain = isA_CFString(myDomain);
+       }
+
+       if (myDomain == NULL) {
+               myDomain = CFDictionaryGetValue(myDefault, kSCPropNetDNSDomainName);
+               myDomain = isA_CFString(myDomain);
+       }
+
+       // add match for default domain
+
+       if (myDomain != NULL) {
+               CFMutableDictionaryRef  mySupplemental;
+
+               mySupplemental = CFDictionaryCreateMutableCopy(NULL, 0, myDefault);
+               CFDictionarySetValue   (mySupplemental, kSCPropNetDNSDomainName, myDomain);
+               CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSearchDomains);
+               CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSupplementalMatchDomains);
+               CFDictionaryRemoveValue(mySupplemental, kSCPropNetDNSSupplementalMatchOrders);
+               CFArrayAppendValue(supplemental, mySupplemental);
+               CFRelease(mySupplemental);
+       }
+
+       // collect (and add) any supplemental resolver configurations
+
+       add_supplemental_resolvers(supplemental, services, serviceOrder);
+
+       // update the "search" list
+
+       update_search_domains(&myDefault, supplemental);
+
+       // add any pre-defined resolver configurations
+
+       add_predefined_resolvers(supplemental);
+
+       // check if the "match for default domain" (above) is really needed
+
+       if (myDomain != NULL) {
+               Boolean sharedDomain    = FALSE;
+
+               n_supplemental = CFArrayGetCount(supplemental);
+               for (i = 1; i < n_supplemental; i++) {
+                       CFStringRef     domain;
+                       CFDictionaryRef mySupplemental;
+
+                       mySupplemental = CFArrayGetValueAtIndex(supplemental, i);
+                       domain = CFDictionaryGetValue(mySupplemental, kSCPropNetDNSDomainName);
+                       if (isA_CFString(domain)) {
+                               if (CFEqual(myDomain, domain)) {
+                                       sharedDomain = TRUE;
+                                       break;
+                               }
+
+                               if (CFStringHasSuffix(myDomain, domain)) {
+                                       CFIndex dotIndex;
+
+                                       dotIndex = CFStringGetLength(myDomain) - CFStringGetLength(domain) - 1;
+                                       if (dotIndex > 0) {
+                                               UniChar dot;
+
+                                               dot = CFStringGetCharacterAtIndex(myDomain, dotIndex);
+                                               if (dot == (UniChar)'.') {
+                                                       sharedDomain = TRUE;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               if (!sharedDomain) {
+                       // if the default resolver domain name is not shared
+                       CFArrayRemoveValueAtIndex(supplemental, 0);
+               }
+       }
+
+       // establish resolver configuration
+
+       n_supplemental = CFArrayGetCount(supplemental);
+       if ((defaultResolver == NULL) && (n_supplemental == 0)) {
+               /*
+                * if no default or supplemental resolvers
+                */
+               if (!_dns_configuration_store(NULL)) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("set_dns_configuration: could not store configuration"));
+               }
+       } else {
+               dns_create_config_t     _config;
+
+               /*
+                * if default and/or supplemental resolvers are defined
+                */
+               _config = _dns_configuration_create();
+
+               // add [default] resolver
+
+               if ((n_supplemental == 0) && myOrderAdded) {
+                       CFDictionaryRemoveValue(myDefault, kSCPropNetDNSSearchOrder);
+               }
+               resolver = create_resolver(myDefault);
+               _dns_configuration_add_resolver(&_config, resolver);
+               _dns_resolver_free(&resolver);
+
+               // add [supplemental] resolvers
+
+               for (i = 0; i < n_supplemental; i++) {
+                       CFDictionaryRef supplementalResolver;
+
+                       supplementalResolver = CFArrayGetValueAtIndex(supplemental, i);
+                       resolver = create_resolver(supplementalResolver);
+                       _dns_configuration_add_resolver(&_config, resolver);
+                       _dns_resolver_free(&resolver);
+               }
+
+               // save configuration
+
+               if (!_dns_configuration_store(&_config)) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("set_dns_configuration() failed: could not store configuration"));
+               }
+
+               _dns_configuration_free(&_config);
+       }
+
+       CFRelease(myDefault);
+       CFRelease(supplemental);
+
+       return;
+}
+
+
+static void
+load_predefined_resolvers(CFBundleRef bundle)
+{
+       Boolean                 ok;
+       CFURLRef                url;
+       CFStringRef             xmlError        = NULL;
+       CFDataRef               xmlResolvers    = NULL;
+
+       url = CFBundleCopyResourceURL(bundle, CFSTR("Resolvers"), CFSTR("plist"), NULL);
+       if (url == NULL) {
+               return;
+       }
+
+       ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlResolvers, NULL, NULL, NULL);
+       CFRelease(url);
+       if (!ok || (xmlResolvers == NULL)) {
+               return;
+       }
+
+       /* convert the XML data into a property list */
+       S_predefined = CFPropertyListCreateFromXMLData(NULL, xmlResolvers, kCFPropertyListImmutable, &xmlError);
+       CFRelease(xmlResolvers);
+       if (S_predefined == NULL) {
+               if (xmlError != NULL) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("add_predefined_resolvers: %@"), xmlError);
+                       CFRelease(xmlError);
+               }
+               return;
+       }
+
+       if (!isA_CFArray(S_predefined)) {
+               CFRelease(S_predefined);
+               S_predefined = NULL;
+               return;
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+dns_configuration_init(CFBundleRef bundle)
+{
+       load_predefined_resolvers(bundle);
+       return;
+}
+
diff --git a/Plugins/IPMonitor/ip_plugin.c b/Plugins/IPMonitor/ip_plugin.c
new file mode 100644 (file)
index 0000000..8603a74
--- /dev/null
@@ -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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/sysctl.h>
+#include <limits.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>     /* for SCLog() */
+
+#include <dnsinfo.h>
+
+void load_hostname(Boolean verbose);
+void dns_configuration_init(CFBundleRef bundle);
+void dns_configuration_set(CFDictionaryRef      defaultResolver,
+                          CFDictionaryRef      services,
+                          CFArrayRef           serviceOrder);
+
+#define IP_FORMAT      "%d.%d.%d.%d"
+#define IP_CH(ip)      ((u_char *)(ip))
+#define IP_LIST(ip)    IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
+
+/* debug output on/off */
+static boolean_t               S_IPMonitor_debug = FALSE;
+
+/* are we netbooted?  If so, don't touch the default route */
+static boolean_t               S_netboot = FALSE;
+
+/* notification key indicating dns configuration has been changed */
+static CFStringRef             S_notify_dnsinfo = NULL;
+
+/* dictionary to hold per-service state: key is the serviceID */
+static CFMutableDictionaryRef  S_service_state_dict = NULL;
+
+/* if set, a PPP interface overrides the primary */
+static boolean_t               S_ppp_override_primary = TRUE;
+
+/* the current primary serviceID's */
+static CFStringRef             S_primary_ipv4 = NULL;
+static CFStringRef             S_primary_ipv6 = NULL;
+static CFStringRef             S_primary_dns = NULL;
+static CFStringRef             S_primary_proxies = NULL;
+
+static CFStringRef             S_state_global_ipv4 = NULL;
+static CFStringRef             S_state_global_ipv6 = NULL;
+static CFStringRef             S_state_global_dns = NULL;
+static CFStringRef             S_state_global_netinfo = NULL;
+static CFStringRef             S_state_global_proxies = NULL;
+static CFStringRef             S_state_service_prefix = NULL;
+static CFStringRef             S_setup_global_ipv4 = NULL;
+static CFStringRef             S_setup_global_netinfo = NULL;
+static CFStringRef             S_setup_global_proxies = NULL;
+static CFStringRef             S_setup_service_prefix = NULL;
+
+static struct in_addr          S_router_subnet = { 0 };
+static struct in_addr          S_router_subnet_mask = { 0 };
+
+static const struct in_addr    S_ip_zeros = { 0 };
+static const struct in6_addr   S_ip6_zeros = IN6ADDR_ANY_INIT;
+
+
+#define kRouterNeedsLocalIP    CFSTR("com.apple.IPMonitor.RouterNeedsLocalIP")
+#define kRouterIsDirect                CFSTR("com.apple.IPMonitor.IsDirect")
+
+#define VAR_RUN_RESOLV_CONF            "/var/run/resolv.conf"
+#define VAR_RUN_NICONFIG_LOCAL_XML     "/var/run/niconfig_local.xml"
+
+#ifndef KERN_NETBOOT
+#define KERN_NETBOOT           40      /* int: are we netbooted? 1=yes,0=no */
+#endif KERN_NETBOOT
+
+/**
+ ** entityType*, GetEntityChanges*
+ ** - definitions for the entity types we handle
+ **/
+#define ENTITY_TYPES_COUNT     5
+enum {
+    kEntityTypeIPv4    = 0,
+    kEntityTypeIPv6    = 1,
+    kEntityTypeDNS     = 2,
+    kEntityTypeNetInfo         = 3,
+    kEntityTypeProxies         = 4,
+};
+typedef uint32_t       EntityType;
+
+static CFStringRef entityTypeNames[ENTITY_TYPES_COUNT];
+
+typedef boolean_t (GetEntityChangesFunc)(CFStringRef serviceID,
+                                        CFDictionaryRef state_dict,
+                                        CFDictionaryRef setup_dict,
+                                        CFDictionaryRef info);
+typedef GetEntityChangesFunc * GetEntityChangesFuncRef;
+
+static GetEntityChangesFunc get_ipv4_changes;
+static GetEntityChangesFunc get_ipv6_changes;
+static GetEntityChangesFunc get_dns_changes;
+static GetEntityChangesFunc get_netinfo_changes;
+static GetEntityChangesFunc get_proxies_changes;
+
+static void
+my_CFRelease(void * t);
+
+static void
+my_CFArrayAppendUniqueValue(CFMutableArrayRef arr, CFTypeRef new);
+
+static void
+my_CFArrayRemoveValue(CFMutableArrayRef arr, CFStringRef key);
+
+static GetEntityChangesFuncRef entityChangeFunc[ENTITY_TYPES_COUNT] = {
+    get_ipv4_changes,  /* 0 */
+    get_ipv6_changes,  /* 1 */
+    get_dns_changes,   /* 2 */
+    get_netinfo_changes,/* 3 */
+    get_proxies_changes,/* 4 */
+};
+
+/**
+ ** keyChangeList
+ ** - mechanism to do an atomic update of the SCDynamicStore
+ **   when the content needs to be changed across multiple functions
+ **/
+typedef struct {
+    CFMutableArrayRef          notify;
+    CFMutableArrayRef          remove;
+    CFMutableDictionaryRef     set;
+} keyChangeList, * keyChangeListRef;
+
+static void
+keyChangeListInit(keyChangeListRef keys)
+{
+    keys->notify = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    keys->remove = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    keys->set = CFDictionaryCreateMutable(NULL, 0,
+                                         &kCFTypeDictionaryKeyCallBacks,
+                                         &kCFTypeDictionaryValueCallBacks);
+    return;
+}
+
+static void
+keyChangeListFree(keyChangeListRef keys)
+{
+    my_CFRelease(&keys->notify);
+    my_CFRelease(&keys->remove);
+    my_CFRelease(&keys->set);
+    return;
+}
+
+static void
+keyChangeListNotifyKey(keyChangeListRef keys, CFStringRef key)
+{
+    my_CFArrayAppendUniqueValue(keys->notify, key);
+    return;
+}
+
+static void
+keyChangeListRemoveValue(keyChangeListRef keys, CFStringRef key)
+{
+    my_CFArrayAppendUniqueValue(keys->remove, key);
+    CFDictionaryRemoveValue(keys->set, key);
+    return;
+}
+
+static void
+keyChangeListSetValue(keyChangeListRef keys, CFStringRef key, CFTypeRef value)
+{
+    my_CFArrayRemoveValue(keys->remove, key);
+    CFDictionarySetValue(keys->set, key, value);
+    return;
+}
+
+static void
+keyChangeListApplyToStore(keyChangeListRef keys, SCDynamicStoreRef session)
+{
+    CFArrayRef         notify = keys->notify;
+    CFArrayRef         remove = keys->remove;
+    CFDictionaryRef    set = keys->set;
+
+    if (CFArrayGetCount(notify) == 0) {
+       notify = NULL;
+    }
+    if (CFArrayGetCount(remove) == 0) {
+       remove = NULL;
+    }
+    if (CFDictionaryGetCount(set) == 0) {
+       set = NULL;
+    }
+    if (set == NULL && remove == NULL && notify == NULL) {
+       return;
+    }
+    if (S_IPMonitor_debug) {
+       if (set != NULL) {
+           SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: Setting:\n%@\n"), set);
+       }
+       if (remove != NULL) {
+           SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: Removing:\n%@\n"), remove);
+       }
+       if (notify != NULL) {
+           SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: Notifying:\n%@\n"), notify);
+       }
+    }
+    (void)SCDynamicStoreSetMultiple(session, set, remove, notify);
+    return;
+}
+
+static boolean_t
+S_netboot_root()
+{
+    int mib[2];
+    size_t len;
+    int netboot = 0;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_NETBOOT;
+    len = sizeof(netboot);
+    sysctl(mib, 2, &netboot, &len, NULL, 0);
+    return (netboot);
+}
+
+static void
+my_CFArrayAppendUniqueValue(CFMutableArrayRef arr, CFTypeRef new)
+{
+    CFIndex    n = CFArrayGetCount(arr);
+
+    if (CFArrayContainsValue(arr, CFRangeMake(0, n), new)) {
+       return;
+    }
+    CFArrayAppendValue(arr, new);
+    return;
+}
+
+static void
+my_CFArrayRemoveValue(CFMutableArrayRef arr, CFStringRef key)
+{
+    CFIndex    i;
+
+    i = CFArrayGetFirstIndexOfValue(arr,
+                                   CFRangeMake(0, CFArrayGetCount(arr)),
+                                   key);
+    if (i != kCFNotFound) {
+       CFArrayRemoveValueAtIndex(arr, i);
+    }
+    return;
+}
+
+static void
+my_CFRelease(void * t)
+{
+    void * * obj = (void * *)t;
+
+    if (obj && *obj) {
+       CFRelease(*obj);
+       *obj = NULL;
+    }
+    return;
+}
+
+static CFDictionaryRef
+my_CFDictionaryGetDictionary(CFDictionaryRef dict, CFStringRef key)
+{
+    if (isA_CFDictionary(dict) == NULL) {
+       return (NULL);
+    }
+    return (isA_CFDictionary(CFDictionaryGetValue(dict, key)));
+}
+
+static CFDictionaryRef
+my_SCDCopy(SCDynamicStoreRef session, CFStringRef key)
+{
+    CFDictionaryRef    dict;
+
+    dict = SCDynamicStoreCopyValue(session, key);
+    if (isA_CFDictionary(dict) == NULL) {
+       my_CFRelease(&dict);
+    }
+    return dict;
+}
+
+static boolean_t
+cfstring_to_ipvx(int family, CFStringRef str, void * addr, int addr_size)
+{
+    char        buf[128];
+
+    if (isA_CFString(str) == NULL) {
+       goto done;
+    }
+
+    switch (family) {
+    case AF_INET:
+       if (addr_size < sizeof(struct in_addr)) {
+           goto done;
+       }
+       break;
+    case AF_INET6:
+       if (addr_size < sizeof(struct in6_addr)) {
+           goto done;
+       }
+       break;
+    default:
+       goto done;
+    }
+    (void)_SC_cfstring_to_cstring(str, buf, sizeof(buf), kCFStringEncodingASCII);
+    if (inet_pton(family, buf, addr) == 1) {
+       return (TRUE);
+    }
+ done:
+    bzero(addr, addr_size);
+    return (FALSE);
+}
+
+static boolean_t
+cfstring_to_ip(CFStringRef str, struct in_addr * ip_p)
+{
+    return (cfstring_to_ipvx(AF_INET, str, ip_p, sizeof(*ip_p)));
+}
+
+static boolean_t
+cfstring_to_ip6(CFStringRef str, struct in6_addr * ip6_p)
+{
+    return (cfstring_to_ipvx(AF_INET6, str, ip6_p, sizeof(*ip6_p)));
+}
+
+/*
+ * Function: parse_component
+ * Purpose:
+ *   Given a string 'key' and a string prefix 'prefix',
+ *   return the next component in the slash '/' separated
+ *   key.
+ *
+ * Examples:
+ * 1. key = "a/b/c" prefix = "a/"
+ *    returns "b"
+ * 2. key = "a/b/c" prefix = "a/b/"
+ *    returns "c"
+ */
+static CFStringRef
+parse_component(CFStringRef key, CFStringRef prefix)
+{
+    CFMutableStringRef comp;
+    CFRange            range;
+
+    if (CFStringHasPrefix(key, prefix) == FALSE) {
+       return (NULL);
+    }
+    comp = CFStringCreateMutableCopy(NULL, 0, key);
+    if (comp == NULL) {
+       return (NULL);
+    }
+    CFStringDelete(comp, CFRangeMake(0, CFStringGetLength(prefix)));
+    range = CFStringFind(comp, CFSTR("/"), 0);
+    if (range.location == kCFNotFound) {
+       return (comp);
+    }
+    range.length = CFStringGetLength(comp) - range.location;
+    CFStringDelete(comp, range);
+    return (comp);
+}
+
+static void
+append_netinfo_arrays(CFDictionaryRef dict, CFMutableArrayRef ni_addrs,
+                     CFMutableArrayRef ni_tags)
+{
+    CFArrayRef         addrs;
+    CFArrayRef         tags;
+
+    if (isA_CFDictionary(dict) == NULL)
+       return;
+
+    addrs = isA_CFArray(CFDictionaryGetValue(dict, kSCPropNetNetInfoServerAddresses));
+    tags  = isA_CFArray(CFDictionaryGetValue(dict, kSCPropNetNetInfoServerTags));
+    if (addrs && tags) {
+       CFIndex         addrs_count = CFArrayGetCount(addrs);
+       CFIndex         tags_count = CFArrayGetCount(tags);
+
+       if (addrs_count > 0) {
+           if (addrs_count == tags_count) {
+               CFArrayAppendArray(ni_addrs, addrs,
+                                  CFRangeMake(0, addrs_count));
+               CFArrayAppendArray(ni_tags, tags,
+                                  CFRangeMake(0, tags_count));
+           }
+
+       }
+
+    }
+    return;
+}
+
+static void
+append_netinfo_broadcast_addresses(CFDictionaryRef netinfo_dict,
+                                  CFDictionaryRef ipv4_dict,
+                                  CFMutableArrayRef ni_addrs,
+                                  CFMutableArrayRef ni_tags)
+{
+    CFArrayRef         addrs;
+    CFIndex            addrs_count;
+    CFIndex            i;
+    CFArrayRef         masks;
+    CFIndex            masks_count;
+    CFStringRef                tag;
+
+    tag = CFDictionaryGetValue(netinfo_dict,
+                              kSCPropNetNetInfoBroadcastServerTag);
+    tag = isA_CFString(tag);
+    if (tag == NULL) {
+       tag = kSCValNetNetInfoDefaultServerTag;
+    }
+    addrs = isA_CFArray(CFDictionaryGetValue(ipv4_dict,
+                                            kSCPropNetIPv4Addresses));
+    masks = isA_CFArray(CFDictionaryGetValue(ipv4_dict,
+                                            kSCPropNetIPv4SubnetMasks));
+    if (addrs == NULL || masks == NULL) {
+       return;
+    }
+    masks_count = CFArrayGetCount(masks);
+    addrs_count = CFArrayGetCount(addrs);
+    if (addrs_count != masks_count) {
+       return;
+    }
+
+    for (i = 0; i < addrs_count; i++) {
+       struct in_addr  addr;
+       CFStringRef     broadcast = NULL;
+       struct in_addr  mask;
+
+       if (cfstring_to_ip(CFArrayGetValueAtIndex(addrs, i), &addr)
+           && cfstring_to_ip(CFArrayGetValueAtIndex(masks, i), &mask)) {
+           struct in_addr              b;
+
+           b.s_addr = htonl(ntohl(addr.s_addr) | ~ntohl(mask.s_addr));
+           broadcast = CFStringCreateWithFormat(NULL, NULL,
+                                                CFSTR(IP_FORMAT),
+                                                IP_LIST(&b));
+           CFArrayAppendValue(ni_addrs, broadcast);
+           CFArrayAppendValue(ni_tags, tag);
+           my_CFRelease(&broadcast);
+       }
+    }
+    return;
+}
+
+static CFDictionaryRef
+make_netinfo_dict(CFDictionaryRef state_dict,
+                 CFDictionaryRef setup_dict,
+                 CFDictionaryRef ipv4_dict)
+{
+    boolean_t                  has_manual = FALSE;
+    boolean_t                  has_broadcast = FALSE;
+    boolean_t                  has_dhcp = FALSE;
+    CFIndex                    i;
+    CFArrayRef                 m = NULL;
+    CFIndex                    n;
+    CFMutableArrayRef          ni_addrs = NULL;
+    CFMutableDictionaryRef     ni_dict = NULL;
+    CFMutableArrayRef          ni_tags = NULL;
+
+    if (setup_dict == NULL || ipv4_dict == NULL) {
+       goto netinfo_done;
+    }
+    m = isA_CFArray(CFDictionaryGetValue(setup_dict,
+                                        kSCPropNetNetInfoBindingMethods));
+    if (m == NULL) {
+       goto netinfo_done;
+    }
+    ni_addrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    ni_tags = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+    /* find out which are configured */
+    n = CFArrayGetCount(m);
+    for (i = 0; i < n; i++) {
+       CFStringRef method = CFArrayGetValueAtIndex(m, i);
+
+       if (CFEqual(method,
+                   kSCValNetNetInfoBindingMethodsManual)) {
+           has_manual = TRUE;
+       }
+       else if (CFEqual(method,
+                        kSCValNetNetInfoBindingMethodsDHCP)) {
+           has_dhcp = TRUE;
+       }
+       else if (CFEqual(method,
+                        kSCValNetNetInfoBindingMethodsBroadcast)) {
+           has_broadcast = TRUE;
+       }
+    }
+    if (has_dhcp && state_dict != NULL) {
+       append_netinfo_arrays(state_dict, ni_addrs, ni_tags);
+    }
+    if (has_manual) {
+       append_netinfo_arrays(setup_dict, ni_addrs, ni_tags);
+    }
+    if (has_broadcast) {
+       append_netinfo_broadcast_addresses(setup_dict, ipv4_dict,
+                                          ni_addrs, ni_tags);
+    }
+    if (CFArrayGetCount(ni_addrs) == 0) {
+       goto netinfo_done;
+    }
+    ni_dict = CFDictionaryCreateMutable(NULL, 0,
+                                       &kCFTypeDictionaryKeyCallBacks,
+                                       &kCFTypeDictionaryValueCallBacks);
+    CFDictionarySetValue(ni_dict, kSCPropNetNetInfoServerAddresses,
+                        ni_addrs);
+    CFDictionarySetValue(ni_dict, kSCPropNetNetInfoServerTags,
+                        ni_tags);
+ netinfo_done:
+    my_CFRelease(&ni_addrs);
+    my_CFRelease(&ni_tags);
+    return (ni_dict);
+}
+
+static CFMutableDictionaryRef
+service_dict_copy(CFStringRef serviceID)
+{
+    CFDictionaryRef            d = NULL;
+    CFMutableDictionaryRef     service_dict;
+
+    /* create a modifyable dictionary, a copy or a new one */
+    d = CFDictionaryGetValue(S_service_state_dict, serviceID);
+    if (d == NULL) {
+       service_dict
+           = CFDictionaryCreateMutable(NULL, 0,
+                                       &kCFTypeDictionaryKeyCallBacks,
+                                       &kCFTypeDictionaryValueCallBacks);
+    }
+    else {
+       service_dict = CFDictionaryCreateMutableCopy(NULL, 0, d);
+    }
+    return (service_dict);
+}
+
+static boolean_t
+service_dict_set(CFStringRef serviceID, CFStringRef entity,
+                CFDictionaryRef new_dict)
+{
+    boolean_t                  changed = FALSE;
+    CFDictionaryRef            old;
+    CFMutableDictionaryRef     service_dict;
+
+    service_dict = service_dict_copy(serviceID);
+    old = CFDictionaryGetValue(service_dict, entity);
+    if (new_dict == NULL) {
+       if (old != NULL) {
+           SCLog(S_IPMonitor_debug, LOG_INFO,
+                 CFSTR("IPMonitor: serviceID %@ removed %@ dictionary = %@"),
+                 serviceID, entity, old);
+           CFDictionaryRemoveValue(service_dict, entity);
+           changed = TRUE;
+       }
+    }
+    else {
+       if (old == NULL || CFEqual(new_dict, old) == FALSE) {
+           SCLog(S_IPMonitor_debug, LOG_INFO,
+                 CFSTR("IPMonitor: serviceID %@ changed %@"
+                       " dictionary\nold %@\nnew %@"), serviceID, entity,
+                 (old != NULL) ? (CFTypeRef)old : (CFTypeRef)CFSTR("<none>"),
+                 new_dict);
+           CFDictionarySetValue(service_dict, entity, new_dict);
+           changed = TRUE;
+       }
+    }
+    if (CFDictionaryGetCount(service_dict) == 0) {
+       CFDictionaryRemoveValue(S_service_state_dict, serviceID);
+    }
+    else {
+       CFDictionarySetValue(S_service_state_dict, serviceID, service_dict);
+    }
+    my_CFRelease(&service_dict);
+    return (changed);
+}
+
+static CFDictionaryRef
+service_dict_get(CFStringRef serviceID, CFStringRef entity)
+{
+    CFDictionaryRef    service_dict;
+
+    service_dict = CFDictionaryGetValue(S_service_state_dict, serviceID);
+    if (service_dict == NULL) {
+       return (NULL);
+    }
+    return (CFDictionaryGetValue(service_dict, entity));
+}
+
+/**
+ ** GetEntityChangesFunc functions
+ **/
+static __inline__ struct in_addr
+subnet_addr(struct in_addr addr, struct in_addr mask)
+{
+    struct in_addr     net;
+
+    net.s_addr = htonl((uint32_t)ntohl(addr.s_addr)
+                      & (uint32_t)ntohl(mask.s_addr));
+    return (net);
+}
+
+static boolean_t
+get_ipv4_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+                CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+    struct in_addr             addr = { 0 };
+    CFArrayRef                 addrs;
+    boolean_t                  changed = FALSE;
+    CFMutableDictionaryRef     dict = NULL;
+    struct in_addr             mask = { 0 };
+    CFArrayRef                 masks;
+    CFDictionaryRef            new_dict = NULL;
+    CFStringRef                        router = NULL;
+    boolean_t                  valid_ip = FALSE;
+    boolean_t                  valid_mask = FALSE;
+
+    if (state_dict == NULL) {
+       goto done;
+    }
+    addrs = isA_CFArray(CFDictionaryGetValue(state_dict,
+                                            kSCPropNetIPv4Addresses));
+    if (addrs != NULL && CFArrayGetCount(addrs) > 0) {
+       valid_ip = cfstring_to_ip(CFArrayGetValueAtIndex(addrs, 0), &addr);
+    }
+    masks = isA_CFArray(CFDictionaryGetValue(state_dict,
+                                            kSCPropNetIPv4SubnetMasks));
+    if (masks != NULL && CFArrayGetCount(masks) > 0) {
+       valid_mask = cfstring_to_ip(CFArrayGetValueAtIndex(masks, 0), &mask);
+    }
+    if (valid_ip == FALSE) {
+       SCLog(S_IPMonitor_debug, LOG_INFO,
+             CFSTR("IPMonitor: %@ has no valid IP address, ignoring"),
+             serviceID);
+       goto done;
+    }
+    dict = CFDictionaryCreateMutableCopy(NULL, 0, state_dict);
+    if (setup_dict != NULL) {
+       router = CFDictionaryGetValue(setup_dict,
+                                     kSCPropNetIPv4Router);
+       if (router != NULL) {
+           CFDictionarySetValue(dict,
+                                kSCPropNetIPv4Router,
+                                router);
+       }
+    }
+
+    /* check whether the router is direct, or non-local */
+    router = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
+    if (router != NULL) {
+       struct in_addr          router_ip;
+
+       if (cfstring_to_ip(router, &router_ip)) {
+           if (router_ip.s_addr == addr.s_addr) {
+               /* default route routes directly to the interface */
+               CFDictionarySetValue(dict, kRouterIsDirect, kCFBooleanTrue);
+           }
+           else if (valid_mask
+                    && subnet_addr(addr, mask).s_addr
+                    != subnet_addr(router_ip, mask).s_addr) {
+               /* router is not on the same subnet */
+               CFDictionarySetValue(dict, kRouterNeedsLocalIP,
+                                    CFArrayGetValueAtIndex(addrs, 0));
+           }
+       }
+    }
+    new_dict = dict;
+
+ done:
+    changed = service_dict_set(serviceID, kSCEntNetIPv4, new_dict);
+    my_CFRelease(&new_dict);
+    return (changed);
+}
+
+static boolean_t
+get_ipv6_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+                CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+    struct in6_addr            addr;
+    CFArrayRef                 addrs;
+    boolean_t                  changed = FALSE;
+    CFMutableDictionaryRef     dict = NULL;
+    CFDictionaryRef            new_dict = NULL;
+    CFStringRef                        router = NULL;
+    boolean_t                  valid_ip = FALSE;
+
+    if (state_dict == NULL) {
+       goto done;
+    }
+    addrs = isA_CFArray(CFDictionaryGetValue(state_dict,
+                                            kSCPropNetIPv6Addresses));
+    if (addrs != NULL && CFArrayGetCount(addrs) > 0) {
+       valid_ip = cfstring_to_ip6(CFArrayGetValueAtIndex(addrs, 0), &addr);
+    }
+    if (valid_ip == FALSE) {
+       SCLog(S_IPMonitor_debug, LOG_INFO,
+             CFSTR("IPMonitor: %@ has no valid IPv6 address, ignoring"),
+             serviceID);
+       goto done;
+    }
+    dict = CFDictionaryCreateMutableCopy(NULL, 0, state_dict);
+    if (setup_dict != NULL) {
+       router = CFDictionaryGetValue(setup_dict,
+                                     kSCPropNetIPv6Router);
+       if (router != NULL) {
+           CFDictionarySetValue(dict,
+                                kSCPropNetIPv6Router,
+                                router);
+       }
+    }
+    new_dict = dict;
+ done:
+    changed = service_dict_set(serviceID, kSCEntNetIPv6, new_dict);
+    my_CFRelease(&new_dict);
+    return (changed);
+}
+
+static boolean_t
+dns_has_supplemental(CFStringRef serviceID)
+{
+    CFDictionaryRef     dns_dict;
+    CFDictionaryRef     service_dict;
+
+    service_dict = CFDictionaryGetValue(S_service_state_dict, serviceID);
+    if (service_dict == NULL) {
+       return FALSE;
+    }
+
+    dns_dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
+    if (dns_dict == NULL) {
+       return FALSE;
+    }
+
+    return CFDictionaryContainsKey(dns_dict, kSCPropNetDNSSupplementalMatchDomains);
+}
+
+static void
+merge_dns_prop(CFMutableDictionaryRef dict, CFStringRef key,
+                CFDictionaryRef state_dict, CFDictionaryRef setup_dict,
+                Boolean append)
+{
+    CFArrayRef         setup_prop = NULL;
+    CFArrayRef         state_prop = NULL;
+
+    if (setup_dict != NULL) {
+       setup_prop = isA_CFArray(CFDictionaryGetValue(setup_dict, key));
+    }
+    if (state_dict != NULL) {
+       state_prop = isA_CFArray(CFDictionaryGetValue(state_dict, key));
+    }
+    if ((setup_prop != NULL) && (state_prop != NULL)) {
+       CFMutableArrayRef       merge_prop;
+
+       /* create a new list by merging the setup and state lists */
+       merge_prop = CFArrayCreateMutableCopy(NULL, 0, setup_prop);
+       if (append) {
+           CFRange state_range = CFRangeMake(0, CFArrayGetCount(state_prop));
+
+           CFArrayAppendArray(merge_prop, state_prop, state_range);
+       } else {
+           CFIndex     i;
+           CFIndex     n;
+           CFRange     setup_range = CFRangeMake(0, CFArrayGetCount(setup_prop));
+
+           n = CFArrayGetCount(state_prop);
+           for (i = 0; i < n; i++) {
+               CFTypeRef   val;
+
+               val = CFArrayGetValueAtIndex(state_prop, i);
+               if (!CFArrayContainsValue(setup_prop, setup_range, val)) {
+                   CFArrayAppendValue(merge_prop, val);
+               }
+           }
+       }
+       CFDictionarySetValue(dict, key, merge_prop);
+       my_CFRelease(&merge_prop);
+    }
+    else if (setup_prop != NULL) {
+       CFDictionarySetValue(dict, key, setup_prop);
+    }
+    else if (state_prop != NULL) {
+       CFDictionarySetValue(dict, key, state_prop);
+    }
+    return;
+}
+
+static boolean_t
+get_dns_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+               CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+    boolean_t                  changed = FALSE;
+    CFStringRef                        domain;
+    int                                i;
+    struct {
+       CFStringRef     key;
+       Boolean         append;
+    } merge_list[] = {
+       { kSCPropNetDNSSearchDomains, FALSE },
+       { kSCPropNetDNSServerAddresses, FALSE },
+       { kSCPropNetDNSSortList, FALSE },
+       { kSCPropNetDNSSupplementalMatchDomains, TRUE },
+       { kSCPropNetDNSSupplementalMatchOrders, TRUE },
+       { NULL, FALSE }
+    };
+    CFMutableDictionaryRef      new_dict = NULL;
+    CFStringRef                        pick_list[] = {
+       kSCPropNetDNSDomainName,
+       kSCPropNetDNSOptions,
+       kSCPropNetDNSSearchOrder,
+       kSCPropNetDNSServerPort,
+       kSCPropNetDNSServerTimeout,
+       NULL
+    };
+
+    if (state_dict == NULL && setup_dict == NULL) {
+       /* there is no DNS */
+       goto done;
+    }
+    if (service_dict_get(serviceID, kSCEntNetIPv4) == NULL
+       && service_dict_get(serviceID, kSCEntNetIPv6) == NULL) {
+       /* no point in remembering the DNS */
+       goto done;
+    }
+
+    // merge DNS configuration
+    new_dict = CFDictionaryCreateMutable(NULL, 0,
+                                        &kCFTypeDictionaryKeyCallBacks,
+                                        &kCFTypeDictionaryValueCallBacks);
+
+    for (i = 0; merge_list[i].key != NULL; i++) {
+       merge_dns_prop(new_dict,
+                        merge_list[i].key,
+                        state_dict,
+                        setup_dict,
+                        merge_list[i].append);
+    }
+    for (i = 0; pick_list[i]; i++) {
+       CFTypeRef       val = NULL;
+
+       if (setup_dict != NULL) {
+           val = CFDictionaryGetValue(setup_dict, pick_list[i]);
+       }
+       if (val == NULL && state_dict != NULL) {
+           val = CFDictionaryGetValue(state_dict, pick_list[i]);
+       }
+       if (val != NULL) {
+           CFDictionarySetValue(new_dict, pick_list[i], val);
+       }
+    }
+    if (CFDictionaryGetCount(new_dict) == 0) {
+       my_CFRelease(&new_dict);
+       goto done;
+    }
+
+    /*
+     * ensure any specified domain name (e.g. the domain returned by
+     * a DHCP server) is in the search list.
+     */
+    domain = CFDictionaryGetValue(new_dict, kSCPropNetDNSDomainName);
+    if (isA_CFString(domain)) {
+       CFArrayRef      search;
+
+       search = CFDictionaryGetValue(new_dict, kSCPropNetDNSSearchDomains);
+       if (isA_CFArray(search) &&
+           !CFArrayContainsValue(search, CFRangeMake(0, CFArrayGetCount(search)), domain)) {
+           CFMutableArrayRef   new_search;
+
+           new_search = CFArrayCreateMutableCopy(NULL, 0, search);
+           CFArrayAppendValue(new_search, domain);
+           CFDictionarySetValue(new_dict, kSCPropNetDNSSearchDomains, new_search);
+           my_CFRelease(&new_search);
+       }
+    }
+
+ done:
+    changed = service_dict_set(serviceID, kSCEntNetDNS, new_dict);
+    my_CFRelease(&new_dict);
+    return (changed);
+}
+
+static boolean_t
+get_netinfo_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+                   CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+    boolean_t                  changed = FALSE;
+    CFDictionaryRef            global_dict;
+    CFDictionaryRef            ipv4_dict;
+    CFDictionaryRef            new_dict = NULL;
+
+    global_dict = my_CFDictionaryGetDictionary(info, S_setup_global_netinfo);
+    ipv4_dict = service_dict_get(serviceID, kSCEntNetIPv4);
+    new_dict = make_netinfo_dict(state_dict, global_dict, ipv4_dict);
+    changed = service_dict_set(serviceID, kSCEntNetNetInfo, new_dict);
+    my_CFRelease(&new_dict);
+    return (changed);
+}
+
+static boolean_t
+get_proxies_changes(CFStringRef serviceID, CFDictionaryRef state_dict,
+                   CFDictionaryRef setup_dict, CFDictionaryRef info)
+{
+    boolean_t                  changed = FALSE;
+    CFDictionaryRef            new_dict = NULL;
+
+    if (service_dict_get(serviceID, kSCEntNetIPv4) == NULL
+       && service_dict_get(serviceID, kSCEntNetIPv6) == NULL) {
+       /* no point in remembering the Proxies */
+       goto done;
+    }
+    if (setup_dict != NULL) {
+       new_dict = setup_dict;
+    }
+    else {
+       new_dict = state_dict;
+    }
+ done:
+    changed = service_dict_set(serviceID, kSCEntNetProxies, new_dict);
+    return (changed);
+}
+
+static CFStringRef
+state_service_key(CFStringRef serviceID, CFStringRef entity)
+{
+    return (SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                       kSCDynamicStoreDomainState,
+                                                       serviceID,
+                                                       entity));
+}
+
+static CFStringRef
+setup_service_key(CFStringRef serviceID, CFStringRef entity)
+{
+    return (SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                       kSCDynamicStoreDomainSetup,
+                                                       serviceID,
+                                                       entity));
+}
+
+static CFDictionaryRef
+services_info_copy(SCDynamicStoreRef session, CFArrayRef service_list)
+{
+    int                        count;
+    CFMutableArrayRef  get_keys;
+    int                        i;
+    int                        s;
+    CFDictionaryRef    info;
+
+    count = CFArrayGetCount(service_list);
+    get_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+    CFArrayAppendValue(get_keys, S_setup_global_netinfo);
+    CFArrayAppendValue(get_keys, S_setup_global_proxies);
+    CFArrayAppendValue(get_keys, S_setup_global_ipv4);
+
+    for (s = 0; s < count; s++) {
+       CFStringRef     serviceID = CFArrayGetValueAtIndex(service_list, s);
+
+       for (i = 0; i < ENTITY_TYPES_COUNT; i++) {
+           CFStringRef setup_key;
+           CFStringRef state_key;
+
+           setup_key = setup_service_key(serviceID, entityTypeNames[i]);
+           state_key = state_service_key(serviceID, entityTypeNames[i]);
+           CFArrayAppendValue(get_keys, setup_key);
+           CFArrayAppendValue(get_keys, state_key);
+           my_CFRelease(&setup_key);
+           my_CFRelease(&state_key);
+       }
+    }
+
+    info = SCDynamicStoreCopyMultiple(session, get_keys, NULL);
+    my_CFRelease(&get_keys);
+    return (info);
+}
+
+static CFDictionaryRef
+get_service_setup_entity(CFDictionaryRef service_info, CFStringRef serviceID,
+                        CFStringRef entity)
+{
+    CFStringRef                setup_key;
+    CFDictionaryRef    setup_dict;
+
+    setup_key = setup_service_key(serviceID, entity);
+    setup_dict = my_CFDictionaryGetDictionary(service_info, setup_key);
+    my_CFRelease(&setup_key);
+    return (setup_dict);
+}
+
+static CFDictionaryRef
+get_service_state_entity(CFDictionaryRef service_info, CFStringRef serviceID,
+                        CFStringRef entity)
+{
+    CFStringRef                state_key;
+    CFDictionaryRef    state_dict;
+
+    state_key = state_service_key(serviceID, entity);
+    state_dict = my_CFDictionaryGetDictionary(service_info, state_key);
+    my_CFRelease(&state_key);
+    return (state_dict);
+}
+
+static int                     rtm_seq = 0;
+
+static boolean_t
+ipv4_route(int cmd, struct in_addr gateway, struct in_addr netaddr,
+          struct in_addr netmask, char * ifname, boolean_t is_direct)
+{
+    boolean_t                  default_route = (netaddr.s_addr == 0);
+    int                        len;
+    boolean_t                  ret = TRUE;
+    struct {
+       struct rt_msghdr        hdr;
+       struct sockaddr_in      dst;
+       struct sockaddr_in      gway;
+       struct sockaddr_in      mask;
+       struct sockaddr_dl      link;
+    }                          rtmsg;
+    int                        sockfd = -1;
+
+    if (default_route && S_netboot) {
+       return (TRUE);
+    }
+
+    if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR("IPMonitor: ipv4_route: open routing socket failed, %s"),
+             strerror(errno));
+       return (FALSE);
+    }
+
+    memset(&rtmsg, 0, sizeof(rtmsg));
+    rtmsg.hdr.rtm_type = cmd;
+    if (default_route) {
+       if (is_direct) {
+           /* if router is directly reachable, don't set the gateway flag */
+           rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
+       }
+       else {
+           rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
+       }
+    }
+    else {
+       rtmsg.hdr.rtm_flags = RTF_UP | RTF_CLONING | RTF_STATIC;
+    }
+    rtmsg.hdr.rtm_version = RTM_VERSION;
+    rtmsg.hdr.rtm_seq = ++rtm_seq;
+    rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+    rtmsg.dst.sin_len = sizeof(rtmsg.dst);
+    rtmsg.dst.sin_family = AF_INET;
+    rtmsg.dst.sin_addr = netaddr;
+    rtmsg.gway.sin_len = sizeof(rtmsg.gway);
+    rtmsg.gway.sin_family = AF_INET;
+    rtmsg.gway.sin_addr = gateway;
+    rtmsg.mask.sin_len = sizeof(rtmsg.mask);
+    rtmsg.mask.sin_family = AF_INET;
+    rtmsg.mask.sin_addr = netmask;
+
+    len = sizeof(rtmsg);
+    if (ifname) {
+       rtmsg.link.sdl_len = sizeof(rtmsg.link);
+       rtmsg.link.sdl_family = AF_LINK;
+       rtmsg.link.sdl_nlen = strlen(ifname);
+       rtmsg.hdr.rtm_addrs |= RTA_IFP;
+       bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen);
+    }
+    else {
+       /* no link information */
+       len -= sizeof(rtmsg.link);
+    }
+    rtmsg.hdr.rtm_msglen = len;
+    if (write(sockfd, &rtmsg, len) < 0) {
+       if ((cmd == RTM_ADD) && (errno == EEXIST)) {
+           /* no sense complaining about a route that already exists */
+       }
+       else if ((cmd == RTM_DELETE) && (errno == ESRCH)) {
+           /* no sense complaining about a route that isn't there */
+       }
+       else {
+           SCLog(S_IPMonitor_debug, LOG_INFO,
+                 CFSTR("IPMonitor ipv4_route: "
+                       "write routing socket failed, %s"), strerror(errno));
+           ret = FALSE;
+       }
+    }
+
+    close(sockfd);
+    return (ret);
+}
+
+static boolean_t
+ipv6_route(int cmd, struct in6_addr gateway, struct in6_addr netaddr,
+          struct in6_addr netmask, char * ifname, boolean_t is_direct)
+{
+    boolean_t                  default_route;
+    int                        len;
+    boolean_t                  ret = TRUE;
+    struct {
+       struct rt_msghdr        hdr;
+       struct sockaddr_in6     dst;
+       struct sockaddr_in6     gway;
+       struct sockaddr_in6     mask;
+       struct sockaddr_dl      link;
+    }                          rtmsg;
+    int                        sockfd = -1;
+    struct in6_addr            zeroes = IN6ADDR_ANY_INIT;
+
+    default_route = (bcmp(&zeroes, &netaddr, sizeof(netaddr)) == 0);
+
+    if (IN6_IS_ADDR_LINKLOCAL(&gateway) && ifname != NULL) {
+       unsigned int    index = if_nametoindex(ifname);
+
+       /* add the scope id to the link local address */
+       gateway.__u6_addr.__u6_addr16[1] = (uint16_t)htons(index);
+    }
+    if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR("IPMonitor ipv6_route: open routing socket failed, %s"),
+             strerror(errno));
+       return (FALSE);
+    }
+    memset(&rtmsg, 0, sizeof(rtmsg));
+    rtmsg.hdr.rtm_type = cmd;
+    if (default_route) {
+       if (is_direct) {
+           /* if router is directly reachable, don't set the gateway flag */
+           rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
+       }
+       else {
+           rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
+       }
+    }
+    else {
+       rtmsg.hdr.rtm_flags = RTF_UP | RTF_CLONING | RTF_STATIC;
+    }
+    rtmsg.hdr.rtm_version = RTM_VERSION;
+    rtmsg.hdr.rtm_seq = ++rtm_seq;
+    rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+    rtmsg.dst.sin6_len = sizeof(rtmsg.dst);
+    rtmsg.dst.sin6_family = AF_INET6;
+    rtmsg.dst.sin6_addr = netaddr;
+    rtmsg.gway.sin6_len = sizeof(rtmsg.gway);
+    rtmsg.gway.sin6_family = AF_INET6;
+    rtmsg.gway.sin6_addr = gateway;
+    rtmsg.mask.sin6_len = sizeof(rtmsg.mask);
+    rtmsg.mask.sin6_family = AF_INET6;
+    rtmsg.mask.sin6_addr = netmask;
+
+    len = sizeof(rtmsg);
+    if (ifname) {
+       rtmsg.link.sdl_len = sizeof(rtmsg.link);
+       rtmsg.link.sdl_family = AF_LINK;
+       rtmsg.link.sdl_nlen = strlen(ifname);
+       rtmsg.hdr.rtm_addrs |= RTA_IFP;
+       bcopy(ifname, rtmsg.link.sdl_data, rtmsg.link.sdl_nlen);
+    }
+    else {
+       /* no link information */
+       len -= sizeof(rtmsg.link);
+    }
+    rtmsg.hdr.rtm_msglen = len;
+    if (write(sockfd, &rtmsg, len) < 0) {
+       if ((cmd == RTM_ADD) && (errno == EEXIST)) {
+           /* no sense complaining about a route that already exists */
+       }
+       else if ((cmd == RTM_DELETE) && (errno == ESRCH)) {
+           /* no sense complaining about a route that isn't there */
+       }
+       else {
+           SCLog(S_IPMonitor_debug, LOG_INFO,
+                 CFSTR("IPMonitor ipv6_route: write routing"
+                       " socket failed, %s"), strerror(errno));
+           ret = FALSE;
+       }
+    }
+
+    close(sockfd);
+    return (ret);
+}
+
+static boolean_t
+ipv4_subnet_route_add(struct in_addr local_ip,
+                     struct in_addr subnet, struct in_addr mask, char * ifname)
+{
+    if (S_IPMonitor_debug) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR("IPMonitor: IPv4 route add -net "
+                   IP_FORMAT " -netmask %s interface %s"),
+             IP_LIST(&subnet), inet_ntoa(mask), ifname);
+    }
+    return (ipv4_route(RTM_ADD, local_ip, subnet, mask, ifname, FALSE));
+}
+
+static boolean_t
+ipv4_subnet_route_delete(struct in_addr subnet, struct in_addr mask)
+{
+    if (S_IPMonitor_debug) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR("IPMonitor: IPv4 route delete -net "
+                   IP_FORMAT " %s"),
+             IP_LIST(&subnet), inet_ntoa(mask));
+    }
+    return (ipv4_route(RTM_DELETE, S_ip_zeros, subnet, mask, NULL, FALSE));
+}
+
+
+static boolean_t
+ipv4_default_route_delete(void)
+{
+    if (S_IPMonitor_debug) {
+       SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: IPv4 route delete default"));
+    }
+    return (ipv4_route(RTM_DELETE, S_ip_zeros, S_ip_zeros, S_ip_zeros, NULL, FALSE));
+}
+
+static boolean_t
+ipv4_default_route_add(struct in_addr router, char * ifname,
+                      boolean_t is_direct)
+{
+    if (S_IPMonitor_debug) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR("IPMonitor: IPv4 route add default"
+                   " %s interface %s direct %d"),
+             inet_ntoa(router), ifname, is_direct);
+    }
+    return (ipv4_route(RTM_ADD, router, S_ip_zeros, S_ip_zeros, ifname, is_direct));
+}
+
+static boolean_t
+ipv4_default_route_change(struct in_addr router, char * ifname,
+                         boolean_t is_direct)
+{
+    if (S_IPMonitor_debug) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR("IPMonitor: IPv4 route change default"
+                   " %s interface %s direct %d"),
+             inet_ntoa(router), ifname, is_direct);
+    }
+    return (ipv4_route(RTM_CHANGE, router, S_ip_zeros, S_ip_zeros, ifname,
+                      is_direct));
+}
+
+static boolean_t
+ipv6_default_route_delete(void)
+{
+    if (S_IPMonitor_debug) {
+       SCLog(TRUE, LOG_INFO, CFSTR("IPMonitor: IPv6 route delete default"));
+    }
+    return (ipv6_route(RTM_DELETE, S_ip6_zeros, S_ip6_zeros, S_ip6_zeros, NULL, FALSE));
+}
+
+static boolean_t
+ipv6_default_route_add(struct in6_addr router, char * ifname,
+                      boolean_t is_direct)
+{
+    if (S_IPMonitor_debug) {
+       char    str[128];
+
+       str[0] = '\0';
+
+       inet_ntop(AF_INET6, &router, str, sizeof(str));
+       SCLog(TRUE,LOG_INFO,
+             CFSTR("IPMonitor: IPv6 route add default"
+                   " %s interface %s direct %d"),
+             str, ifname, is_direct);
+    }
+    return (ipv6_route(RTM_ADD, router, S_ip6_zeros, S_ip6_zeros, ifname, is_direct));
+}
+
+
+static boolean_t
+multicast_route_delete()
+{
+    struct in_addr gateway = { htonl(INADDR_LOOPBACK) };
+    struct in_addr netaddr = { htonl(INADDR_UNSPEC_GROUP) };
+    struct in_addr netmask = { htonl(IN_CLASSD_NET) };
+
+    return (ipv4_route(RTM_DELETE, gateway, netaddr, netmask, "lo0", FALSE));
+}
+
+static boolean_t
+multicast_route_add()
+{
+    struct in_addr gateway = { htonl(INADDR_LOOPBACK) };
+    struct in_addr netaddr = { htonl(INADDR_UNSPEC_GROUP) };
+    struct in_addr netmask = { htonl(IN_CLASSD_NET) };
+
+    return (ipv4_route(RTM_ADD, gateway, netaddr, netmask, "lo0", FALSE));
+}
+
+static void
+set_ipv4_router(struct in_addr * router, char * ifname, boolean_t is_direct)
+{
+    if (S_router_subnet.s_addr != 0) {
+       ipv4_subnet_route_delete(S_router_subnet, S_router_subnet_mask);
+       S_router_subnet.s_addr = S_router_subnet_mask.s_addr = 0;
+    }
+    /* assign the new default route, ensure local multicast route available */
+    (void)ipv4_default_route_delete();
+    if (router != NULL) {
+       (void)ipv4_default_route_add(*router, ifname, is_direct);
+       (void)multicast_route_delete();
+    }
+    else {
+       (void)multicast_route_add();
+    }
+
+    return;
+}
+
+static void
+set_ipv6_router(struct in6_addr * router, char * ifname, boolean_t is_direct)
+{
+    /* assign the new default route, ensure local multicast route available */
+    (void)ipv6_default_route_delete();
+    if (router != NULL) {
+       (void)ipv6_default_route_add(*router, ifname, is_direct);
+    }
+    return;
+}
+
+static __inline__ void
+empty_dns()
+{
+    (void)unlink(VAR_RUN_RESOLV_CONF);
+}
+
+static void
+empty_netinfo(SCDynamicStoreRef session)
+{
+    int fd = open(VAR_RUN_NICONFIG_LOCAL_XML "-",
+                 O_CREAT|O_TRUNC|O_WRONLY, 0644);
+    if (fd >= 0) {
+       close(fd);
+       rename(VAR_RUN_NICONFIG_LOCAL_XML "-", VAR_RUN_NICONFIG_LOCAL_XML);
+    }
+
+    return;
+}
+
+static void
+set_dns(CFArrayRef val_search_domains,
+       CFStringRef val_domain_name,
+       CFArrayRef val_servers,
+       CFArrayRef val_sortlist)
+{
+    FILE * f = fopen(VAR_RUN_RESOLV_CONF "-", "w");
+
+    /* publish new resolv.conf */
+    if (f) {
+       CFIndex i;
+       CFIndex n;
+
+       if (isA_CFString(val_domain_name)) {
+           SCPrint(TRUE, f, CFSTR("domain %@\n"), val_domain_name);
+       }
+
+       if (isA_CFArray(val_search_domains)) {
+           SCPrint(TRUE, f, CFSTR("search"));
+           n = CFArrayGetCount(val_search_domains);
+           for (i = 0; i < n; i++) {
+               CFStringRef     domain;
+
+               domain = CFArrayGetValueAtIndex(val_search_domains, i);
+               if (isA_CFString(domain)) {
+                   SCPrint(TRUE, f, CFSTR(" %@"), domain);
+               }
+           }
+           SCPrint(TRUE, f, CFSTR("\n"));
+       }
+
+       if (isA_CFArray(val_servers)) {
+           n = CFArrayGetCount(val_servers);
+           for (i = 0; i < n; i++) {
+               CFStringRef     nameserver;
+
+               nameserver = CFArrayGetValueAtIndex(val_servers, i);
+               if (isA_CFString(nameserver)) {
+                   SCPrint(TRUE, f, CFSTR("nameserver %@\n"), nameserver);
+               }
+           }
+       }
+
+       if (isA_CFArray(val_sortlist)) {
+           SCPrint(TRUE, f, CFSTR("sortlist"));
+           n = CFArrayGetCount(val_sortlist);
+           for (i = 0; i < n; i++) {
+               CFStringRef     address;
+
+               address = CFArrayGetValueAtIndex(val_sortlist, i);
+               if (isA_CFString(address)) {
+                   SCPrint(TRUE, f, CFSTR(" %@"), address);
+               }
+           }
+           SCPrint(TRUE, f, CFSTR("\n"));
+       }
+
+       fclose(f);
+       rename(VAR_RUN_RESOLV_CONF "-", VAR_RUN_RESOLV_CONF);
+    }
+    return;
+}
+
+static void
+set_netinfo(CFDictionaryRef dict)
+{
+    int fd = open(VAR_RUN_NICONFIG_LOCAL_XML "-",
+                 O_CREAT|O_TRUNC|O_WRONLY, 0644);
+    if (fd >= 0) {
+       /* publish new netinfo config */
+       CFDataRef       contents;
+       contents = CFPropertyListCreateXMLData(NULL, dict);
+       if (contents) {
+           CFIndex     len = CFDataGetLength(contents);
+
+           write(fd, CFDataGetBytePtr(contents), len);
+           CFRelease(contents);
+       }
+       close(fd);
+       rename(VAR_RUN_NICONFIG_LOCAL_XML "-", VAR_RUN_NICONFIG_LOCAL_XML);
+    }
+    return;
+}
+
+static boolean_t
+router_is_our_ipv6_address(CFStringRef router, CFArrayRef addr_list)
+{
+    CFIndex            i;
+    CFIndex            n = CFArrayGetCount(addr_list);
+    struct in6_addr    r;
+
+    (void)cfstring_to_ip6(router, &r);
+    for (i = 0; i < n; i++) {
+       struct in6_addr ip;
+
+       if (cfstring_to_ip6(CFArrayGetValueAtIndex(addr_list, i), &ip)
+           && bcmp(&r, &ip, sizeof(r)) == 0) {
+           return (TRUE);
+       }
+    }
+    return (FALSE);
+}
+
+static void
+update_ipv4(SCDynamicStoreRef session, CFDictionaryRef service_info,
+           CFStringRef primary, keyChangeListRef keys)
+{
+    CFDictionaryRef    ipv4_dict = NULL;
+
+    if (primary != NULL) {
+       CFDictionaryRef         service_dict;
+
+       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+       if (service_dict != NULL) {
+           ipv4_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+       }
+    }
+    if (ipv4_dict != NULL) {
+       CFMutableDictionaryRef  dict = NULL;
+       CFStringRef             if_name = NULL;
+       char                    ifn[IFNAMSIZ + 1] = { '\0' };
+       char *                  ifn_p = NULL;
+       boolean_t               is_direct = FALSE;
+       struct in_addr          local_ip = { 0 };
+       CFStringRef             val_router = NULL;
+       struct in_addr          router = { 0 };
+
+       dict = CFDictionaryCreateMutable(NULL, 0,
+                                        &kCFTypeDictionaryKeyCallBacks,
+                                        &kCFTypeDictionaryValueCallBacks);
+       val_router = CFDictionaryGetValue(ipv4_dict, kSCPropNetIPv4Router);
+       if (val_router != NULL) {
+           cfstring_to_ip(val_router, &router);
+           CFDictionarySetValue(dict, kSCPropNetIPv4Router, val_router);
+           if (CFDictionaryContainsKey(ipv4_dict, kRouterIsDirect)) {
+               is_direct = TRUE;
+           }
+           else {
+               CFStringRef             local_ip_str;
+
+               local_ip_str = CFDictionaryGetValue(ipv4_dict,
+                                                   kRouterNeedsLocalIP);
+               if (local_ip_str != NULL) {
+                   cfstring_to_ip(local_ip_str, &local_ip);
+               }
+           }
+       }
+       else {
+           CFArrayRef          addrs;
+
+           addrs = CFDictionaryGetValue(ipv4_dict,
+                                        kSCPropNetIPv4Addresses);
+           val_router = CFArrayGetValueAtIndex(addrs, 0);
+           cfstring_to_ip(val_router, &router);
+           is_direct = TRUE;
+       }
+       if_name = CFDictionaryGetValue(ipv4_dict, kSCPropInterfaceName);
+       if (if_name) {
+           CFDictionarySetValue(dict,
+                                kSCDynamicStorePropNetPrimaryInterface,
+                                if_name);
+           if (CFStringGetCString(if_name, ifn, sizeof(ifn),
+                                  kCFStringEncodingASCII)) {
+               ifn_p = ifn;
+           }
+       }
+       CFDictionarySetValue(dict, kSCDynamicStorePropNetPrimaryService,
+                            primary);
+       keyChangeListSetValue(keys, S_state_global_ipv4, dict);
+       CFRelease(dict);
+
+       /* route add default ... */
+       if (local_ip.s_addr != 0) {
+           struct in_addr      m;
+
+           m.s_addr = htonl(INADDR_BROADCAST);
+           ipv4_subnet_route_add(local_ip, router, m, ifn_p);
+           set_ipv4_router(&local_ip, ifn_p, FALSE);
+           ipv4_default_route_change(router, ifn_p, FALSE);
+           S_router_subnet = router;
+           S_router_subnet_mask = m;
+       }
+       else {
+           set_ipv4_router(&router, ifn_p, is_direct);
+       }
+    }
+    else {
+       keyChangeListRemoveValue(keys, S_state_global_ipv4);
+       set_ipv4_router(NULL, NULL, FALSE);
+    }
+    return;
+}
+
+static void
+update_ipv6(SCDynamicStoreRef session, CFDictionaryRef service_info,
+           CFStringRef primary, keyChangeListRef keys)
+{
+    CFDictionaryRef    ipv6_dict = NULL;
+
+    if (primary != NULL) {
+       CFDictionaryRef         service_dict;
+
+       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+       if (service_dict != NULL) {
+           ipv6_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv6);
+       }
+    }
+    if (ipv6_dict != NULL) {
+       CFArrayRef              addrs;
+       CFMutableDictionaryRef  dict = NULL;
+       CFStringRef             if_name = NULL;
+       char                    ifn[IFNAMSIZ + 1] = { '\0' };
+       char *                  ifn_p = NULL;
+       boolean_t               is_direct = FALSE;
+       CFStringRef             val_router = NULL;
+
+       dict = CFDictionaryCreateMutable(NULL, 0,
+                                        &kCFTypeDictionaryKeyCallBacks,
+                                        &kCFTypeDictionaryValueCallBacks);
+       val_router = CFDictionaryGetValue(ipv6_dict, kSCPropNetIPv6Router);
+       addrs = CFDictionaryGetValue(ipv6_dict,
+                                    kSCPropNetIPv6Addresses);
+       if (val_router != NULL) {
+           /* no router if router is one of our IP addresses */
+           is_direct = router_is_our_ipv6_address(val_router, addrs);
+           CFDictionarySetValue(dict, kSCPropNetIPv6Router,
+                                val_router);
+       }
+       else {
+           val_router = CFArrayGetValueAtIndex(addrs, 0);
+           is_direct = TRUE;
+       }
+       if_name = CFDictionaryGetValue(ipv6_dict, kSCPropInterfaceName);
+       if (if_name) {
+           CFDictionarySetValue(dict,
+                                kSCDynamicStorePropNetPrimaryInterface,
+                                if_name);
+           if (CFStringGetCString(if_name, ifn, sizeof(ifn),
+                                  kCFStringEncodingASCII)) {
+               ifn_p = ifn;
+           }
+       }
+       CFDictionarySetValue(dict, kSCDynamicStorePropNetPrimaryService,
+                            primary);
+       keyChangeListSetValue(keys, S_state_global_ipv6, dict);
+       CFRelease(dict);
+
+       { /* route add default ... */
+           struct in6_addr     router;
+
+           (void)cfstring_to_ip6(val_router, &router);
+           set_ipv6_router(&router, ifn_p, is_direct);
+       }
+    }
+    else {
+       keyChangeListRemoveValue(keys, S_state_global_ipv6);
+       set_ipv6_router(NULL, NULL, FALSE);
+    }
+    return;
+}
+
+static void
+update_dns(SCDynamicStoreRef session, CFDictionaryRef service_info,
+          CFStringRef primary, keyChangeListRef keys)
+{
+    CFDictionaryRef            dict = NULL;
+
+    if (primary != NULL) {
+       CFDictionaryRef         service_dict;
+
+       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+       if (service_dict != NULL) {
+           dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
+       }
+    }
+    if (dict == NULL) {
+       empty_dns();
+       keyChangeListRemoveValue(keys, S_state_global_dns);
+    }
+    else {
+       set_dns(CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains),
+               CFDictionaryGetValue(dict, kSCPropNetDNSDomainName),
+               CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses),
+               CFDictionaryGetValue(dict, kSCPropNetDNSSortList));
+       keyChangeListSetValue(keys, S_state_global_dns, dict);
+    }
+    return;
+}
+
+static void
+update_dnsinfo(CFStringRef primary, CFArrayRef service_order, keyChangeListRef keys)
+{
+    CFDictionaryRef            dict = NULL;
+
+    if (primary != NULL) {
+       CFDictionaryRef         service_dict;
+
+       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+       if (service_dict != NULL) {
+           dict = CFDictionaryGetValue(service_dict, kSCEntNetDNS);
+       }
+    }
+    if (dict == NULL) {
+       /* update DNS configuration */
+       dns_configuration_set(NULL, NULL, NULL);
+    }
+    else {
+       /* update DNS configuration */
+       dns_configuration_set(dict, S_service_state_dict, service_order);
+    }
+    keyChangeListNotifyKey(keys, S_notify_dnsinfo);
+    return;
+}
+
+static void
+update_netinfo(SCDynamicStoreRef session, CFDictionaryRef service_info,
+              CFStringRef primary, keyChangeListRef keys)
+{
+    CFDictionaryRef    dict = NULL;
+
+    if (primary != NULL) {
+       CFDictionaryRef         ipv4_dict = NULL;
+       CFDictionaryRef         service_dict;
+       CFDictionaryRef         setup_dict;
+       CFStringRef             state_key;
+       CFDictionaryRef         state_dict;
+
+       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+       if (service_dict != NULL) {
+           ipv4_dict = CFDictionaryGetValue(service_dict, kSCEntNetIPv4);
+       }
+       state_key = state_service_key(primary, kSCEntNetNetInfo);
+       state_dict = my_CFDictionaryGetDictionary(service_info, state_key);
+       if (state_dict != NULL) {
+           CFRetain(state_dict);
+       }
+       else {
+           state_dict = my_SCDCopy(session, state_key);
+       }
+       setup_dict = my_CFDictionaryGetDictionary(service_info,
+                                                 S_setup_global_netinfo);
+       dict = make_netinfo_dict(state_dict, setup_dict, ipv4_dict);
+       my_CFRelease(&state_key);
+       my_CFRelease(&state_dict);
+    }
+    if (dict == NULL) {
+       empty_netinfo(session);
+       keyChangeListRemoveValue(keys, S_state_global_netinfo);
+    }
+    else {
+       set_netinfo(dict);
+       keyChangeListSetValue(keys, S_state_global_netinfo, dict);
+       my_CFRelease(&dict);
+    }
+    return;
+}
+
+static void
+update_proxies(SCDynamicStoreRef session, CFDictionaryRef service_info,
+              CFStringRef primary, keyChangeListRef keys)
+{
+    CFDictionaryRef            dict = NULL;
+
+    if (primary != NULL) {
+       CFDictionaryRef                 service_dict;
+       service_dict = CFDictionaryGetValue(S_service_state_dict, primary);
+       if (service_dict != NULL) {
+           dict = CFDictionaryGetValue(service_dict, kSCEntNetProxies);
+           if (dict == NULL) {
+               dict = my_CFDictionaryGetDictionary(service_info,
+                                                   S_setup_global_proxies);
+           }
+       }
+    }
+    if (dict == NULL) {
+       keyChangeListRemoveValue(keys, S_state_global_proxies);
+    }
+    else {
+       keyChangeListSetValue(keys, S_state_global_proxies, dict);
+    }
+    return;
+}
+
+static unsigned int
+get_service_rank(CFStringRef proto_key, CFArrayRef order, CFStringRef serviceID)
+{
+    CFDictionaryRef    d;
+    CFIndex            i;
+    CFDictionaryRef    proto_dict;
+
+    if (serviceID == NULL) {
+       goto done;
+    }
+    d = CFDictionaryGetValue(S_service_state_dict, serviceID);
+    if (d == NULL) {
+       goto done;
+    }
+
+    proto_dict = CFDictionaryGetValue(d, proto_key);
+    if (proto_dict) {
+       CFStringRef     if_name;
+       CFNumberRef     override = NULL;
+
+       if_name = CFDictionaryGetValue(proto_dict, kSCPropInterfaceName);
+       if (S_ppp_override_primary == TRUE
+           && if_name != NULL
+           && CFStringHasPrefix(if_name, CFSTR("ppp"))) {
+           /* PPP override: make ppp* look the best */
+           /* Hack: should use interface type, not interface name */
+           return (0);
+       }
+       /* check for the "OverridePrimary" property */
+       override = CFDictionaryGetValue(proto_dict, kSCPropNetOverridePrimary);
+       if (isA_CFNumber(override) != NULL) {
+           int         val = 0;
+
+           CFNumberGetValue(override,  kCFNumberIntType, &val);
+           if (val != 0) {
+               return (0);
+           }
+       }
+    }
+
+    if (serviceID != NULL && order != NULL) {
+       CFIndex n = CFArrayGetCount(order);
+
+       for (i = 0; i < n; i++) {
+           CFStringRef s = isA_CFString(CFArrayGetValueAtIndex(order, i));
+
+           if (s == NULL) {
+               continue;
+           }
+           if (CFEqual(serviceID, s)) {
+               return (i + 1);
+           }
+       }
+    }
+
+ done:
+    return (UINT_MAX);
+}
+
+/**
+ ** Service election:
+ **/
+typedef boolean_t (*routerCheckFunc)(CFStringRef str);
+
+static boolean_t
+check_ipv4_router(CFStringRef router)
+{
+    struct in_addr     ip;
+
+    return (cfstring_to_ip(router, &ip));
+}
+
+static boolean_t
+check_ipv6_router(CFStringRef router)
+{
+    struct in6_addr    ip6;
+
+    return (cfstring_to_ip6(router, &ip6));
+}
+
+struct election_state {
+    routerCheckFunc            router_check;
+    CFStringRef                        proto_key; /* e.g. kSCEntNetIPv4 */
+    CFStringRef                        router_key;/* e.g. kSCPropNetIPv4Router */
+    CFArrayRef                 order;
+    CFStringRef                        new_primary;
+    boolean_t                  new_has_router;
+    unsigned int               new_primary_index;
+};
+
+static void
+elect_protocol(const void * key, const void * value, void * context)
+{
+    struct election_state *    elect_p = (struct election_state *)context;
+    CFDictionaryRef            proto_dict = NULL;
+    CFStringRef                        router;
+    boolean_t                  router_valid = FALSE;
+    CFStringRef                        serviceID = (CFStringRef)key;
+    CFDictionaryRef            service_dict = (CFDictionaryRef)value;
+    unsigned int               service_index;
+
+    proto_dict = CFDictionaryGetValue(service_dict, elect_p->proto_key);
+    if (proto_dict == NULL) {
+       return;
+    }
+    router = CFDictionaryGetValue(proto_dict, elect_p->router_key);
+    router_valid = (*elect_p->router_check)(router);
+    if (router_valid == FALSE && elect_p->new_has_router == TRUE) {
+       /* skip it */
+       return;
+    }
+    service_index
+       = get_service_rank(elect_p->proto_key, elect_p->order, serviceID);
+    if (elect_p->new_primary == NULL
+       || service_index < elect_p->new_primary_index
+       || (router_valid && elect_p->new_has_router == FALSE)) {
+       my_CFRelease(&elect_p->new_primary);
+       elect_p->new_primary = CFRetain(serviceID);
+       elect_p->new_primary_index = service_index;
+       elect_p->new_has_router = router_valid;
+    }
+    return;
+}
+
+static CFStringRef
+elect_new_primary(CFArrayRef order, CFStringRef proto_key,
+                 CFStringRef router_key)
+{
+    struct election_state      elect;
+
+    if (CFEqual(proto_key, kSCEntNetIPv4)) {
+       elect.router_check = check_ipv4_router;
+    }
+    else if (CFEqual(proto_key, kSCEntNetIPv6)) {
+       elect.router_check = check_ipv6_router;
+    }
+    else {
+       return (NULL);
+    }
+    elect.order = order;
+    elect.new_primary = NULL;
+    elect.new_primary_index = 0;
+    elect.new_has_router = FALSE;
+    elect.proto_key = proto_key;
+    elect.router_key = router_key;
+    CFDictionaryApplyFunction(S_service_state_dict, elect_protocol, &elect);
+    return (elect.new_primary);
+}
+
+static uint32_t
+service_changed(CFDictionaryRef services_info, CFStringRef serviceID)
+{
+    uint32_t           changed = 0;
+    int                        i;
+
+    for (i = 0; i < ENTITY_TYPES_COUNT; i++) {
+       GetEntityChangesFuncRef func = entityChangeFunc[i];
+       if ((*func)(serviceID,
+                   get_service_state_entity(services_info, serviceID,
+                                            entityTypeNames[i]),
+                   get_service_setup_entity(services_info, serviceID,
+                                            entityTypeNames[i]),
+                   services_info)) {
+           changed |= (1 << i);
+       }
+    }
+    return (changed);
+}
+
+static CFArrayRef
+service_order_get(CFDictionaryRef services_info)
+{
+    CFArrayRef                 order = NULL;
+    CFNumberRef                        ppp_override = NULL;
+    int                                ppp_val = TRUE;
+    CFDictionaryRef            ipv4_dict = NULL;
+
+    ipv4_dict = my_CFDictionaryGetDictionary(services_info,
+                                            S_setup_global_ipv4);
+    if (ipv4_dict != NULL) {
+       order = CFDictionaryGetValue(ipv4_dict, kSCPropNetServiceOrder);
+       order = isA_CFArray(order);
+
+       /* get ppp override primary */
+       ppp_override = CFDictionaryGetValue(ipv4_dict,
+                                           kSCPropNetPPPOverridePrimary);
+       ppp_override = isA_CFNumber(ppp_override);
+       if (ppp_override != NULL) {
+           CFNumberGetValue(ppp_override, kCFNumberIntType, &ppp_val);
+       }
+       S_ppp_override_primary = (ppp_val != 0) ? TRUE : FALSE;
+    }
+    else {
+       S_ppp_override_primary = TRUE;
+    }
+    return (order);
+}
+
+static boolean_t
+set_new_primary(CFStringRef * primary_p, CFStringRef new_primary,
+               const char * entity)
+{
+    boolean_t          changed = FALSE;
+    CFStringRef                primary = *primary_p;
+
+    if (new_primary != NULL) {
+       if (primary != NULL && CFEqual(new_primary, primary)) {
+           SCLog(S_IPMonitor_debug, LOG_INFO,
+                 CFSTR("IPMonitor: %@ is still primary %s"),
+                 new_primary, entity);
+       }
+       else {
+           my_CFRelease(primary_p);
+           *primary_p = CFRetain(new_primary);
+           SCLog(S_IPMonitor_debug, LOG_INFO,
+                 CFSTR("IPMonitor: %@ is the new primary %s"),
+                 new_primary, entity);
+           changed = TRUE;
+       }
+    }
+    else if (primary != NULL) {
+       SCLog(S_IPMonitor_debug, LOG_INFO,
+             CFSTR("IPMonitor: %@ is no longer primary %s"), primary, entity);
+       my_CFRelease(primary_p);
+       changed = TRUE;
+    }
+    return (changed);
+}
+
+static unsigned int
+rank_service_entity(CFArrayRef order, CFStringRef primary,
+                   CFStringRef proto_key, CFStringRef entity)
+{
+    CFDictionaryRef    dict;
+    dict = service_dict_get(primary, entity);
+    if (dict == NULL) {
+       return (UINT_MAX);
+    }
+    return (get_service_rank(proto_key, order, primary));
+}
+
+static void
+IPMonitorNotify(SCDynamicStoreRef session, CFArrayRef changed_keys,
+               void * not_used)
+{
+    CFIndex            count;
+    boolean_t          dnsinfo_changed = FALSE;
+    boolean_t          global_ipv4_changed = FALSE;
+    boolean_t          global_ipv6_changed = FALSE;
+    keyChangeList      keys;
+    int                        i;
+    CFIndex            n;
+    CFArrayRef         service_order;
+    CFMutableArrayRef  service_changes = NULL;
+    CFDictionaryRef    services_info = NULL;
+
+    count = CFArrayGetCount(changed_keys);
+    if (count == 0) {
+       return;
+    }
+
+    SCLog(S_IPMonitor_debug, LOG_INFO,
+         CFSTR("IPMonitor: changes %@ (%d)"), changed_keys, count);
+
+    keyChangeListInit(&keys);
+    service_changes = CFArrayCreateMutable(NULL, 0,
+                                          &kCFTypeArrayCallBacks);
+    for (i = 0; i < count; i++) {
+       CFStringRef     change = CFArrayGetValueAtIndex(changed_keys, i);
+       if (CFEqual(change, S_setup_global_ipv4)) {
+           global_ipv4_changed = TRUE;
+           global_ipv6_changed = TRUE;
+       }
+       else if (CFEqual(change, S_setup_global_netinfo)) {
+           if (S_primary_ipv4 != NULL) {
+               my_CFArrayAppendUniqueValue(service_changes, S_primary_ipv4);
+           }
+       }
+       else if (CFEqual(change, S_setup_global_proxies)) {
+           if (S_primary_proxies != NULL) {
+               my_CFArrayAppendUniqueValue(service_changes, S_primary_proxies);
+           }
+       }
+       else if (CFStringHasPrefix(change, S_state_service_prefix)) {
+           CFStringRef serviceID = parse_component(change,
+                                                   S_state_service_prefix);
+           if (serviceID) {
+               my_CFArrayAppendUniqueValue(service_changes, serviceID);
+               CFRelease(serviceID);
+           }
+       }
+       else if (CFStringHasPrefix(change, S_setup_service_prefix)) {
+           CFStringRef serviceID = parse_component(change,
+                                                   S_setup_service_prefix);
+           if (serviceID) {
+               my_CFArrayAppendUniqueValue(service_changes, serviceID);
+               CFRelease(serviceID);
+           }
+       }
+    }
+
+    /* grab a snapshot of everything we need */
+    services_info = services_info_copy(session, service_changes);
+    service_order = service_order_get(services_info);
+    if (service_order != NULL) {
+       SCLog(S_IPMonitor_debug, LOG_INFO,
+             CFSTR("IPMonitor: service_order %@ "), service_order);
+    }
+    n = CFArrayGetCount(service_changes);
+    for (i = 0; i < n; i++) {
+       uint32_t        changes;
+       CFStringRef     serviceID;
+       Boolean         wasSupplemental;
+
+       serviceID = CFArrayGetValueAtIndex(service_changes, i);
+       wasSupplemental = dns_has_supplemental(serviceID);
+       changes = service_changed(services_info, serviceID);
+
+       if (S_primary_ipv4 != NULL && CFEqual(S_primary_ipv4, serviceID)) {
+           if ((changes & (1 << kEntityTypeIPv4)) != 0) {
+               update_ipv4(session, services_info, serviceID, &keys);
+               global_ipv4_changed = TRUE;
+           }
+           if ((changes & (1 << kEntityTypeNetInfo)) != 0) {
+               update_netinfo(session, services_info, serviceID, &keys);
+           }
+       }
+       else if ((changes & (1 << kEntityTypeIPv4)) != 0) {
+           global_ipv4_changed = TRUE;
+       }
+       if ((changes & (1 << kEntityTypeIPv6)) != 0) {
+           if (S_primary_ipv6 != NULL && CFEqual(S_primary_ipv6, serviceID)) {
+               update_ipv6(session, services_info, serviceID, &keys);
+           }
+           global_ipv6_changed = TRUE;
+       }
+       if ((changes & (1 << kEntityTypeDNS)) != 0) {
+           if (S_primary_dns != NULL && CFEqual(S_primary_dns, serviceID)) {
+               update_dns(session, services_info, serviceID, &keys);
+               dnsinfo_changed = TRUE;
+           }
+           else if (wasSupplemental || dns_has_supplemental(serviceID)) {
+               dnsinfo_changed = TRUE;
+           }
+       }
+       if ((changes & (1 << kEntityTypeProxies)) != 0) {
+           if (S_primary_proxies != NULL && CFEqual(S_primary_proxies, serviceID)) {
+               update_proxies(session, services_info, serviceID, &keys);
+           }
+       }
+    }
+
+    if (global_ipv4_changed) {
+       CFStringRef new_primary;
+
+       SCLog(S_IPMonitor_debug, LOG_INFO,
+             CFSTR("IPMonitor: IPv4 service election"));
+       new_primary = elect_new_primary(service_order,
+                                       kSCEntNetIPv4, kSCPropNetIPv4Router);
+       if (set_new_primary(&S_primary_ipv4, new_primary, "IPv4")) {
+           update_ipv4(session, services_info, S_primary_ipv4, &keys);
+           update_netinfo(session, services_info, S_primary_ipv4, &keys);
+       }
+       my_CFRelease(&new_primary);
+    }
+    if (global_ipv6_changed) {
+       CFStringRef new_primary;
+
+       SCLog(S_IPMonitor_debug, LOG_INFO,
+             CFSTR("IPMonitor: IPv6 service election"));
+       new_primary = elect_new_primary(service_order,
+                                       kSCEntNetIPv6, kSCPropNetIPv6Router);
+       if (set_new_primary(&S_primary_ipv6, new_primary, "IPv6")) {
+           update_ipv6(session, services_info, S_primary_ipv6, &keys);
+       }
+       my_CFRelease(&new_primary);
+    }
+    if (global_ipv4_changed || global_ipv6_changed) {
+       CFStringRef     new_primary_dns;
+       CFStringRef     new_primary_proxies;
+
+       if (S_primary_ipv4 != NULL && S_primary_ipv6 != NULL) {
+           /* decide between IPv4 and IPv6 */
+           if (rank_service_entity(service_order, S_primary_ipv4,
+                                   kSCEntNetIPv4, kSCEntNetDNS)
+               <= rank_service_entity(service_order, S_primary_ipv6,
+                                      kSCEntNetIPv6, kSCEntNetDNS)) {
+               new_primary_dns = S_primary_ipv4;
+           }
+           else {
+               new_primary_dns = S_primary_ipv6;
+           }
+           if (rank_service_entity(service_order, S_primary_ipv4,
+                                   kSCEntNetIPv4, kSCEntNetProxies)
+               <= rank_service_entity(service_order, S_primary_ipv6,
+                                      kSCEntNetIPv6, kSCEntNetProxies)) {
+               new_primary_proxies = S_primary_ipv4;
+           }
+           else {
+               new_primary_proxies = S_primary_ipv6;
+           }
+
+       }
+       else if (S_primary_ipv6 != NULL) {
+           new_primary_dns = new_primary_proxies = S_primary_ipv6;
+       }
+       else if (S_primary_ipv4 != NULL) {
+           new_primary_dns = new_primary_proxies = S_primary_ipv4;
+       }
+       else {
+           new_primary_dns = new_primary_proxies = NULL;
+       }
+
+       if (set_new_primary(&S_primary_dns, new_primary_dns, "DNS")) {
+           update_dns(session, services_info, S_primary_dns, &keys);
+           dnsinfo_changed = TRUE;
+       }
+       if (set_new_primary(&S_primary_proxies, new_primary_proxies, "Proxies")) {
+           update_proxies(session, services_info, S_primary_proxies, &keys);
+       }
+    }
+    if (dnsinfo_changed) {
+       update_dnsinfo(S_primary_dns, service_order, &keys);
+    }
+    my_CFRelease(&service_changes);
+    my_CFRelease(&services_info);
+    keyChangeListApplyToStore(&keys, session);
+    keyChangeListFree(&keys);
+    return;
+}
+
+static void
+initEntityNames(void)
+{
+    entityTypeNames[0] = kSCEntNetIPv4;        /* 0 */
+    entityTypeNames[1] = kSCEntNetIPv6;        /* 1 */
+    entityTypeNames[2] = kSCEntNetDNS;         /* 2 */
+    entityTypeNames[3] = kSCEntNetNetInfo;     /* 3 */
+    entityTypeNames[4] = kSCEntNetProxies;     /* 4 */
+    return;
+}
+
+static void
+ip_plugin_init()
+{
+    int                        i;
+    CFStringRef                key;
+    CFMutableArrayRef  keys = NULL;
+    CFMutableArrayRef  patterns = NULL;
+    CFRunLoopSourceRef rls = NULL;
+    SCDynamicStoreRef  session = NULL;
+
+    initEntityNames();
+    if (S_netboot_root() != 0) {
+       S_netboot = TRUE;
+    }
+    session = SCDynamicStoreCreate(NULL, CFSTR("IPMonitor"),
+                                  IPMonitorNotify, NULL);
+    if (session == NULL) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR("IPMonitor ip_plugin_init SCDynamicStoreCreate failed: %s"),
+             SCErrorString(SCError()));
+       return;
+    }
+    S_state_global_ipv4
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainState,
+                                                    kSCEntNetIPv4);
+    S_state_global_ipv6
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainState,
+                                                    kSCEntNetIPv6);
+    S_state_global_dns
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainState,
+                                                    kSCEntNetDNS);
+    S_state_global_netinfo
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainState,
+                                                    kSCEntNetNetInfo);
+    S_state_global_proxies
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainState,
+                                                    kSCEntNetProxies);
+    S_setup_global_ipv4
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainSetup,
+                                                    kSCEntNetIPv4);
+    S_setup_global_netinfo
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainSetup,
+                                                    kSCEntNetNetInfo);
+    S_setup_global_proxies
+       = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainSetup,
+                                                    kSCEntNetProxies);
+    S_state_service_prefix
+       = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"),
+                                 kSCDynamicStoreDomainState,
+                                 kSCCompNetwork,
+                                 kSCCompService);
+    S_setup_service_prefix
+       = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@/"),
+                                 kSCDynamicStoreDomainSetup,
+                                 kSCCompNetwork,
+                                 kSCCompService);
+    S_service_state_dict
+       = CFDictionaryCreateMutable(NULL, 0,
+                                   &kCFTypeDictionaryKeyCallBacks,
+                                   &kCFTypeDictionaryValueCallBacks);
+
+    key = CFStringCreateWithCString(NULL,
+                                   dns_configuration_notify_key(),
+                                   kCFStringEncodingASCII);
+    S_notify_dnsinfo = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), key);
+    CFRelease(key);
+
+    keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+    /* register for State: and Setup: per-service notifications */
+    for (i = 0; i < ENTITY_TYPES_COUNT; i++) {
+       key = state_service_key(kSCCompAnyRegex, entityTypeNames[i]);
+       CFArrayAppendValue(patterns, key);
+       CFRelease(key);
+       key = setup_service_key(kSCCompAnyRegex, entityTypeNames[i]);
+       CFArrayAppendValue(patterns, key);
+       CFRelease(key);
+    }
+
+    /* add notifier for setup global netinfo */
+    CFArrayAppendValue(keys, S_setup_global_netinfo);
+
+    /* add notifier for ServiceOrder/PPPOverridePrimary changes for IPv4 */
+    key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                    kSCDynamicStoreDomainSetup,
+                                                    kSCEntNetIPv4);
+    CFArrayAppendValue(keys, key);
+    CFRelease(key);
+
+    if (!SCDynamicStoreSetNotificationKeys(session, keys, patterns)) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR("IPMonitor ip_plugin_init "
+                   "SCDynamicStoreSetNotificationKeys failed: %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+    rls = SCDynamicStoreCreateRunLoopSource(NULL, session, 0);
+    if (rls == NULL) {
+       SCLog(TRUE, LOG_ERR,
+             CFSTR("IPMonitor ip_plugin_init "
+                   "SCDynamicStoreCreateRunLoopSource failed: %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+    CFRelease(rls);
+
+    /* initialize dns configuration */
+    dns_configuration_set(NULL, NULL, NULL);
+    empty_dns();
+    (void)SCDynamicStoreRemoveValue(session, S_state_global_dns);
+
+    /* initialize netinfo state */
+    empty_netinfo(session);
+    (void)SCDynamicStoreRemoveValue(session, S_state_global_netinfo);
+
+  done:
+    my_CFRelease(&keys);
+    my_CFRelease(&patterns);
+    my_CFRelease(&session);
+    return;
+}
+
+__private_extern__
+void
+prime_IPMonitor()
+{
+    /* initialize multicast route */
+    set_ipv4_router(NULL, NULL, FALSE);
+}
+
+__private_extern__
+void
+load_IPMonitor(CFBundleRef bundle, Boolean bundleVerbose)
+{
+    if (bundleVerbose) {
+       S_IPMonitor_debug = 1;
+    }
+
+    dns_configuration_init(bundle);
+    ip_plugin_init();
+
+    load_hostname(S_IPMonitor_debug);
+
+    return;
+}
+
+
+#ifdef  MAIN
+#undef  MAIN
+#include "dns-configuration.c"
+#include "set-hostname.c"
+
+int
+main(int argc, char **argv)
+{
+    _sc_log     = FALSE;
+    _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+    load_IPMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+    prime_IPMonitor();
+    CFRunLoopRun();
+    /* not reached */
+    exit(0);
+    return 0;
+}
+#endif
+
diff --git a/Plugins/IPMonitor/set-hostname.c b/Plugins/IPMonitor/set-hostname.c
new file mode 100644 (file)
index 0000000..b5408f9
--- /dev/null
@@ -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 <ctype.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb_async.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCDynamicStoreCopyDHCPInfo.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>     // for SCLog(), SCPrint()
+
+#include <notify.h>
+
+
+static SCDynamicStoreRef       store           = NULL;
+static CFRunLoopSourceRef      rls             = NULL;
+
+static CFMachPortRef           dnsPort         = NULL;
+static CFRunLoopSourceRef      dnsRLS          = NULL;
+static struct timeval          dnsQueryStart;
+
+static Boolean                 _verbose        = FALSE;
+
+
+/* SPI (from SCNetworkReachability.c) */
+Boolean
+_SC_checkResolverReachability(SCDynamicStoreRef         *storeP,
+                             SCNetworkConnectionFlags  *flags,
+                             Boolean                   *haveDNS,
+                             const char *              nodename);
+
+
+/*
+ * checkResolverReachabilityByAddress()
+ *
+ * Given an IP address, determine whether a reverse DNS query can be issued
+ * using the current network configuration.
+ */
+static Boolean
+checkResolverReachabilityByAddress(SCDynamicStoreRef store, struct sockaddr *sa)
+{
+       SCNetworkConnectionFlags        flags;
+       Boolean                         haveDNS;
+       int                             i;
+       Boolean                         ok              = FALSE;
+       char                            ptr_name[128];
+
+       /*
+        * Ideally, we would have an API that given a local IP
+        * address would return the DNS server(s) that would field
+        * a given PTR query.  Fortunately, we do have an SPI which
+        * which will provide this information given a "name" so we
+        * take the address, convert it into the inverse query name,
+        * and find out which servers should be consulted.
+        */
+
+       switch (sa->sa_family) {
+               case AF_INET : {
+                       union {
+                               in_addr_t       s_addr;
+                               unsigned char   b[4];
+                       } rev;
+                       struct sockaddr_in      *sin    = (struct sockaddr_in *)sa;
+
+                       /*
+                        * build "PTR" query name
+                        *   NNN.NNN.NNN.NNN.in-addr.arpa.
+                        */
+                       rev.s_addr = sin->sin_addr.s_addr;
+                       (void) snprintf(ptr_name, sizeof(ptr_name), "%u.%u.%u.%u.in-addr.arpa.",
+                                       rev.b[3],
+                                       rev.b[2],
+                                       rev.b[1],
+                                       rev.b[0]);
+
+                       break;
+               }
+
+               case AF_INET6 : {
+                       int                     s       = 0;
+                       struct sockaddr_in6     *sin6   = (struct sockaddr_in6 *)sa;
+                       int                     x       = sizeof(ptr_name);
+                       int                     n;
+
+#define        USE_NIBBLE_QUERY
+#ifdef USE_NIBBLE_QUERY
+                       /*
+                        * build IPv6 "nibble" PTR query name (RFC 1886, RFC 3152)
+                        *   N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.ip6.arpa.
+                        */
+                       for (i = sizeof(sin6->sin6_addr) - 1; i >= 0; i--) {
+                               n = snprintf(&ptr_name[s], x, "%x.%x.",
+                                            ( sin6->sin6_addr.s6_addr[i]       & 0xf),
+                                            ((sin6->sin6_addr.s6_addr[i] >> 4) & 0xf));
+                               if ((n == -1) || (n >= x)) {
+                                       goto done;
+                               }
+
+                               s += n;
+                               x -= n;
+                       }
+
+                       n = snprintf(&ptr_name[s], x, "ip6.arpa.");
+                       if ((n == -1) || (n >= x)) {
+                               goto done;
+                       }
+#else  /* USE_NIBBLE_QUERY */
+                       /*
+                        * build IPv6 "bit-string" PTR query name (RFC 2673)
+                        *   \[xNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN].ip6.arpa.
+                        */
+                       n = snprintf(&ptr_name[0], x, "\\[x");
+                       if ((n == -1) || (n >= x)) {
+                               goto done;
+                       }
+
+                       s += n;
+                       x -= n;
+                       for (i = 0; i < 16; i++) {
+                               n = snprintf(&ptr_name[s], x, "%2.2x", sin6->sin6_addr.s6_addr[i]);
+                               if ((n == -1) || (n >= x)) {
+                                       goto done;
+                               }
+
+                               s += n;
+                               x -= n;
+                       }
+
+                       n = snprintf(&ptr_name[s], x, "].ip6.arpa.");
+                       if ((n == -1) || (n >= x)) {
+                               goto done;
+                       }
+#endif /* USE_NIBBLE_QUERY */
+
+                       break;
+               }
+
+               default :
+                       goto done;
+       }
+
+       ok = _SC_checkResolverReachability(&store, &flags, &haveDNS, ptr_name);
+       if (ok) {
+               if (!(flags & kSCNetworkFlagsReachable) ||
+                       (flags & kSCNetworkFlagsConnectionRequired)) {
+                       // if not reachable *OR* connection required
+                       ok = FALSE;
+               }
+       }
+
+    done :
+
+       return ok;
+}
+
+
+#define        HOSTNAME_NOTIFY_KEY     "com.apple.system.hostname"
+
+
+static void
+set_hostname(CFStringRef hostname)
+{
+       if (hostname != NULL) {
+               char    old_name[MAXHOSTNAMELEN];
+               char    new_name[MAXHOSTNAMELEN];
+
+               if (gethostname(old_name, sizeof(old_name)) == -1) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("gethostname() failed: %s"), strerror(errno));
+                       old_name[0] = '\0';
+               }
+
+               if (_SC_cfstring_to_cstring(hostname,
+                                           new_name,
+                                           sizeof(new_name),
+                                           kCFStringEncodingUTF8) == NULL) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("could not convert [new] hostname"));
+                       new_name[0] = '\0';
+               }
+
+               old_name[sizeof(old_name)-1] = '\0';
+               new_name[sizeof(new_name)-1] = '\0';
+               if (strcmp(old_name, new_name) != 0) {
+                       if (sethostname(new_name, strlen(new_name)) == 0) {
+                               uint32_t        status;
+
+                               SCLog(TRUE, LOG_NOTICE,
+                                     CFSTR("setting hostname to \"%s\""),
+                                     new_name);
+
+                               status = notify_post(HOSTNAME_NOTIFY_KEY);
+                               if (status != NOTIFY_STATUS_OK) {
+                                       SCLog(TRUE, LOG_ERR,
+                                             CFSTR("notify_post(" HOSTNAME_NOTIFY_KEY ") failed: error=%lu"),
+                                             status);
+                               }
+                       } else {
+                               SCLog(TRUE, LOG_ERR,
+                                     CFSTR("sethostname(%s, %d) failed: %s"),
+                                     new_name,
+                                     strlen(new_name),
+                                     strerror(errno));
+                       }
+               }
+       }
+
+       return;
+}
+
+
+#define        HOSTCONFIG      "/etc/hostconfig"
+#define HOSTNAME_KEY   "HOSTNAME="
+#define        AUTOMATIC       "-AUTOMATIC-"
+
+#define HOSTNAME_KEY_LEN       (sizeof(HOSTNAME_KEY) - 1)
+
+static CFStringRef
+copy_static_name()
+{
+       FILE *          f;
+       char            buf[256];
+       CFStringRef     name    = NULL;
+
+       f = fopen(HOSTCONFIG, "r");
+       if (f == NULL) {
+               return NULL;
+       }
+
+       while (fgets(buf, sizeof(buf), f) != NULL) {
+               char *  bp;
+               int     n;
+               char *  np;
+               Boolean str_escape;
+               Boolean str_quote;
+
+               n = strlen(buf);
+               if (buf[n-1] == '\n') {
+                       /* the entire line fit in the buffer, remove the newline */
+                       buf[n-1] = '\0';
+               } else {
+                       /* eat the remainder of the line */
+                       do {
+                               n = fgetc(f);
+                       } while ((n != '\n') && (n != EOF));
+               }
+
+               // skip leading white space
+               bp = &buf[0];
+               while (isspace(*bp)) {
+                       bp++;
+               }
+
+               // find "HOSTNAME=" key
+               if (strncmp(bp, HOSTNAME_KEY, HOSTNAME_KEY_LEN) != 0) {
+                       continue;       // if not
+               }
+
+               // get the hostname string
+               bp += HOSTNAME_KEY_LEN;
+               str_escape = FALSE;
+               str_quote  = FALSE;
+
+               np = &buf[0];
+               while (*bp != '\0') {
+                       char    ch = *bp;
+
+                       switch (ch) {
+                               case '\\' :
+                                       if (!str_escape) {
+                                               str_escape = TRUE;
+                                               bp++;
+                                               continue;
+                                       }
+                                       break;
+                               case '"' :
+                                       if (!str_escape) {
+                                               str_quote = !str_quote;
+                                               bp++;
+                                               continue;
+                                       }
+                                       break;
+                               default :
+                                       break;
+                       }
+
+                       if (str_escape) {
+                               str_escape = FALSE;
+                       } else if (!str_quote && (isspace(ch) || (ch == '#'))) {
+                               break;
+                       }
+
+                       *np++ = ch;
+                       bp++;
+               }
+
+               *np = '\0';
+
+               if (name != NULL) {
+                       CFRelease(name);
+                       name = NULL;
+               }
+
+               if (str_quote) {
+                       // the shell won't parse this file so neither will we
+                       break;
+               }
+
+               if (strcmp(buf, AUTOMATIC) == 0) {
+                       // skip "-AUTOMATIC-"
+                       continue;
+               }
+
+               name = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
+       }
+
+       (void) fclose(f);
+       return name;
+}
+
+
+#ifndef        kSCPropNetHostName
+#define        kSCPropNetHostName      CFSTR("HostName")
+#endif
+
+
+static CFStringRef
+copy_prefs_hostname(SCDynamicStoreRef store)
+{
+       CFDictionaryRef         dict;
+       CFStringRef             key;
+       CFStringRef             name            = NULL;
+
+       key  = SCDynamicStoreKeyCreateComputerName(NULL);
+       dict = SCDynamicStoreCopyValue(store, key);
+       CFRelease(key);
+       if (dict == NULL) {
+               goto done;
+       }
+       if (!isA_CFDictionary(dict)) {
+               goto done;
+       }
+
+       name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetHostName));
+       if (name == NULL) {
+               goto done;
+       }
+       CFRetain(name);
+
+    done :
+
+       if (dict != NULL)       CFRelease(dict);
+       
+       return name;
+}
+
+
+static CFStringRef
+copy_primary_service(SCDynamicStoreRef store)
+{
+       CFDictionaryRef dict;
+       CFStringRef     key;
+       CFStringRef     serviceID       = NULL;
+
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetIPv4);
+       dict = SCDynamicStoreCopyValue(store, key);
+       CFRelease(key);
+
+       if (dict != NULL) {
+               if (isA_CFDictionary(dict)) {
+                       serviceID = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryService);
+                       if (isA_CFString(serviceID)) {
+                               CFRetain(serviceID);
+                       } else {
+                               serviceID = NULL;
+                       }
+               }
+               CFRelease(dict);
+       }
+
+       return serviceID;
+}
+
+
+static CFStringRef
+copy_primary_ip(SCDynamicStoreRef store, CFStringRef serviceID)
+{
+       CFDictionaryRef dict;
+       CFStringRef     key;
+       CFStringRef     address = NULL;
+
+       key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                         kSCDynamicStoreDomainState,
+                                                         serviceID,
+                                                         kSCEntNetIPv4);
+       dict = SCDynamicStoreCopyValue(store, key);
+       CFRelease(key);
+
+       if (dict != NULL) {
+               if (isA_CFDictionary(dict)) {
+                       CFArrayRef      addresses;
+
+                       addresses = CFDictionaryGetValue(dict, kSCPropNetIPv4Addresses);
+                       if (isA_CFArray(addresses) && (CFArrayGetCount(addresses) > 0)) {
+                               address = CFArrayGetValueAtIndex(addresses, 0);
+                               if (isA_CFString(address)) {
+                                       CFRetain(address);
+                               } else {
+                                       address = NULL;
+                               }
+                       }
+               }
+               CFRelease(dict);
+       }
+
+       return address;
+}
+
+
+#define        DHCP_OPTION_HOSTNAME    12
+
+static CFStringRef
+copy_dhcp_name(SCDynamicStoreRef store, CFStringRef serviceID)
+{
+       CFDictionaryRef info;
+       CFStringRef     name    = NULL;
+
+       info = SCDynamicStoreCopyDHCPInfo(store, serviceID);
+       if (info != NULL) {
+               CFDataRef       data;
+
+               data = DHCPInfoGetOptionData(info, DHCP_OPTION_HOSTNAME);
+               if (data != NULL) {
+                       name = CFStringCreateFromExternalRepresentation(NULL, data, kCFStringEncodingUTF8);
+               }
+
+               CFRelease(info);
+       }
+
+       return name;
+}
+
+
+static void
+reverseDNSComplete(int32_t status, char *host, char *serv, void *context)
+{
+       struct timeval          dnsQueryComplete;
+       struct timeval          dnsQueryElapsed;
+       CFStringRef             hostname;
+       SCDynamicStoreRef       store   = (SCDynamicStoreRef)context;
+
+       (void) gettimeofday(&dnsQueryComplete, NULL);
+       timersub(&dnsQueryComplete, &dnsQueryStart, &dnsQueryElapsed);
+       SCLog(_verbose, LOG_INFO,
+             CFSTR("async DNS complete%s (query time = %d.%3.3d)"),
+             ((status == 0) && (host != NULL)) ? "" : ", host not found",
+             dnsQueryElapsed.tv_sec,
+             dnsQueryElapsed.tv_usec / 1000);
+
+       // use reverse DNS name, if available
+
+       switch (status) {
+               case 0 :
+                       /*
+                        * if [reverse] DNS query was successful
+                        */
+                       if (host != NULL) {
+                               hostname = CFStringCreateWithCString(NULL, host, kCFStringEncodingUTF8);
+                               SCLog(TRUE, LOG_INFO, CFSTR("hostname (reverse DNS query) = %@"), hostname);
+                               set_hostname(hostname);
+                               CFRelease(hostname);
+                               goto done;
+                       }
+                       break;
+
+               case EAI_NONAME :
+                       /*
+                        * if no name available
+                        */
+                       break;
+
+               default :
+                       /*
+                        * Hmmmm...
+                        */
+                       SCLog(TRUE, LOG_ERR, CFSTR("getnameinfo() failed: %s"), gai_strerror(status));
+       }
+
+       // get local (multicast DNS) name, if available
+
+       hostname = SCDynamicStoreCopyLocalHostName(store);
+       if (hostname != NULL) {
+               CFMutableStringRef      localName;
+
+               SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
+               localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+               CFStringAppend(localName, CFSTR(".local"));
+               set_hostname(localName);
+               CFRelease(localName);
+               CFRelease(hostname);
+               goto done;
+       }
+
+       // use "localhost" if not other name is available
+
+       set_hostname(CFSTR("localhost"));
+
+    done :
+
+       if (host != NULL)       free(host);
+       if (serv != NULL)       free(serv);
+       return;
+}
+
+
+static void
+getnameinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
+{
+       getnameinfo_async_handle_reply(msg);
+
+       if (port == dnsPort) {
+               CFRelease(dnsRLS);
+               dnsRLS = NULL;
+               CFRelease(dnsPort);
+               dnsPort = NULL;
+       }
+
+       return;
+}
+
+
+static void
+start_dns_query(SCDynamicStoreRef store, CFStringRef address)
+{
+       char                    addr[64];
+       Boolean                 ok;
+       struct sockaddr         *sa;
+       struct sockaddr_in      sin;
+       struct sockaddr_in6     sin6;
+
+       if (_SC_cfstring_to_cstring(address, addr, sizeof(addr), kCFStringEncodingASCII) == NULL) {
+               SCLog(TRUE, LOG_ERR, CFSTR("could not convert [primary] address"));
+               return;
+       }
+
+       bzero(&sin, sizeof(sin));
+       sin.sin_len    = sizeof(sin);
+       sin.sin_family = AF_INET;
+
+       bzero(&sin6, sizeof(sin6));
+       sin6.sin6_len    = sizeof(sin6);
+       sin6.sin6_family = AF_INET6;
+
+       if (inet_aton(addr, &sin.sin_addr) == 1) {
+               /*
+                * if IPv4 address
+                */
+               sa = (struct sockaddr *)&sin;
+       } else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr) == 1) {
+               /*
+                * if IPv6 address
+                */
+               char    *p;
+
+               p = strchr(addr, '%');
+               if (p != NULL) {
+                       sin6.sin6_scope_id = if_nametoindex(p+1);
+               }
+
+               sa = (struct sockaddr *)&sin6;
+       } else {
+               goto done;
+       }
+
+       ok = checkResolverReachabilityByAddress(store, sa);
+       if (ok) {
+               CFMachPortContext       context = { 0, (void *)store, CFRetain, CFRelease, CFCopyDescription };
+               mach_port_t             port;
+               int32_t                 error;
+
+               if ((dnsPort != NULL) && (dnsRLS != NULL)) {
+                       /* if we already have an active async DNS query */
+                       lu_async_call_cancel(CFMachPortGetPort(dnsPort));
+                       CFRelease(dnsRLS);
+                       dnsRLS = NULL;
+                       CFRelease(dnsPort);
+                       dnsPort = NULL;
+               }
+
+               (void) gettimeofday(&dnsQueryStart, NULL);
+
+               error = getnameinfo_async_start(&port,
+                                               sa,
+                                               sa->sa_len,
+                                               0,              // flags
+                                               reverseDNSComplete,
+                                               NULL);
+               if (error != 0) {
+                       goto done;
+               }
+
+               dnsPort = CFMachPortCreateWithPort(NULL,
+                                                  port,
+                                                  getnameinfo_async_handleCFReply,
+                                                  &context,
+                                                  NULL);
+               dnsRLS = CFMachPortCreateRunLoopSource(NULL, dnsPort, 0);
+               CFRunLoopAddSource(CFRunLoopGetCurrent(), dnsRLS, kCFRunLoopDefaultMode);
+       }
+
+    done :
+
+       return;
+}
+
+
+static void
+update_hostname(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+       CFStringRef     address         = NULL;
+       CFStringRef     hostname        = NULL;
+       CFStringRef     serviceID       = NULL;
+
+       // get static hostname, if available
+
+       hostname = copy_static_name();
+       if (hostname != NULL) {
+               SCLog(TRUE, LOG_INFO, CFSTR("hostname (static) = %@"), hostname);
+               set_hostname(hostname);
+               goto done;
+       }
+
+       // get [prefs] hostname, if available
+
+       hostname = copy_prefs_hostname(store);
+       if (hostname != NULL) {
+               SCLog(TRUE, LOG_INFO, CFSTR("hostname (prefs) = %@"), hostname);
+               set_hostname(hostname);
+               goto done;
+       }
+
+       // get primary service ID
+
+       serviceID = copy_primary_service(store);
+       if (serviceID == NULL) {
+               goto mDNS;
+       }
+
+       // get DHCP provided name, if available
+
+       hostname = copy_dhcp_name(store, serviceID);
+       if (hostname != NULL) {
+               SCLog(TRUE, LOG_INFO, CFSTR("hostname (DHCP) = %@"), hostname);
+               set_hostname(hostname);
+               goto done;
+       }
+
+       // get DNS name associated with primary IP, if available
+
+       address = copy_primary_ip(store, serviceID);
+       if (address != NULL) {
+               // start reverse DNS query using primary IP address
+               (void) start_dns_query(store, address);
+               goto done;
+       }
+
+    mDNS :
+
+       // get local (multicast DNS) name, if available
+
+       hostname = SCDynamicStoreCopyLocalHostName(store);
+       if (hostname != NULL) {
+               CFMutableStringRef      localName;
+
+               SCLog(TRUE, LOG_INFO, CFSTR("hostname (multicast DNS) = %@"), hostname);
+               localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+               CFStringAppend(localName, CFSTR(".local"));
+               set_hostname(localName);
+               CFRelease(localName);
+               goto done;
+       }
+
+       // use "localhost" if not other name is available
+
+       set_hostname(CFSTR("localhost"));
+
+    done :
+
+       if (address)    CFRelease(address);
+       if (hostname)   CFRelease(hostname);
+       if (serviceID)  CFRelease(serviceID);
+
+       return;
+}
+
+
+__private_extern__
+void
+load_hostname(Boolean verbose)
+{
+       CFStringRef             key;
+       CFMutableArrayRef       keys            = NULL;
+       CFMutableArrayRef       patterns        = NULL;
+
+       if (verbose) {
+               _verbose = TRUE;
+       }
+
+       /* initialize a few globals */
+
+       store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), update_hostname, NULL);
+       if (store == NULL) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreCreate() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       /* establish notification keys and patterns */
+
+       keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       /* ...watch for primary service / interface changes */
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetIPv4);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       /* ...watch for DNS configuration changes */
+       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+                                                        kSCDynamicStoreDomainState,
+                                                        kSCEntNetDNS);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       /* ...watch for (per-service) DHCP option changes */
+       key = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
+                                                         kSCDynamicStoreDomainState,
+                                                         kSCCompAnyRegex,
+                                                         kSCEntNetDHCP);
+       CFArrayAppendValue(patterns, key);
+       CFRelease(key);
+
+       /* ...watch for (BSD) hostname changes */
+       key = SCDynamicStoreKeyCreateComputerName(NULL);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       /* ...watch for local (multicast DNS) hostname changes */
+       key = SCDynamicStoreKeyCreateHostNames(NULL);
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       /* register the keys/patterns */
+       if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreSetNotificationKeys() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+       if (!rls) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+
+       CFRelease(keys);
+       CFRelease(patterns);
+       return;
+
+    error :
+
+       if (keys != NULL)       CFRelease(keys);
+       if (patterns != NULL)   CFRelease(patterns);
+       if (store != NULL)      CFRelease(store);
+       return;
+}
+
+
+#ifdef MAIN
+int
+main(int argc, char **argv)
+{
+
+#ifdef DEBUG
+
+       _sc_log = FALSE;
+       if ((argc > 1) && (strcmp(argv[1], "-d") == 0)) {
+               _sc_verbose = TRUE;
+               argv++;
+               argc--;
+       }
+
+       CFStringRef             address;
+       CFStringRef             hostname;
+       CFStringRef             serviceID;
+       SCDynamicStoreRef       store;
+
+       store = SCDynamicStoreCreate(NULL, CFSTR("set-hostname"), NULL, NULL);
+       if (store == NULL) {
+               SCPrint(TRUE, stdout,
+                       CFSTR("SCDynamicStoreCreate() failed: %s\n"),
+                       SCErrorString(SCError()));
+               exit(1);
+       }
+
+       // get static hostname
+       hostname = copy_static_name();
+       if (hostname != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("hostname (static) = %@\n"), hostname);
+               CFRelease(hostname);
+       }
+
+       // get [prefs] hostname, if available
+       hostname = copy_prefs_hostname(store);
+       if (hostname != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("hostname (prefs) = %@\n"), hostname);
+               CFRelease(hostname);
+       }
+
+       // get primary service
+       serviceID = copy_primary_service(store);
+       if (serviceID != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("primary service ID = %@\n"), serviceID);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("No primary service\n"));
+               goto mDNS;
+       }
+
+       if ((argc == (2+1)) && (argv[1][0] == 's')) {
+               if (serviceID != NULL)  CFRelease(serviceID);
+               serviceID = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
+               SCPrint(TRUE, stdout, CFSTR("alternate service ID = %@\n"), serviceID);
+       }
+
+       // get DHCP provided name
+       hostname = copy_dhcp_name(store, serviceID);
+       if (hostname != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("hostname (DHCP) = %@\n"), hostname);
+               CFRelease(hostname);
+       }
+
+       // get primary IP address
+       address = copy_primary_ip(store, serviceID);
+       if (address != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("primary address = %@\n"), address);
+
+               if ((argc == (2+1)) && (argv[1][0] == 'a')) {
+                       if (address != NULL)    CFRelease(address);
+                       address = CFStringCreateWithCString(NULL, argv[2], kCFStringEncodingUTF8);
+                       SCPrint(TRUE, stdout, CFSTR("alternate primary address = %@\n"), address);
+               }
+
+               // start reverse DNS query using primary IP address
+               start_dns_query(store, address);
+               CFRelease(address);
+       }
+
+       CFRelease(serviceID);
+
+    mDNS :
+
+       // get local (multicast DNS) name, if available
+
+       hostname = SCDynamicStoreCopyLocalHostName(store);
+       if (hostname != NULL) {
+               CFMutableStringRef      localName;
+
+               SCPrint(TRUE, stdout, CFSTR("hostname (multicast DNS) = %@\n"), hostname);
+               localName = CFStringCreateMutableCopy(NULL, 0, hostname);
+               CFStringAppend(localName, CFSTR(".local"));
+               CFRelease(localName);
+       }
+
+       if (hostname != NULL)   CFRelease(hostname);
+
+       update_hostname(store, NULL, NULL);
+
+       CFRelease(store);
+
+       CFRunLoopRun();
+
+#else  /* DEBUG */
+
+       _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+       load_hostname((argc > 1) ? TRUE : FALSE);
+       CFRunLoopRun();
+       /* not reached */
+
+#endif /* DEBUG */
+
+       exit(0);
+       return 0;
+}
+#endif /* MAIN */
diff --git a/Plugins/InterfaceNamer/Info.plist b/Plugins/InterfaceNamer/Info.plist
new file mode 100644 (file)
index 0000000..69db34e
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>InterfaceNamer</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Builtin</key>
+       <true/>
+</dict>
+</plist>
diff --git a/Plugins/InterfaceNamer/ifnamer.c b/Plugins/InterfaceNamer/ifnamer.c
new file mode 100644 (file)
index 0000000..a0a9620
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - sort new interfaces by IOKit path (rather than MAC address) to
+ *   help facilitate a more predictable interface-->name mapping for
+ *   like hardware configurations.
+ *
+ * June 23, 2001               Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * January 23, 2001            Dieter Siegmund <dieter@apple.com>
+ * - initial revision
+ */
+
+/*
+ * ifnamer.c
+ * - module that receives IOKit Network Interface messages
+ *   and names any interface that currently does not have a name
+ * - uses Interface Type and MACAddress as the unique identifying
+ *   keys; any interface that doesn't contain both of these properties
+ *   is ignored and not processed
+ * - stores the Interface Type, MACAddress, and Unit in permanent storage
+ *   to give persistent interface names
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/sockio.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <mach/mach.h>
+#include <net/if_types.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCDPlugin.h>
+#include <SystemConfiguration/SCPrivate.h>     // for SCLog(), SCPrint()
+#include <SystemConfiguration/SCValidation.h>
+
+#include <SystemConfiguration/BondConfiguration.h>
+#include <SystemConfiguration/BondConfigurationPrivate.h>
+
+#include <SystemConfiguration/VLANConfiguration.h>
+#include <SystemConfiguration/VLANConfigurationPrivate.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/network/IONetworkController.h>
+#include <IOKit/network/IONetworkInterface.h>
+
+#ifndef        kIOBuiltin
+#define        kIOBuiltin                      "IOBuiltin"
+#endif
+
+#ifndef        kIOLocation
+#define        kIOLocation                     "IOLocation"
+#endif
+
+#define kIONetworkStackUserCommand     "IONetworkStackUserCommand"
+#define kIORegisterOne                 1
+
+#define MY_PLUGIN_NAME                 "InterfaceNamer"
+
+static boolean_t                       S_debug = FALSE;
+static CFMutableArrayRef               S_dblist = NULL;
+static io_connect_t                    S_connect = MACH_PORT_NULL;
+static io_iterator_t                   S_iter = MACH_PORT_NULL;
+static IONotificationPortRef           S_notify = NULL;
+
+static void
+writeInterfaceList(CFArrayRef ilist);
+
+static void
+displayInterface(CFDictionaryRef if_dict);
+
+static CFDictionaryRef
+lookupIOKitPath(CFStringRef if_path);
+
+static __inline__ CFComparisonResult
+compareMacAddress(CFDataRef addr1, CFDataRef addr2)
+{
+    int len1;
+    int len2;
+    int clen;
+    int res;
+
+    len1 = CFDataGetLength(addr1);
+    len2 = CFDataGetLength(addr2);
+
+    if (len1 == len2) {
+       if (len1 == 0)
+           return (kCFCompareEqualTo);
+       return (memcmp(CFDataGetBytePtr(addr1),
+                      CFDataGetBytePtr(addr2),
+                      len1));
+    }
+    clen = len1;
+    if (len2 < clen)
+       clen = len2;
+    res = memcmp(CFDataGetBytePtr(addr1),
+                CFDataGetBytePtr(addr2),
+                clen);
+    if (res == 0) {
+       return (len1 - len2);
+    }
+    return (res);
+}
+
+static CFComparisonResult
+if_unit_compare(const void *val1, const void *val2, void *context)
+{
+    CFComparisonResult res;
+    CFNumberRef                type1;
+    CFNumberRef                type2;
+    CFNumberRef                unit1;
+    CFNumberRef                unit2;
+
+    type1 = CFDictionaryGetValue((CFDictionaryRef)val1,
+                                CFSTR(kIOInterfaceType));
+    type2 = CFDictionaryGetValue((CFDictionaryRef)val2,
+                                CFSTR(kIOInterfaceType));
+    res = CFNumberCompare(type1, type2, NULL);
+    if (res != kCFCompareEqualTo) {
+       return (res);
+    }
+    unit1 = CFDictionaryGetValue((CFDictionaryRef)val1,
+                                CFSTR(kIOInterfaceUnit));
+    unit2 = CFDictionaryGetValue((CFDictionaryRef)val2,
+                                CFSTR(kIOInterfaceUnit));
+    return (CFNumberCompare(unit1, unit2, NULL));
+}
+
+static CFArrayRef
+split_path(CFStringRef path)
+{
+       CFArrayRef              components;
+       CFMutableStringRef      nPath;
+
+       // turn '@'s into '/'s
+       nPath = CFStringCreateMutableCopy(NULL, 0, path);
+       (void) CFStringFindAndReplace(nPath,
+                                     CFSTR("@"),
+                                     CFSTR("/"),
+                                     CFRangeMake(0, CFStringGetLength(nPath)),
+                                     0);
+
+       // split path into components to be compared
+       components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
+       CFRelease(nPath);
+
+       return components;
+}
+
+
+static CFComparisonResult
+if_path_compare(const void *val1, const void *val2, void *context)
+{
+    CFBooleanRef       builtin;
+    Boolean            builtin_val1    = FALSE;
+    Boolean            builtin_val2    = FALSE;
+    CFArrayRef         elements1       = NULL;
+    CFArrayRef         elements2       = NULL;
+    CFIndex            i;
+    CFIndex            n;
+    CFIndex            n1              = 0;
+    CFIndex            n2              = 0;
+    CFStringRef                path;
+    CFComparisonResult res;
+    CFNumberRef                type1;
+    CFNumberRef                type2;
+
+    /* sort by interface type */
+
+    type1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOInterfaceType));
+    type2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOInterfaceType));
+    res = CFNumberCompare(type1, type2, NULL);
+    if (res != kCFCompareEqualTo) {
+       return (res);
+    }
+
+    /* built-in interfaces sort first */
+    builtin = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOBuiltin));
+    if (isA_CFBoolean(builtin) != NULL) {
+       builtin_val1 = CFBooleanGetValue(builtin);
+    }
+    builtin = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOBuiltin));
+    if (isA_CFBoolean(builtin) != NULL) {
+       builtin_val2 = CFBooleanGetValue(builtin);
+    }
+    if (builtin_val1 != builtin_val2) {
+       if (builtin_val1) {
+           res = kCFCompareLessThan;
+       } else {
+           res = kCFCompareGreaterThan;
+       }
+       return (res);
+    }
+
+    /* ... and then sort built-in interfaces by "location" */
+    if (builtin_val1) {
+       CFStringRef     location1;
+       CFStringRef     location2;
+
+       location1 = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOLocation));
+       location2 = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOLocation));
+       if (location1 != location2) {
+           if (isA_CFString(location1)) {
+               if (isA_CFString(location2)) {
+                   res = CFStringCompare(location1, location2, 0);
+               } else {
+                   res = kCFCompareLessThan;
+               }
+           } else {
+               res = kCFCompareGreaterThan;
+           }
+
+           if (res != kCFCompareEqualTo) {
+               return (res);
+           }
+       }
+    }
+
+    /* ... and then sort by IOPathMatch */
+
+    path = CFDictionaryGetValue((CFDictionaryRef)val1, CFSTR(kIOPathMatchKey));
+    if (isA_CFString(path)) {
+       elements1 = split_path(path);
+       n1 = CFArrayGetCount(elements1);
+    } else {
+       goto done;
+    }
+
+    path = CFDictionaryGetValue((CFDictionaryRef)val2, CFSTR(kIOPathMatchKey));
+    if (isA_CFString(path)) {
+       elements2 = split_path(path);
+       n2 = CFArrayGetCount(elements2);
+    } else {
+       goto done;
+    }
+
+    n = (n1 <= n2) ? n1 : n2;
+    for (i = 0; i < n; i++) {
+       CFStringRef     e1;
+       CFStringRef     e2;
+       char            *end;
+       quad_t          q1;
+       quad_t          q2;
+       char            *str;
+       Boolean         isNum;
+
+       e1 = CFArrayGetValueAtIndex(elements1, i);
+       e2 = CFArrayGetValueAtIndex(elements2, i);
+
+       str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingASCII);
+       errno = 0;
+       q1 = strtoq(str, &end, 16);
+       isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+       CFAllocatorDeallocate(NULL, str);
+
+       if (isNum) {
+           // if e1 is a valid numeric string
+           str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingASCII);
+           errno = 0;
+           q2 = strtoq(str, &end, 16);
+           isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+           CFAllocatorDeallocate(NULL, str);
+
+           if (isNum) {
+               // if e2 is also a valid numeric string
+
+               if (q1 == q2) {
+                   res = kCFCompareEqualTo;
+                   continue;
+               } else if (q1 < q2) {
+                   res = kCFCompareLessThan;
+               } else {
+                   res = kCFCompareGreaterThan;
+               }
+               break;
+           }
+       }
+
+       res = CFStringCompare(e1, e2, 0);
+       if (res != kCFCompareEqualTo) {
+           break;
+       }
+    }
+
+    if (res == kCFCompareEqualTo) {
+       if (n1 < n2) {
+           res = kCFCompareLessThan;
+       } else if (n1 < n2) {
+           res = kCFCompareGreaterThan;
+       }
+    }
+
+ done :
+    if ( elements1 ) CFRelease( elements1 );
+    if ( elements2 ) CFRelease( elements2 );
+
+    return res;
+}
+
+static boolean_t
+addCFStringProperty( CFMutableDictionaryRef dict,
+                    const char *           key,
+                    const char *           string )
+{
+    boolean_t    ret = false;
+    CFStringRef  valObj, keyObj;
+
+    if ( (string == 0) || (key == 0) || (dict == 0) )
+       return false;
+
+    keyObj = CFStringCreateWithCString(NULL,
+                                      key,
+                                      kCFStringEncodingASCII );
+
+    valObj = CFStringCreateWithCString(NULL,
+                                      string,
+                                      kCFStringEncodingASCII );
+
+    if (valObj && keyObj) {
+       CFDictionarySetValue( dict, keyObj, valObj );
+       ret = true;
+    }
+
+    if ( keyObj ) CFRelease( keyObj );
+    if ( valObj ) CFRelease( valObj );
+
+    return ret;
+}
+
+static boolean_t
+addCFNumberProperty( CFMutableDictionaryRef dict,
+                    const char *           key,
+                    unsigned int           number )
+{
+    boolean_t    ret = false;
+    CFNumberRef  numObj;
+    CFStringRef  keyObj;
+
+    if ( (key == 0) || (dict == 0) )
+       return false;
+
+    numObj = CFNumberCreate(NULL,
+                           kCFNumberLongType,
+                           &number);
+
+    keyObj = CFStringCreateWithCString(NULL,
+                                      key,
+                                      kCFStringEncodingASCII );
+
+    if ( numObj && keyObj )
+       {
+           CFDictionarySetValue( dict, keyObj, numObj );
+           ret = true;
+       }
+
+    if ( numObj ) CFRelease( numObj );
+    if ( keyObj ) CFRelease( keyObj );
+
+    return ret;
+}
+
+static void *
+read_file(char * filename, size_t * data_length)
+{
+    void *             data = NULL;
+    size_t             len = 0;
+    int                        fd = -1;
+    struct stat                sb;
+
+    *data_length = 0;
+    if (stat(filename, &sb) < 0)
+       goto done;
+    len = sb.st_size;
+    if (len == 0)
+       goto done;
+
+    data = malloc(len);
+    if (data == NULL)
+       goto done;
+
+    fd = open(filename, O_RDONLY);
+    if (fd < 0)
+       goto done;
+
+    if (read(fd, data, len) != len) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": read %s failed, %s"),
+             filename, strerror(errno));
+       goto done;
+    }
+ done:
+    if (fd >= 0)
+       close(fd);
+    if (data) {
+       *data_length = len;
+    }
+    return (data);
+}
+
+static CFPropertyListRef
+readPropertyList(char * filename)
+{
+    void *             buf;
+    size_t             bufsize;
+    CFDataRef          data = NULL;
+    CFPropertyListRef  plist = NULL;
+    CFStringRef                errorString = NULL;
+
+    buf = read_file(filename, &bufsize);
+    if (buf == NULL) {
+       return (NULL);
+    }
+    data = CFDataCreate(NULL, buf, bufsize);
+    if (data == NULL) {
+       goto error;
+    }
+
+    plist = CFPropertyListCreateFromXMLData(NULL, data,
+                                           kCFPropertyListMutableContainers,
+                                           &errorString);
+    if (plist == NULL) {
+       if (errorString) {
+           SCLog(TRUE, LOG_INFO,
+                 CFSTR(MY_PLUGIN_NAME ":%@"),
+                 errorString);
+           CFRelease(errorString);
+       }
+    }
+ error:
+    if (data)
+       CFRelease(data);
+    if (buf)
+       free(buf);
+    return (plist);
+}
+
+#define        IFNAMER_ID                      CFSTR("com.apple.SystemConfiguration.InterfaceNamer")
+#define        INTERFACES                      CFSTR("Interfaces")
+#define        NETWORK_INTERFACES_PREFS        CFSTR("NetworkInterfaces.plist")
+#define        OLD_NETWORK_INTERFACES_FILE     "/var/db/NetworkInterfaces.xml"
+
+static CFMutableArrayRef
+readInterfaceList()
+{
+    CFArrayRef         ilist;
+    CFMutableArrayRef  plist = NULL;
+    SCPreferencesRef   prefs = NULL;
+
+    prefs = SCPreferencesCreate(NULL, IFNAMER_ID, NETWORK_INTERFACES_PREFS);
+    if (!prefs) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
+             SCErrorString(SCError()));
+       return (NULL);
+    }
+
+    ilist = SCPreferencesGetValue(prefs, INTERFACES);
+    if (isA_CFArray(ilist)) {
+       plist = CFArrayCreateMutableCopy(NULL, 0, ilist);
+    } else {
+       plist = (CFMutableArrayRef)readPropertyList(OLD_NETWORK_INTERFACES_FILE);
+       if (plist == NULL) {
+           goto done;
+       }
+       if (isA_CFArray(plist) == NULL) {
+           CFRelease(plist);
+           goto done;
+       }
+       writeInterfaceList(plist);
+       (void)unlink(OLD_NETWORK_INTERFACES_FILE);
+    }
+
+  done:
+    if (prefs) {
+       CFRelease(prefs);
+    }
+    return (plist);
+}
+
+static void
+writeInterfaceList(CFArrayRef ilist)
+{
+    SCPreferencesRef   prefs;
+
+    if (isA_CFArray(ilist) == NULL) {
+       return;
+    }
+
+    prefs = SCPreferencesCreate(NULL, IFNAMER_ID, NETWORK_INTERFACES_PREFS);
+    if (prefs == NULL) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCreate failed, %s"),
+             SCErrorString(SCError()));
+       return;
+    }
+
+    if (!SCPreferencesSetValue(prefs, INTERFACES, ilist)) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesSetValue failed, %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+    if (!SCPreferencesCommitChanges(prefs)) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": SCPreferencesCommitChanges failed, %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+done:
+
+    CFRelease(prefs);
+    return;
+}
+
+static void
+updateBondConfiguration(void)
+{
+    BondPreferencesRef prefs;
+
+    prefs = BondPreferencesCreate(NULL);
+    if (prefs == NULL) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": BondPreferencesCreate failed, %s"),
+             SCErrorString(SCError()));
+       return;
+    }
+
+    if (!_BondPreferencesUpdateConfiguration(prefs)) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": _BondPreferencesUpdateConfiguration failed, %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+done:
+
+    CFRelease(prefs);
+    return;
+}
+
+static void
+updateVLANConfiguration(void)
+{
+    VLANPreferencesRef prefs;
+
+    prefs = VLANPreferencesCreate(NULL);
+    if (prefs == NULL) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": VLANPreferencesCreate failed, %s"),
+             SCErrorString(SCError()));
+       return;
+    }
+
+    if (!_VLANPreferencesUpdateConfiguration(prefs)) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME ": _VLANPreferencesUpdateConfiguration failed, %s"),
+             SCErrorString(SCError()));
+       goto done;
+    }
+
+done:
+
+    CFRelease(prefs);
+    return;
+}
+
+#define INDEX_BAD      (-1)
+
+static CFDictionaryRef
+lookupInterfaceByType(CFArrayRef list, CFDictionaryRef if_dict, int * where)
+{
+    CFDataRef  addr;
+    CFIndex    i;
+    CFIndex    n;
+    CFNumberRef        type;
+
+    if (where) {
+       *where = INDEX_BAD;
+    }
+    if (list == NULL) {
+       return (NULL);
+    }
+    addr = CFDictionaryGetValue(if_dict, CFSTR(kIOMACAddress));
+    type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+    if (type == NULL || addr == NULL) {
+       return (NULL);
+    }
+
+    n = CFArrayGetCount(list);
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+       CFDataRef       a;
+       CFNumberRef     t;
+
+       a = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+       t = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+       if (a == NULL || t == NULL)
+           continue;
+
+       if (CFNumberCompare(type, t, NULL) == kCFCompareEqualTo
+           && compareMacAddress(addr, a) == kCFCompareEqualTo) {
+           if (where) {
+               *where = i;
+           }
+           return (dict);
+       }
+    }
+    return (NULL);
+}
+
+static CFDictionaryRef
+lookupInterfaceByUnit(CFArrayRef list, CFDictionaryRef if_dict, int * where)
+{
+    CFIndex    i;
+    CFIndex    n;
+    CFNumberRef        type;
+    CFNumberRef        unit;
+
+    if (where) {
+       *where = INDEX_BAD;
+    }
+    if (list == NULL) {
+       return (NULL);
+    }
+    type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+    unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+    if (type == NULL || unit == NULL) {
+       return (NULL);
+    }
+
+    n = CFArrayGetCount(list);
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+       CFNumberRef     t;
+       CFNumberRef     u;
+
+       t = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+       u = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+       if (t == NULL || u == NULL) {
+           continue;
+       }
+
+       if (CFNumberCompare(type, t, NULL) == kCFCompareEqualTo
+           && CFNumberCompare(unit, u, NULL) == kCFCompareEqualTo) {
+           if (where)
+               *where = i;
+           return (dict);
+       }
+    }
+    return (NULL);
+}
+
+#define kAirPortDriverPath     CFSTR("AirPort")
+#define kIO80211InterfacePath  CFSTR("IO80211Interface")
+#define APPLE_WIRELESS_80211   CFSTR("AppleWireless80211")
+
+static __inline__ boolean_t
+pathIsAirPort(CFStringRef path)
+{
+    CFRange r;
+
+    r = CFStringFind(path, kIO80211InterfacePath, 0);
+    if (r.location != kCFNotFound) {
+       return (TRUE);
+    }
+
+    r = CFStringFind(path, kAirPortDriverPath, 0);
+    if (r.location != kCFNotFound) {
+       return (TRUE);
+    }
+
+    r = CFStringFind(path, APPLE_WIRELESS_80211, 0);
+    if (r.location != kCFNotFound) {
+       return (TRUE);
+    }
+
+    return (FALSE);
+}
+
+static CFDictionaryRef
+lookupAirPortInterface(CFArrayRef list, int * where)
+{
+    CFIndex    i;
+    CFIndex    n;
+
+    if (where) {
+       *where = INDEX_BAD;
+    }
+    if (list == NULL) {
+       return (NULL);
+    }
+    n = CFArrayGetCount(list);
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+       CFStringRef     path;
+
+       path = CFDictionaryGetValue(dict, CFSTR(kIOPathMatchKey));
+       if (path == NULL) {
+           continue;
+       }
+       if (pathIsAirPort(path) == TRUE) {
+           if (where)
+               *where = i;
+           return (dict);
+       }
+    }
+    return (NULL);
+}
+
+static void
+insertInterface(CFMutableArrayRef list, CFDictionaryRef if_dict)
+{
+    CFIndex            i;
+    CFNumberRef                if_type;
+    CFNumberRef                if_unit;
+    CFIndex            n       = CFArrayGetCount(list);
+    CFComparisonResult res;
+
+    if_type = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceType));
+    if_unit = CFDictionaryGetValue(if_dict, CFSTR(kIOInterfaceUnit));
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(list, i);
+       CFNumberRef     type;
+       CFNumberRef     unit;
+
+       type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+       unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+       res = CFNumberCompare(if_type, type, NULL);
+       if (res == kCFCompareLessThan
+           || (res == kCFCompareEqualTo
+               && (CFNumberCompare(if_unit, unit, NULL)
+                   == kCFCompareLessThan))) {
+           CFArrayInsertValueAtIndex(list, i, if_dict);
+           return;
+       }
+    }
+    CFArrayAppendValue(S_dblist, if_dict);
+    return;
+}
+
+static void
+replaceInterface(CFDictionaryRef if_dict)
+{
+    int where;
+
+    if (S_dblist == NULL) {
+       S_dblist = CFArrayCreateMutable(NULL, 0,
+                                       &kCFTypeArrayCallBacks);
+    }
+    /* remove any dict that has our type/addr */
+    if (lookupInterfaceByType(S_dblist, if_dict, &where) != NULL) {
+       CFArrayRemoveValueAtIndex(S_dblist, where);
+    }
+    /* remove any dict that has the same type/unit */
+    if (lookupInterfaceByUnit(S_dblist, if_dict, &where) != NULL) {
+       CFArrayRemoveValueAtIndex(S_dblist, where);
+    }
+    insertInterface(S_dblist, if_dict);
+    return;
+}
+
+static CFNumberRef
+getHighestUnitForType(CFNumberRef if_type)
+{
+    int                i;
+    CFIndex            n;
+    CFNumberRef                ret_unit = NULL;
+
+    if (S_dblist == NULL)
+       return (NULL);
+
+    n = CFArrayGetCount(S_dblist);
+    for (i = 0; i < n; i++) {
+       CFDictionaryRef dict = CFArrayGetValueAtIndex(S_dblist, i);
+       CFNumberRef     type;
+       CFNumberRef     unit;
+
+       type = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceType));
+       if (CFEqual(type, if_type)) {
+           unit = CFDictionaryGetValue(dict, CFSTR(kIOInterfaceUnit));
+           if (ret_unit == NULL
+               || (CFNumberCompare(unit, ret_unit, NULL)
+                   == kCFCompareGreaterThan)) {
+               ret_unit = unit;
+           }
+       }
+    }
+    return (ret_unit);
+}
+
+//------------------------------------------------------------------------
+// Register a single interface with the given service path to the
+// data link layer (BSD), using the specified unit number.
+
+static kern_return_t
+registerInterface(io_connect_t connect,
+                 CFStringRef path,
+                 CFNumberRef unit)
+{
+    CFMutableDictionaryRef     dict;
+    kern_return_t              kr = kIOReturnNoMemory;
+
+    dict = CFDictionaryCreateMutable(NULL, 0,
+                                    &kCFTypeDictionaryKeyCallBacks,
+                                    &kCFTypeDictionaryValueCallBacks);
+    if (dict == NULL
+       || addCFNumberProperty(dict, kIONetworkStackUserCommand,
+                              kIORegisterOne) == FALSE)
+       ;
+    else {
+       CFDictionarySetValue(dict, CFSTR(kIOPathMatchKey), path);
+       CFDictionarySetValue(dict, CFSTR(kIOInterfaceUnit), unit);
+       kr = IOConnectSetCFProperties(connect, dict);
+    }
+    if (dict) CFRelease( dict );
+    return kr;
+}
+
+/*
+ * Note: this function blocks all other plug-ins until it completes
+ */
+static void
+waitForQuiet(mach_port_t masterPort)
+{
+    mach_timespec_t t;
+    kern_return_t   wait_ret;
+
+    t.tv_sec  = 4;
+    t.tv_nsec = 0;
+
+    // kIOReturnTimeout if the wait timed out.
+    // kIOReturnSuccess on success.
+    wait_ret = IOKitWaitQuiet(masterPort, &t);
+    return;
+}
+
+/*
+ * Function: createNetworkStackObject
+ * Purpose:
+ *   Get a reference to the single IONetworkStack object instance in
+ *   the kernel. Naming requests must be sent to this object, which is
+ *   attached as a client to all network interface objects in the system.
+ * Note:
+ *   Call IOObjectRelease on the returned object.
+ */
+static io_object_t
+createNetworkStackObject(mach_port_t masterPort)
+{
+    io_iterator_t      iter = MACH_PORT_NULL;
+    kern_return_t      kr;
+    io_object_t                stack = MACH_PORT_NULL;
+
+    kr = IOServiceGetMatchingServices(masterPort,
+                                     IOServiceMatching("IONetworkStack"),
+                                     &iter);
+    if (iter != MACH_PORT_NULL) {
+       if (kr == KERN_SUCCESS) {
+           stack = IOIteratorNext(iter);
+       }
+       IOObjectRelease(iter);
+    }
+    return stack;
+}
+
+static void
+printMacAddress(CFDataRef data)
+{
+    int                i;
+    CFIndex    n = CFDataGetLength(data);
+
+    for (i = 0; i < n; i++) {
+       if (i != 0) SCPrint(TRUE, stdout, CFSTR(":"));
+       SCPrint(TRUE, stdout, CFSTR("%02x"), CFDataGetBytePtr(data)[i]);
+    }
+    return;
+}
+
+/*
+ * Function: getMacAddress
+ *
+ * Purpose:
+ *   Given an interface object if_obj, return its associated mac address.
+ *   The mac address is stored in the parent, the network controller object.
+ *
+ * Returns:
+ *   The CFDataRef containing the bytes of the mac address.
+ */
+static CFDataRef
+getMacAddress(io_object_t if_obj)
+{
+    CFMutableDictionaryRef     dict = NULL;
+    CFDataRef                  data = NULL;
+    kern_return_t              kr;
+    io_object_t                        parent_obj = MACH_PORT_NULL;
+
+    /* get the parent node */
+    kr = IORegistryEntryGetParentEntry(if_obj, kIOServicePlane, &parent_obj);
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME
+                   ": IORegistryEntryGetParentEntry returned 0x%x"),
+             kr);
+       goto failed;
+    }
+
+    /* get the dictionary associated with the node */
+    kr = IORegistryEntryCreateCFProperties(parent_obj,
+                                          &dict,
+                                          NULL,
+                                          kNilOptions );
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME
+                   ": IORegistryEntryCreateCFProperties returned 0x%x"),
+             kr);
+       goto failed;
+    }
+    data = CFDictionaryGetValue(dict, CFSTR(kIOMACAddress));
+    if (data) {
+       CFRetain(data);
+    }
+
+ failed:
+    if (dict)
+       CFRelease(dict);
+    if (parent_obj)
+       IOObjectRelease(parent_obj);
+    return (data);
+}
+
+static CFDictionaryRef
+getInterface(io_object_t if_obj)
+{
+    CFBooleanRef                       builtin;
+    kern_return_t                      kr;
+    CFDataRef                          mac_address = NULL;
+    CFStringRef                                location;
+    CFMutableDictionaryRef             new_if = NULL;
+    io_string_t                                path;
+    CFMutableDictionaryRef             reginfo_if = NULL;
+    CFDictionaryRef                    ret_dict = NULL;
+    CFStringRef                                string;
+    CFNumberRef                                type;
+    CFNumberRef                                unit;
+
+    kr = IORegistryEntryGetPath(if_obj, kIOServicePlane, path);
+    if (kr != KERN_SUCCESS) {
+       SCLog(TRUE, LOG_INFO,
+             CFSTR(MY_PLUGIN_NAME
+                   ": IORegistryEntryGetPath returned 0x%x"),
+             kr);
+       goto failed;
+    }
+    kr = IORegistryEntryCreateCFProperties(if_obj,
+                                          &reginfo_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 (file)
index 0000000..0a9b667
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>KernelEventMonitor</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.KernelEventMonitor</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Requires</key>
+       <array>
+               <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+       </array>
+       <key>Builtin</key>
+       <true/>
+</dict>
+</plist>
diff --git a/Plugins/KernelEventMonitor/ev_appletalk.c b/Plugins/KernelEventMonitor/ev_appletalk.c
new file mode 100644 (file)
index 0000000..cbcfd2e
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_appletalk.h"
+
+// from <netat/ddp.h>
+#define DDP_MIN_NETWORK        0x0001
+#define DDP_MAX_NETWORK        0xfffe
+
+
+static int
+get_atalk_interface_cfg(const char *if_name, at_if_cfg_t *cfg)
+{
+       int     fd;
+
+       /* open socket */
+       if ((fd = socket(AF_APPLETALK, SOCK_RAW, 0)) < 0)
+               return -1;
+
+       /* get config info for given interface */
+       strncpy(cfg->ifr_name, if_name, sizeof(cfg->ifr_name));
+       if (ioctl(fd, AIOCGETIFCFG, (caddr_t)cfg) < 0) {
+               (void)close(fd);
+               return -1;
+       }
+
+       (void)close(fd);
+       return 0;
+}
+
+
+static CFMutableDictionaryRef
+getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+{
+       CFDictionaryRef         dict            = NULL;
+       CFMutableDictionaryRef  newDict         = NULL;
+
+       if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
+               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+       } else {
+               dict = cache_SCDynamicStoreCopyValue(store, key);
+               if (dict) {
+                       CFDictionarySetValue(oldIFs, key, dict);
+                       if (isA_CFDictionary(dict)) {
+                               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkID);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNodeID);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkNetworkRange);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetAppleTalkDefaultZone);
+                       }
+                       CFRelease(dict);
+               }
+       }
+
+       if (!newDict) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       return newDict;
+}
+
+
+static void
+updateStore(const void *key, const void *value, void *context)
+{
+       CFDictionaryRef dict;
+       CFDictionaryRef newDict = (CFDictionaryRef)value;
+       CFDictionaryRef oldIFs  = (CFDictionaryRef)context;
+
+       dict = CFDictionaryGetValue(oldIFs, key);
+
+       if (!dict || !CFEqual(dict, newDict)) {
+               if (CFDictionaryGetCount(newDict) > 0) {
+                       cache_SCDynamicStoreSetValue(store, key, newDict);
+               } else if (dict) {
+                       cache_SCDynamicStoreRemoveValue(store, key);
+               }
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+interface_update_appletalk(struct ifaddrs *ifap, const char *if_name)
+{
+       struct ifaddrs          *ifa;
+       struct ifaddrs          *ifap_temp      = NULL;
+       CFStringRef             interface;
+       boolean_t               interfaceFound  = FALSE;
+       CFStringRef             key             = NULL;
+       CFMutableDictionaryRef  oldIFs;
+       CFMutableDictionaryRef  newDict         = NULL;
+       CFMutableDictionaryRef  newIFs;
+
+       oldIFs = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+       newIFs = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+
+       if (!ifap) {
+               if (getifaddrs(&ifap_temp) < 0) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+                       goto error;
+               }
+               ifap = ifap_temp;
+       }
+
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               at_if_cfg_t             cfg;
+               int                     iVal;
+               CFNumberRef             num;
+               struct sockaddr_at      *sat;
+
+               if (ifa->ifa_addr->sa_family != AF_APPLETALK) {
+                       continue;                       /* sorry, not interested */
+               }
+
+               /* check if this is the requested interface */
+               if (if_name) {
+                       if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
+                               interfaceFound = TRUE;  /* yes, this is the one I want */
+                       } else {
+                               continue;               /* sorry, not interested */
+                       }
+               }
+
+               /* get the current cache information */
+               interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
+               key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                         kSCDynamicStoreDomainState,
+                                                                         interface,
+                                                                         kSCEntNetAppleTalk);
+               CFRelease(interface);
+
+               newDict = getIF(key, oldIFs, newIFs);
+
+               sat = (struct sockaddr_at *)ifa->ifa_addr;
+
+               iVal = (int)sat->sat_addr.s_net;
+               num  = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+               CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, num);
+               CFRelease(num);
+
+               iVal = (int)sat->sat_addr.s_node;
+               num  = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+               CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, num);
+               CFRelease(num);
+
+               if (get_atalk_interface_cfg(ifa->ifa_name, &cfg) == 0) {
+                       CFStringRef             zone;
+
+                       /*
+                        * Set starting and ending net values
+                        */
+                       if (!(((cfg.netStart == 0) && (cfg.netEnd == 0)) ||
+                             ((cfg.netStart == DDP_MIN_NETWORK) && (cfg.netEnd == DDP_MAX_NETWORK)))) {
+                               CFMutableArrayRef       array;
+
+                               array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+                               iVal = cfg.netStart;
+                               num  = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+                               CFArrayAppendValue(array, num);
+                               CFRelease(num);
+
+                               iVal = cfg.netEnd;
+                               num  = CFNumberCreate(NULL, kCFNumberIntType, &iVal);
+                               CFArrayAppendValue(array, num);
+                               CFRelease(num);
+
+                               CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkRange, array);
+                               CFRelease(array);
+                       }
+
+                       /*
+                        * Set the default zone
+                        */
+                       zone = CFStringCreateWithPascalString(NULL,
+                                                             (ConstStr255Param)&cfg.zonename,
+                                                             kCFStringEncodingMacRoman);
+                       CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, zone);
+                       CFRelease(zone);
+               }
+
+               CFDictionarySetValue(newIFs, key, newDict);
+               CFRelease(newDict);
+               CFRelease(key);
+       }
+
+       /* if the last address[es] were removed from the target interface */
+       if (if_name && !interfaceFound) {
+               interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+               key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                         kSCDynamicStoreDomainState,
+                                                                         interface,
+                                                                         kSCEntNetAppleTalk);
+               CFRelease(interface);
+
+               newDict = getIF(key, oldIFs, newIFs);
+
+               CFDictionarySetValue(newIFs, key, newDict);
+               CFRelease(newDict);
+               CFRelease(key);
+       }
+
+       CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
+
+    error :
+
+       if (ifap_temp)  freeifaddrs(ifap_temp);
+       CFRelease(oldIFs);
+       CFRelease(newIFs);
+
+       return;
+}
+
+
+__private_extern__
+void
+interface_update_atalk_address(struct kev_atalk_data *aEvent, const char *if_name)
+{
+       CFStringRef             interface;
+       CFStringRef             key;
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict = NULL;
+       CFNumberRef             newNode, newNet;
+       int                     node;
+       int                     net;
+
+       /* get the current cache information */
+       interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+       key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                 kSCDynamicStoreDomainState,
+                                                                 interface,
+                                                                 kSCEntNetAppleTalk);
+       CFRelease(interface);
+
+       dict = cache_SCDynamicStoreCopyValue(store, key);
+       if (dict) {
+               if (isA_CFDictionary(dict)) {
+                       newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+               }
+               CFRelease(dict);
+       }
+
+       if (!newDict) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       /* Update node/net values in cache */
+       node    = (int)aEvent->node_data.address.s_node;
+       net     = (int)aEvent->node_data.address.s_net;
+
+       newNode = CFNumberCreate(NULL, kCFNumberIntType, &node);
+       newNet  = CFNumberCreate(NULL, kCFNumberIntType, &net);
+
+       CFDictionarySetValue(newDict, kSCPropNetAppleTalkNodeID, newNode);
+       CFDictionarySetValue(newDict, kSCPropNetAppleTalkNetworkID, newNet);
+
+       CFRelease(newNode);
+       CFRelease(newNet);
+
+       /* update cache */
+       cache_SCDynamicStoreSetValue(store, key, newDict);
+       CFRelease(newDict);
+       CFRelease(key);
+       return;
+}
+
+
+__private_extern__
+void
+interface_update_atalk_zone(struct kev_atalk_data *aEvent, const char *if_name)
+{
+       CFStringRef             interface;
+       CFStringRef             key;
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict = NULL;
+       CFStringRef             newZone;
+
+       /* get the current cache information */
+       interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+       key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                 kSCDynamicStoreDomainState,
+                                                                 interface,
+                                                                 kSCEntNetAppleTalk);
+       CFRelease(interface);
+
+       dict = cache_SCDynamicStoreCopyValue(store, key);
+       if (dict) {
+               if (isA_CFDictionary(dict)) {
+                       newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+               }
+               CFRelease(dict);
+       }
+
+       if (!newDict) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       /* Update zone value in cache */
+       newZone = CFStringCreateWithPascalString(NULL, (ConstStr255Param)&(aEvent->node_data.zone), kCFStringEncodingMacRoman);
+
+       CFDictionarySetValue(newDict, kSCPropNetAppleTalkDefaultZone, newZone);
+
+       CFRelease(newZone);
+
+       /* update cache */
+       cache_SCDynamicStoreSetValue(store, key, newDict);
+       CFRelease(newDict);
+       CFRelease(key);
+       return;
+}
+
+
+__private_extern__
+void
+interface_update_shutdown_atalk()
+{
+       CFStringRef                     cacheKey;
+       CFDictionaryRef                 dict;
+       CFArrayRef                      ifList = NULL;
+       CFIndex                         count, index;
+       CFStringRef                     interface;
+       CFStringRef                     key;
+
+       cacheKey  = SCDynamicStoreKeyCreateNetworkInterface(NULL,
+                                                           kSCDynamicStoreDomainState);
+
+       dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
+       CFRelease(cacheKey);
+
+       if (dict) {
+               if (isA_CFDictionary(dict)) {
+                       /*get a list of the interfaces*/
+                       ifList  = isA_CFArray(CFDictionaryGetValue(dict, kSCDynamicStorePropNetInterfaces));
+                       if (ifList) {
+                               count = CFArrayGetCount(ifList);
+
+                               /*iterate through list and remove AppleTalk data*/
+                               for (index = 0; index < count; index++) {
+                                       interface = CFArrayGetValueAtIndex(ifList, index);
+                                       key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                                                 kSCDynamicStoreDomainState,
+                                                                                                 interface,
+                                                                                                 kSCEntNetAppleTalk);
+                                       cache_SCDynamicStoreRemoveValue(store, key);
+                                       CFRelease(key);
+                               }
+                       }
+               }
+               CFRelease(dict);
+       }
+
+       return;
+}
diff --git a/Plugins/KernelEventMonitor/ev_appletalk.h b/Plugins/KernelEventMonitor/ev_appletalk.h
new file mode 100644 (file)
index 0000000..bb48ef4
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EV_APPLETALK_H
+#define _EV_APPLETALK_H
+
+#include <netat/appletalk.h>
+#include <netat/at_var.h>
+
+__BEGIN_DECLS
+
+void   interface_update_appletalk      (struct ifaddrs *ifap, const char *if_name);
+void   interface_update_atalk_address  (struct kev_atalk_data *aEvent, const char *if_name);
+void   interface_update_atalk_zone     (struct kev_atalk_data *aEvent, const char *if_name);
+void   interface_update_shutdown_atalk ();
+
+__END_DECLS
+
+#endif /* _EV_EVENTMON_H */
+
diff --git a/Plugins/KernelEventMonitor/ev_dlil.c b/Plugins/KernelEventMonitor/ev_dlil.c
new file mode 100644 (file)
index 0000000..516fe99
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_dlil.h"
+
+static CFStringRef
+create_interface_key(const char * if_name)
+{
+       CFStringRef             interface;
+       CFStringRef             key;
+
+       interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+       key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                 kSCDynamicStoreDomainState,
+                                                                 interface,
+                                                                 kSCEntNetLink);
+       CFRelease(interface);
+       return (key);
+}
+
+
+static CFMutableDictionaryRef
+copy_entity(CFStringRef key)
+{
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict         = NULL;
+
+       dict = cache_SCDynamicStoreCopyValue(store, key);
+       if (dict != NULL) {
+               if (isA_CFDictionary(dict) != NULL) {
+                       newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+               }
+               CFRelease(dict);
+       }
+       if (newDict == NULL) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+       return (newDict);
+}
+
+
+static void
+interface_update_status(const char *if_name, CFBooleanRef active,
+                       boolean_t attach)
+{
+       CFStringRef             key             = NULL;
+       CFMutableDictionaryRef  newDict         = NULL;
+       CFBooleanRef            state           = NULL;
+
+       key = create_interface_key(if_name);
+       newDict = copy_entity(key);
+       state = isA_CFBoolean(CFDictionaryGetValue(newDict,
+                                                  kSCPropNetLinkActive));
+       /* if new status available, update cache */
+       if (active == NULL) {
+           CFDictionaryRemoveValue(newDict, kSCPropNetLinkActive);
+       } else {
+           CFDictionarySetValue(newDict, kSCPropNetLinkActive, active);
+       }
+       if (attach == TRUE) {
+               /* the interface was attached, remove stale state */
+               CFDictionaryRemoveValue(newDict, kSCPropNetLinkDetaching);
+       }
+
+       /* update status */
+       if (CFDictionaryGetCount(newDict) > 0) {
+               cache_SCDynamicStoreSetValue(store, key, newDict);
+       } else {
+               cache_SCDynamicStoreRemoveValue(store, key);
+       }
+
+       CFRelease(key);
+       CFRelease(newDict);
+       return;
+}
+
+__private_extern__
+void
+interface_detaching(const char *if_name)
+{
+       CFStringRef             key;
+       CFMutableDictionaryRef  newDict;
+
+       key = create_interface_key(if_name);
+       newDict = copy_entity(key);
+       CFDictionarySetValue(newDict, kSCPropNetLinkDetaching,
+                            kCFBooleanTrue);
+       cache_SCDynamicStoreSetValue(store, key, newDict);
+       CFRelease(newDict);
+       CFRelease(key);
+       return;
+}
+
+static void
+interface_remove(const char *if_name)
+{
+       CFStringRef             key;
+
+       key = create_interface_key(if_name);
+       cache_SCDynamicStoreRemoveValue(store, key);
+       CFRelease(key);
+       return;
+}
+
+
+__private_extern__
+void
+link_update_status(const char *if_name, boolean_t attach)
+{
+       CFBooleanRef            active  = NULL;
+       struct ifmediareq       ifm;
+       int                     sock;
+
+       sock = dgram_socket(AF_INET);
+       if (sock < 0) {
+               SCLog(TRUE, LOG_NOTICE, CFSTR("link_update_status: socket open failed,  %s"), strerror(errno));
+               goto done;
+       }
+       bzero((char *)&ifm, sizeof(ifm));
+       (void) strncpy(ifm.ifm_name, if_name, sizeof(ifm.ifm_name));
+
+       if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifm) == -1) {
+               /* if media status not available for this interface */
+               goto done;
+       }
+
+       if (ifm.ifm_count == 0) {
+               /* no media types */
+               goto done;
+       }
+
+       if (!(ifm.ifm_status & IFM_AVALID)) {
+               /* if active bit not valid */
+               goto done;
+       }
+
+       if (ifm.ifm_status & IFM_ACTIVE) {
+               active = kCFBooleanTrue;
+       } else {
+               active = kCFBooleanFalse;
+       }
+
+ done:
+       interface_update_status(if_name, active, attach);
+       if (sock >= 0)
+               close(sock);
+       return;
+}
+
+
+__private_extern__
+void
+link_add(const char *if_name)
+{
+       CFStringRef             interface;
+       CFStringRef             cacheKey;
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict         = NULL;
+       CFArrayRef              ifList;
+       CFMutableArrayRef       newIFList       = NULL;
+
+       interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+       cacheKey  = SCDynamicStoreKeyCreateNetworkInterface(NULL,
+                                                           kSCDynamicStoreDomainState);
+
+       dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
+       if (dict) {
+               if (isA_CFDictionary(dict)) {
+                       newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+                       ifList  = CFDictionaryGetValue(newDict, kSCDynamicStorePropNetInterfaces);
+                       if (isA_CFArray(ifList)) {
+                               newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+                       }
+               }
+               CFRelease(dict);
+       }
+
+       if (!newDict) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       if (!newIFList) {
+               newIFList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       if (CFArrayContainsValue(newIFList,
+                                CFRangeMake(0, CFArrayGetCount(newIFList)),
+                                interface) == FALSE) {
+               CFArrayAppendValue(newIFList, interface);
+               CFDictionarySetValue(newDict,
+                                    kSCDynamicStorePropNetInterfaces,
+                                    newIFList);
+       }
+       cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
+       link_update_status(if_name, TRUE);
+       CFRelease(cacheKey);
+       CFRelease(interface);
+       if (newDict)    CFRelease(newDict);
+       if (newIFList)  CFRelease(newIFList);
+
+       return;
+}
+
+
+__private_extern__
+void
+link_remove(const char *if_name)
+{
+       CFStringRef             interface;
+       CFStringRef             cacheKey;
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict         = NULL;
+       CFArrayRef              ifList;
+       CFMutableArrayRef       newIFList       = NULL;
+       CFIndex                 i;
+
+       interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+       cacheKey  = SCDynamicStoreKeyCreateNetworkInterface(NULL,
+                                                           kSCDynamicStoreDomainState);
+
+       dict = cache_SCDynamicStoreCopyValue(store, cacheKey);
+       if (dict) {
+               if (isA_CFDictionary(dict)) {
+                       newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+                       ifList  = CFDictionaryGetValue(newDict, kSCDynamicStorePropNetInterfaces);
+                       if (isA_CFArray(ifList)) {
+                               newIFList = CFArrayCreateMutableCopy(NULL, 0, ifList);
+                       }
+               }
+               CFRelease(dict);
+       }
+
+       if (!newIFList ||
+           ((i = CFArrayGetFirstIndexOfValue(newIFList,
+                                            CFRangeMake(0, CFArrayGetCount(newIFList)),
+                                            interface)) == kCFNotFound)
+          ) {
+               /* we're not tracking this interface */
+               goto done;
+       }
+
+       CFArrayRemoveValueAtIndex(newIFList, i);
+       CFDictionarySetValue(newDict, kSCDynamicStorePropNetInterfaces, newIFList);
+       cache_SCDynamicStoreSetValue(store, cacheKey, newDict);
+
+       interface_remove(if_name);
+
+    done:
+
+       CFRelease(cacheKey);
+       CFRelease(interface);
+       if (newDict)    CFRelease(newDict);
+       if (newIFList)  CFRelease(newIFList);
+
+       return;
+}
diff --git a/Plugins/KernelEventMonitor/ev_dlil.h b/Plugins/KernelEventMonitor/ev_dlil.h
new file mode 100644 (file)
index 0000000..6ab9a80
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EV_DLIL_H
+#define _EV_DLIL_H
+
+__BEGIN_DECLS
+
+void   interface_detaching     (const char *if_name);
+void   link_add                (const char *if_name);
+void   link_remove             (const char *if_name);
+void   link_update_status      (const char *if_name, boolean_t attach);
+
+__END_DECLS
+
+#endif /* _EV_DLIL_H */
+
diff --git a/Plugins/KernelEventMonitor/ev_ipv4.c b/Plugins/KernelEventMonitor/ev_ipv4.c
new file mode 100644 (file)
index 0000000..c8071e7
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_ipv4.h"
+
+#ifndef kSCEntNetIPv4ARPCollision
+#define kSCEntNetIPv4ARPCollision      CFSTR("IPv4ARPCollision")
+#endif kSCEntNetIPv4ARPCollision
+
+#define IP_FORMAT      "%d.%d.%d.%d"
+#define IP_CH(ip, i)   (((u_char *)(ip))[i])
+#define IP_LIST(ip)    IP_CH(ip,0),IP_CH(ip,1),IP_CH(ip,2),IP_CH(ip,3)
+
+
+static void
+appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct in_addr *address)
+{
+       CFStringRef             addr;
+       CFArrayRef              addrs;
+       CFMutableArrayRef       newAddrs;
+
+       addrs = CFDictionaryGetValue(dict, key);
+       if (addrs) {
+               newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
+       } else {
+               newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       addr = CFStringCreateWithFormat(NULL, NULL, CFSTR(IP_FORMAT), IP_LIST(address));
+       CFArrayAppendValue(newAddrs, addr);
+       CFRelease(addr);
+
+       CFDictionarySetValue(dict, key, newAddrs);
+       CFRelease(newAddrs);
+       return;
+}
+
+
+static CFMutableDictionaryRef
+getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+{
+       CFDictionaryRef         dict            = NULL;
+       CFMutableDictionaryRef  newDict         = NULL;
+
+       if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
+               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+       } else {
+               dict = cache_SCDynamicStoreCopyValue(store, key);
+               if (dict) {
+                       CFDictionarySetValue(oldIFs, key, dict);
+                       if (isA_CFDictionary(dict)) {
+                               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv4Addresses);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv4SubnetMasks);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv4DestAddresses);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv4BroadcastAddresses);
+                       }
+                       CFRelease(dict);
+               }
+       }
+
+       if (!newDict) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       return newDict;
+}
+
+
+static void
+updateStore(const void *key, const void *value, void *context)
+{
+       CFDictionaryRef dict;
+       CFDictionaryRef newDict = (CFDictionaryRef)value;
+       CFDictionaryRef oldIFs  = (CFDictionaryRef)context;
+
+       dict = CFDictionaryGetValue(oldIFs, key);
+
+       if (!dict || !CFEqual(dict, newDict)) {
+               if (CFDictionaryGetCount(newDict) > 0) {
+                       cache_SCDynamicStoreSetValue(store, key, newDict);
+               } else if (dict) {
+                       cache_SCDynamicStoreRemoveValue(store, key);
+               }
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+interface_update_ipv4(struct ifaddrs *ifap, const char *if_name)
+{
+       struct ifaddrs          *ifa;
+       struct ifaddrs          *ifap_temp      = NULL;
+       CFStringRef             interface;
+       boolean_t               interfaceFound  = FALSE;
+       CFStringRef             key             = NULL;
+       CFMutableDictionaryRef  oldIFs;
+       CFMutableDictionaryRef  newDict         = NULL;
+       CFMutableDictionaryRef  newIFs;
+
+       oldIFs = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+       newIFs = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+
+       if (!ifap) {
+               if (getifaddrs(&ifap_temp) < 0) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+                       goto error;
+               }
+               ifap = ifap_temp;
+       }
+
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               struct sockaddr_in      *sin;
+
+               if (ifa->ifa_addr->sa_family != AF_INET) {
+                       continue;                       /* sorry, not interested */
+               }
+
+               /* check if this is the requested interface */
+               if (if_name) {
+                       if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
+                               interfaceFound = TRUE;  /* yes, this is the one I want */
+                       } else {
+                               continue;               /* sorry, not interested */
+                       }
+               }
+
+               interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
+               key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                         kSCDynamicStoreDomainState,
+                                                                         interface,
+                                                                         kSCEntNetIPv4);
+               CFRelease(interface);
+
+               newDict = getIF(key, oldIFs, newIFs);
+
+               sin = (struct sockaddr_in *)ifa->ifa_addr;
+               appendAddress(newDict, kSCPropNetIPv4Addresses, &sin->sin_addr);
+
+               if (ifa->ifa_flags & IFF_POINTOPOINT) {
+                       struct sockaddr_in      *dst;
+
+                       dst = (struct sockaddr_in *)ifa->ifa_dstaddr;
+                       appendAddress(newDict, kSCPropNetIPv4DestAddresses, &dst->sin_addr);
+               } else {
+                       struct sockaddr_in      *brd;
+                       struct sockaddr_in      *msk;
+
+                       brd = (struct sockaddr_in *)ifa->ifa_broadaddr;
+                       appendAddress(newDict, kSCPropNetIPv4BroadcastAddresses, &brd->sin_addr);
+                       msk = (struct sockaddr_in *)ifa->ifa_netmask;
+                       appendAddress(newDict, kSCPropNetIPv4SubnetMasks, &msk->sin_addr);
+               }
+
+               CFDictionarySetValue(newIFs, key, newDict);
+               CFRelease(newDict);
+               CFRelease(key);
+       }
+
+       /* if the last address[es] were removed from the target interface */
+       if (if_name && !interfaceFound) {
+               interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+               key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                         kSCDynamicStoreDomainState,
+                                                                         interface,
+                                                                         kSCEntNetIPv4);
+               CFRelease(interface);
+
+               newDict = getIF(key, oldIFs, newIFs);
+
+               CFDictionarySetValue(newIFs, key, newDict);
+               CFRelease(newDict);
+               CFRelease(key);
+       }
+
+       CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
+
+    error :
+
+       if (ifap_temp)  freeifaddrs(ifap_temp);
+       CFRelease(oldIFs);
+       CFRelease(newIFs);
+
+       return;
+}
+
+__private_extern__
+void
+interface_collision_ipv4(const char *if_name, struct in_addr ip_addr, int hw_len, const void * hw_addr)
+{
+       uint8_t *               hw_addr_bytes = (uint8_t *)hw_addr;
+       int                     i;
+       CFStringRef             if_name_cf;
+       CFMutableStringRef      key;
+       CFStringRef             prefix;
+
+       if_name_cf = CFStringCreateWithCString(NULL, if_name,
+                                              kCFStringEncodingASCII);
+       prefix = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                              kSCDynamicStoreDomainState,
+                                                              if_name_cf,
+                                                              kSCEntNetIPv4ARPCollision);
+       key = CFStringCreateMutableCopy(NULL, 0, prefix);
+       CFStringAppendFormat(key, NULL, CFSTR("/" IP_FORMAT),
+                            IP_LIST(&ip_addr));
+       for (i = 0; i < hw_len; i++) {
+           CFStringAppendFormat(key, NULL, CFSTR("%s%02x"),
+                                (i == 0) ? "/" : ":", hw_addr_bytes[i]);
+       }
+       cache_SCDynamicStoreNotifyValue(store, key);
+       CFRelease(key);
+       CFRelease(prefix);
+       CFRelease(if_name_cf);
+       return;
+}
diff --git a/Plugins/KernelEventMonitor/ev_ipv4.h b/Plugins/KernelEventMonitor/ev_ipv4.h
new file mode 100644 (file)
index 0000000..8a38843
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EV_IPV4_H
+#define _EV_IPV4_H
+
+#include <netinet/in_var.h>
+
+__BEGIN_DECLS
+
+void   interface_update_ipv4   (struct ifaddrs *ifap, const char *if_name);
+void   interface_collision_ipv4(const char *if_name,
+                                struct in_addr ip_addr,
+                                int hw_len, const void * hw_addr);
+__END_DECLS
+
+#endif /* _EV_IPV4_H */
+
diff --git a/Plugins/KernelEventMonitor/ev_ipv6.c b/Plugins/KernelEventMonitor/ev_ipv6.c
new file mode 100644 (file)
index 0000000..47705c4
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_ipv6.h"
+
+#define s6_addr16 __u6_addr.__u6_addr16
+
+#ifndef        kSCPropNetIPv6DestAddresses
+#define kSCPropNetIPv6DestAddresses            SCSTR("DestAddresses")
+#endif
+
+#ifndef        kSCPropNetIPv6Flags
+#define kSCPropNetIPv6Flags                    SCSTR("Flags")
+#endif
+
+#ifndef        kSCPropNetIPv6PrefixLength
+#define kSCPropNetIPv6PrefixLength             SCSTR("PrefixLength")
+#endif
+
+#ifdef NOTYET
+#ifndef        kSCPropNetIPv6ScopeID
+#define kSCPropNetIPv6ScopeID                  SCSTR("ScopeID")
+#endif
+#endif /* NOTYET */
+
+
+static void
+appendAddress(CFMutableDictionaryRef dict, CFStringRef key, struct sockaddr_in6 *sin6)
+{
+       CFStringRef             addr;
+       CFArrayRef              addrs;
+       CFMutableArrayRef       newAddrs;
+       char                    str[64];
+
+       addrs = CFDictionaryGetValue(dict, key);
+       if (addrs) {
+               newAddrs = CFArrayCreateMutableCopy(NULL, 0, addrs);
+       } else {
+               newAddrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr, str, sizeof(str)) == NULL) {
+               SCLog(TRUE, LOG_ERR, CFSTR("inet_ntop() failed: %s"), strerror(errno));
+               str[0] = '\0';
+       }
+
+       addr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), str);
+       CFArrayAppendValue(newAddrs, addr);
+       CFRelease(addr);
+
+       CFDictionarySetValue(dict, key, newAddrs);
+       CFRelease(newAddrs);
+       return;
+}
+
+
+static void
+appendFlags(CFMutableDictionaryRef dict, int flags6)
+{
+       CFArrayRef              flags;
+       CFMutableArrayRef       newFlags;
+       CFNumberRef             v6Flags;
+
+       flags = CFDictionaryGetValue(dict, kSCPropNetIPv6Flags);
+       if (flags) {
+               newFlags = CFArrayCreateMutableCopy(NULL, 0, flags);
+       } else {
+               newFlags = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       v6Flags = CFNumberCreate(NULL, kCFNumberIntType, &flags6);
+       CFArrayAppendValue(newFlags, v6Flags);
+       CFRelease(v6Flags);
+
+       CFDictionarySetValue(dict, kSCPropNetIPv6Flags, newFlags);
+       CFRelease(newFlags);
+       return;
+}
+
+
+static void
+appendPrefixLen(CFMutableDictionaryRef dict, struct sockaddr_in6 *sin6)
+{
+       register u_int8_t       *name           = &sin6->sin6_addr.s6_addr[0];
+       CFNumberRef             prefixLen;
+       CFArrayRef              prefixLens;
+       CFMutableArrayRef       newPrefixLens;
+
+       register int            byte;
+       register int            bit;
+       int                     plen            = 0;
+
+       for (byte = 0; byte < sizeof(struct in6_addr); byte++, plen += 8) {
+               if (name[byte] != 0xff) {
+                       break;
+               }
+       }
+
+       if (byte == sizeof(struct in6_addr)) {
+               goto append;
+       }
+
+       for (bit = 7; bit != 0; bit--, plen++) {
+               if (!(name[byte] & (1 << bit))) {
+                       break;
+               }
+       }
+
+       for (; bit != 0; bit--) {
+               if (name[byte] & (1 << bit)) {
+                       plen = 0;
+                       goto append;
+               }
+       }
+
+       byte++;
+       for (; byte < sizeof(struct in6_addr); byte++) {
+               if (name[byte]) {
+                       plen = 0;
+                       goto append;
+               }
+       }
+
+    append :
+
+       prefixLens = CFDictionaryGetValue(dict, kSCPropNetIPv6PrefixLength);
+       if (prefixLens) {
+               newPrefixLens = CFArrayCreateMutableCopy(NULL, 0, prefixLens);
+       } else {
+               newPrefixLens = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       prefixLen = CFNumberCreate(NULL, kCFNumberIntType, &plen);
+       CFArrayAppendValue(newPrefixLens, prefixLen);
+       CFRelease(prefixLen);
+
+       CFDictionarySetValue(dict, kSCPropNetIPv6PrefixLength, newPrefixLens);
+       CFRelease(newPrefixLens);
+       return;
+}
+
+
+#ifdef NOTYET
+static void
+appendScopeID(CFMutableDictionaryRef dict, struct sockaddr_in6 *sin6)
+{
+       CFNumberRef             scope;
+       CFArrayRef              scopes;
+       CFMutableArrayRef       newScopes;
+
+       scopes = CFDictionaryGetValue(dict, kSCPropNetIPv6ScopeID);
+       if (scopes) {
+               newScopes = CFArrayCreateMutableCopy(NULL, 0, scopes);
+       } else {
+               newScopes = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       scope = CFNumberCreate(NULL, kCFNumberSInt32Type, &sin6->sin6_scope_id);
+       CFArrayAppendValue(newScopes, scope);
+       CFRelease(scope);
+
+       CFDictionarySetValue(dict, kSCPropNetIPv6ScopeID, newScopes);
+       CFRelease(newScopes);
+       return;
+}
+#endif /* NOTYET */
+
+
+static CFMutableDictionaryRef
+getIF(CFStringRef key, CFMutableDictionaryRef oldIFs, CFMutableDictionaryRef newIFs)
+{
+       CFDictionaryRef         dict            = NULL;
+       CFMutableDictionaryRef  newDict         = NULL;
+
+       if (CFDictionaryGetValueIfPresent(newIFs, key, (const void **)&dict)) {
+               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+       } else {
+               dict = cache_SCDynamicStoreCopyValue(store, key);
+               if (dict) {
+                       CFDictionarySetValue(oldIFs, key, dict);
+                       if (isA_CFDictionary(dict)) {
+                               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv6Addresses);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv6DestAddresses);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv6Flags);
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv6PrefixLength);
+#ifdef NOTYET
+                               CFDictionaryRemoveValue(newDict, kSCPropNetIPv6ScopeID);
+#endif /* NOTYET */
+                       }
+                       CFRelease(dict);
+               }
+       }
+
+       if (!newDict) {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       return newDict;
+}
+
+
+static void
+updateStore(const void *key, const void *value, void *context)
+{
+       CFDictionaryRef dict;
+       CFDictionaryRef newDict = (CFDictionaryRef)value;
+       CFDictionaryRef oldIFs  = (CFDictionaryRef)context;
+
+       dict = CFDictionaryGetValue(oldIFs, key);
+
+       if (!dict || !CFEqual(dict, newDict)) {
+               if (CFDictionaryGetCount(newDict) > 0) {
+                       cache_SCDynamicStoreSetValue(store, key, newDict);
+               } else if (dict) {
+                       cache_SCDynamicStoreRemoveValue(store, key);
+               }
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+interface_update_ipv6(struct ifaddrs *ifap, const char *if_name)
+{
+       struct ifaddrs          *ifa;
+       struct ifaddrs          *ifap_temp      = NULL;
+       CFStringRef             interface;
+       boolean_t               interfaceFound  = FALSE;
+       CFStringRef             key             = NULL;
+       CFMutableDictionaryRef  oldIFs;
+       CFMutableDictionaryRef  newDict         = NULL;
+       CFMutableDictionaryRef  newIFs;
+       int                     sock            = -1;
+
+       oldIFs = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+       newIFs = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+
+       if (!ifap) {
+               if (getifaddrs(&ifap_temp) < 0) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+                       goto error;
+               }
+               ifap = ifap_temp;
+       }
+
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               struct in6_ifreq        ifr6;
+#define        flags6  ifr6.ifr_ifru.ifru_flags6
+               struct sockaddr_in6     *sin6;
+
+               if (ifa->ifa_addr->sa_family != AF_INET6) {
+                       continue;                       /* sorry, not interested */
+               }
+
+               /* check if this is the requested interface */
+               if (if_name) {
+                       if (strncmp(if_name, ifa->ifa_name, IFNAMSIZ) == 0) {
+                               interfaceFound = TRUE;  /* yes, this is the one I want */
+                       } else {
+                               continue;               /* sorry, not interested */
+                       }
+               }
+
+               if (sock < 0) {
+                       sock = dgram_socket(AF_INET6);
+                       if (sock < 0) {
+                               SCLog(TRUE, LOG_NOTICE, CFSTR("interface_update_ipv6: socket open failed, %s"), strerror(errno));
+                               goto error;
+                       }
+               }
+
+               /* get the current cache information */
+               interface = CFStringCreateWithCString(NULL, ifa->ifa_name, kCFStringEncodingMacRoman);
+               key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                         kSCDynamicStoreDomainState,
+                                                                         interface,
+                                                                         kSCEntNetIPv6);
+               CFRelease(interface);
+
+               newDict = getIF(key, oldIFs, newIFs);
+
+               sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+
+               /* XXX: embedded link local addr check */
+               if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+                       u_int16_t       index;
+
+                       index = sin6->sin6_addr.s6_addr16[1];
+                       if (index != 0) {
+                               sin6->sin6_addr.s6_addr16[1] = 0;
+                               if (sin6->sin6_scope_id == 0) {
+                                       sin6->sin6_scope_id = ntohs(index);
+                               }
+                       }
+               }
+
+               bzero((char *)&ifr6, sizeof(ifr6));
+               strncpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
+               ifr6.ifr_addr = *sin6;
+               if (ioctl(sock, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
+                       /* if flags not available for this address */
+                       SCLog(TRUE, LOG_NOTICE, CFSTR("interface_update_ipv6: ioctl failed, %s"), strerror(errno));
+               }
+
+               appendAddress  (newDict, kSCPropNetIPv6Addresses, sin6);
+#ifdef NOTYET
+               appendScopeID  (newDict, sin6);
+#endif /* NOTYET */
+               appendPrefixLen(newDict, (struct sockaddr_in6 *)ifa->ifa_netmask);
+               appendFlags    (newDict, flags6);
+
+
+               if (ifa->ifa_flags & IFF_POINTOPOINT) {
+                       struct sockaddr_in6     *dst6;
+
+                       dst6 = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+
+                       /* XXX: embedded link local addr check */
+                       if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) {
+                               u_int16_t       index;
+
+                               index = dst6->sin6_addr.s6_addr16[1];
+                               if (index != 0) {
+                                       dst6->sin6_addr.s6_addr16[1] = 0;
+                                       if (dst6->sin6_scope_id == 0) {
+                                               dst6->sin6_scope_id = ntohs(index);
+                                       }
+                               }
+                       }
+
+                       appendAddress(newDict, kSCPropNetIPv6DestAddresses, dst6);
+               }
+
+               CFDictionarySetValue(newIFs, key, newDict);
+               CFRelease(newDict);
+               CFRelease(key);
+       }
+
+       /* if the last address[es] were removed from the target interface */
+       if (if_name && !interfaceFound) {
+               interface = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingMacRoman);
+               key       = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+                                                                         kSCDynamicStoreDomainState,
+                                                                         interface,
+                                                                         kSCEntNetIPv6);
+               CFRelease(interface);
+
+               newDict = getIF(key, oldIFs, newIFs);
+
+               CFDictionarySetValue(newIFs, key, newDict);
+               CFRelease(newDict);
+               CFRelease(key);
+       }
+
+       CFDictionaryApplyFunction(newIFs, updateStore, oldIFs);
+
+    error :
+
+       if (ifap_temp)  freeifaddrs(ifap_temp);
+       if (sock >= 0)  close(sock);
+       CFRelease(oldIFs);
+       CFRelease(newIFs);
+
+       return;
+}
diff --git a/Plugins/KernelEventMonitor/ev_ipv6.h b/Plugins/KernelEventMonitor/ev_ipv6.h
new file mode 100644 (file)
index 0000000..24113d5
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#ifndef _EV_IPV6_H
+#define _EV_IPV6_H
+
+#include <netinet6/in6_var.h>
+
+__BEGIN_DECLS
+
+void   interface_update_ipv6   (struct ifaddrs *ifap, const char *if_name);
+
+__END_DECLS
+
+#endif /* _EV_IPV6_H */
+
diff --git a/Plugins/KernelEventMonitor/eventmon.c b/Plugins/KernelEventMonitor/eventmon.c
new file mode 100644 (file)
index 0000000..24946f3
--- /dev/null
@@ -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 <dieter@apple.com>
+ * - handle the new KEV_INET_ARPCOLLISION event
+ * - format the event into a DynamicStore key
+ *     State:/Network/Interface/ifname/IPv4Collision/ip_addr/hw_addr
+ *   and send a notification on the key
+ *
+ * August 8, 2002              Allan Nathanson <ajn@apple.com>
+ * - added support for KEV_INET6_xxx events
+ *
+ * January 6, 2002             Jessica Vazquez <vazquez@apple.com>
+ * - added handling for KEV_ATALK_xxx events
+ *
+ * July 2, 2001                        Dieter Siegmund <dieter@apple.com>
+ * - added handling for KEV_DL_PROTO_{ATTACHED, DETACHED}
+ * - mark an interface up if the number of protocols remaining is not 0,
+ *   mark an interface down if the number is zero
+ * - allocate socket on demand instead of keeping it open all the time
+ *
+ * June 23, 2001               Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * May 17, 2001                        Allan Nathanson <ajn@apple.com>
+ * - add/maintain per-interface address/netmask/destaddr information
+ *   in the dynamic store.
+ *
+ * June 30, 2000               Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include "eventmon.h"
+#include "cache.h"
+#include "ev_dlil.h"
+#include "ev_ipv4.h"
+#include "ev_ipv6.h"
+#include "ev_appletalk.h"
+
+static const char *inetEventName[] = {
+       "",
+       "INET address added",
+       "INET address changed",
+       "INET address deleted",
+       "INET destination address changed",
+       "INET broadcast address changed",
+       "INET netmask changed",
+       "INET ARP collision",
+};
+
+static const char *dlEventName[] = {
+       "",
+       "KEV_DL_SIFFLAGS",
+       "KEV_DL_SIFMETRICS",
+       "KEV_DL_SIFMTU",
+       "KEV_DL_SIFPHYS",
+       "KEV_DL_SIFMEDIA",
+       "KEV_DL_SIFGENERIC",
+       "KEV_DL_ADDMULTI",
+       "KEV_DL_DELMULTI",
+       "KEV_DL_IF_ATTACHED",
+       "KEV_DL_IF_DETACHING",
+       "KEV_DL_IF_DETACHED",
+       "KEV_DL_LINK_OFF",
+       "KEV_DL_LINK_ON",
+       "KEV_DL_PROTO_ATTACHED",
+       "KEV_DL_PROTO_DETACHED",
+};
+
+static const char *atalkEventName[] = {
+       "",
+       "KEV_ATALK_ENABLED",
+       "KEV_ATALK_DISABLED",
+       "KEV_ATALK_ZONEUPDATED",
+       "KEV_ATALK_ROUTERUP",
+       "KEV_ATALK_ROUTERUP_INVALID",
+       "KEV_ATALK_ROUTERDOWN",
+       "KEV_ATALK_ZONELISTCHANGED"
+};
+
+static const char *inet6EventName[] = {
+       "",
+       "KEV_INET6_NEW_USER_ADDR",
+       "KEV_INET6_CHANGED_ADDR",
+       "KEV_INET6_ADDR_DELETED",
+       "KEV_INET6_NEW_LL_ADDR",
+       "KEV_INET6_NEW_RTADV_ADDR",
+       "KEV_INET6_DEFROUTER"
+
+};
+
+
+__private_extern__ SCDynamicStoreRef   store           = NULL;
+__private_extern__ Boolean             _verbose        = FALSE;
+
+
+__private_extern__
+int
+dgram_socket(int domain)
+{
+    return (socket(domain, SOCK_DGRAM, 0));
+}
+
+static int
+ifflags_set(int s, char * name, short flags)
+{
+    struct ifreq       ifr;
+    int                ret;
+
+    bzero(&ifr, sizeof(ifr));
+    strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+    ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
+    if (ret < 0) {
+               return (ret);
+    }
+    ifr.ifr_flags |= flags;
+    return (ioctl(s, SIOCSIFFLAGS, &ifr));
+}
+
+static int
+ifflags_clear(int s, char * name, short flags)
+{
+    struct ifreq       ifr;
+    int                ret;
+
+    bzero(&ifr, sizeof(ifr));
+    strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+    ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
+    if (ret < 0) {
+               return (ret);
+    }
+    ifr.ifr_flags &= ~flags;
+    return (ioctl(s, SIOCSIFFLAGS, &ifr));
+}
+
+static void
+mark_if_up(char * name)
+{
+       int s = dgram_socket(AF_INET);
+       if (s < 0)
+               return;
+       ifflags_set(s, name, IFF_UP);
+       close(s);
+}
+
+static void
+mark_if_down(char * name)
+{
+       int s = dgram_socket(AF_INET);
+       if (s < 0)
+               return;
+       ifflags_clear(s, name, IFF_UP);
+       close(s);
+}
+
+static void
+logEvent(CFStringRef evStr, struct kern_event_msg *ev_msg)
+{
+       int     i;
+       int     j;
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("%@ event:"), evStr);
+       SCLog(_verbose, LOG_DEBUG,
+             CFSTR("  Event size=%d, id=%d, vendor=%d, class=%d, subclass=%d, code=%d"),
+             ev_msg->total_size,
+             ev_msg->id,
+             ev_msg->vendor_code,
+             ev_msg->kev_class,
+             ev_msg->kev_subclass,
+             ev_msg->event_code);
+       for (i = 0, j = KEV_MSG_HEADER_SIZE; j < ev_msg->total_size; i++, j+=4) {
+               SCLog(_verbose, LOG_DEBUG, CFSTR("  Event data[%2d] = %08lx"), i, ev_msg->event_data[i]);
+       }
+}
+
+static const char *
+inetEventNameString(u_long event_code)
+{
+       if (event_code <= KEV_INET_ARPCOLLISION) {
+               return (inetEventName[event_code]);
+       }
+       return ("New Apple network INET subcode");
+}
+
+static const char *
+inet6EventNameString(u_long event_code)
+{
+       if (event_code <= KEV_INET6_DEFROUTER) {
+               return (inet6EventName[event_code]);
+       }
+       return ("New Apple network INET6 subcode");
+}
+
+static const char *
+dlEventNameString(u_long event_code)
+{
+       if (event_code <= KEV_DL_PROTO_DETACHED) {
+               return (dlEventName[event_code]);
+       }
+       return ("New Apple network DL subcode");
+}
+
+static const char *
+atalkEventNameString(u_long event_code)
+{
+       if (event_code <= KEV_ATALK_ZONELISTCHANGED) {
+               return (atalkEventName[event_code]);
+       }
+       return ("New Apple network AppleTalk subcode");
+}
+
+
+static void
+copy_if_name(struct net_event_data * ev, char * ifr_name, int ifr_len)
+{
+       snprintf(ifr_name, ifr_len, "%s%ld", ev->if_name, ev->if_unit);
+       return;
+}
+
+static void
+processEvent_Apple_Network(struct kern_event_msg *ev_msg)
+{
+       const char *                    eventName = NULL;
+       int                             dataLen = (ev_msg->total_size - KEV_MSG_HEADER_SIZE);
+       void *                          event_data = &ev_msg->event_data[0];
+       Boolean                         handled = TRUE;
+       char                            ifr_name[IFNAMSIZ+1];
+
+       switch (ev_msg->kev_subclass) {
+               case KEV_INET_SUBCLASS : {
+                       eventName = inetEventNameString(ev_msg->event_code);
+                       switch (ev_msg->event_code) {
+                               case KEV_INET_NEW_ADDR :
+                               case KEV_INET_CHANGED_ADDR :
+                               case KEV_INET_ADDR_DELETED :
+                               case KEV_INET_SIFDSTADDR :
+                               case KEV_INET_SIFBRDADDR :
+                               case KEV_INET_SIFNETMASK : {
+                                       struct kev_in_data * ev;
+
+                                       ev = (struct kev_in_data *)event_data;
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+                                       interface_update_ipv4(NULL, ifr_name);
+                                       break;
+                               }
+                               case KEV_INET_ARPCOLLISION : {
+                                       struct kev_in_collision * ev;
+
+                                       ev = (struct kev_in_collision *)event_data;
+                                       if ((dataLen < sizeof(*ev))
+                                           || (dataLen < (sizeof(*ev) + ev->hw_len))) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+                                       interface_collision_ipv4(ifr_name,
+                                                                ev->ia_ipaddr,
+                                                                ev->hw_len,
+                                                                ev->hw_addr);
+                                       break;
+                               }
+                               default :
+                                       handled = FALSE;
+                                       break;
+                       }
+                       break;
+               }
+               case KEV_INET6_SUBCLASS : {
+                       struct kev_in6_data * ev;
+
+                       eventName = inet6EventNameString(ev_msg->event_code);
+                       ev = (struct kev_in6_data *)event_data;
+                       switch (ev_msg->event_code) {
+                               case KEV_INET6_NEW_USER_ADDR :
+                               case KEV_INET6_CHANGED_ADDR :
+                               case KEV_INET6_ADDR_DELETED :
+                               case KEV_INET6_NEW_LL_ADDR :
+                               case KEV_INET6_NEW_RTADV_ADDR :
+                               case KEV_INET6_DEFROUTER :
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+                                       interface_update_ipv6(NULL, ifr_name);
+                                       break;
+
+                               default :
+                                       handled = FALSE;
+                                       break;
+                       }
+                       break;
+               }
+               case KEV_DL_SUBCLASS : {
+                       struct net_event_data * ev;
+
+                       eventName = dlEventNameString(ev_msg->event_code);
+                       ev = (struct net_event_data *)event_data;
+                       switch (ev_msg->event_code) {
+                               case KEV_DL_IF_ATTACHED :
+                                       /*
+                                        * new interface added
+                                        */
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(ev, ifr_name, sizeof(ifr_name));
+                                       link_add(ifr_name);
+                                       break;
+
+                               case KEV_DL_IF_DETACHED :
+                                       /*
+                                        * interface removed
+                                        */
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(ev, ifr_name, sizeof(ifr_name));
+                                       link_remove(ifr_name);
+                                       break;
+
+                               case KEV_DL_IF_DETACHING :
+                                       /*
+                                        * interface detaching
+                                        */
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(ev, ifr_name, sizeof(ifr_name));
+                                       interface_detaching(ifr_name);
+                                       break;
+
+                               case KEV_DL_SIFFLAGS :
+                               case KEV_DL_SIFMETRICS :
+                               case KEV_DL_SIFMTU :
+                               case KEV_DL_SIFPHYS :
+                               case KEV_DL_SIFMEDIA :
+                               case KEV_DL_SIFGENERIC :
+                               case KEV_DL_ADDMULTI :
+                               case KEV_DL_DELMULTI :
+                                       handled = FALSE;
+                                       break;
+
+                               case KEV_DL_PROTO_ATTACHED :
+                               case KEV_DL_PROTO_DETACHED : {
+                                       struct kev_dl_proto_data * protoEvent;
+
+                                       protoEvent = (struct kev_dl_proto_data *)event_data;
+                                       if (dataLen < sizeof(*protoEvent)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(&protoEvent->link_data,
+                                                    ifr_name, sizeof(ifr_name));
+                                       if (protoEvent->proto_remaining_count == 0) {
+                                               mark_if_down(ifr_name);
+                                       } else {
+                                               mark_if_up(ifr_name);
+                                       }
+                                       break;
+                               }
+
+                               case KEV_DL_LINK_OFF :
+                               case KEV_DL_LINK_ON :
+                                       /*
+                                        * update the link status in the store
+                                        */
+                                       if (dataLen < sizeof(*ev)) {
+                                               handled = FALSE;
+                                               break;
+                                       }
+                                       copy_if_name(ev, ifr_name, sizeof(ifr_name));
+                                       link_update_status(ifr_name, FALSE);
+                                       break;
+
+                               default :
+                                       handled = FALSE;
+                                       break;
+                       }
+                       break;
+               }
+               case KEV_ATALK_SUBCLASS: {
+                       struct kev_atalk_data * ev;
+
+                       eventName = atalkEventNameString(ev_msg->event_code);
+                       ev = (struct kev_atalk_data *)event_data;
+                       if (dataLen < sizeof(*ev)) {
+                               handled = FALSE;
+                               break;
+                       }
+                       copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
+                       switch (ev_msg->event_code) {
+                               case KEV_ATALK_ENABLED:
+                                       interface_update_atalk_address(ev, ifr_name);
+                                       break;
+
+                               case KEV_ATALK_DISABLED:
+                                       interface_update_shutdown_atalk();
+                                       break;
+
+                               case KEV_ATALK_ZONEUPDATED:
+                                       interface_update_atalk_zone(ev, ifr_name);
+                                       break;
+
+                               case KEV_ATALK_ROUTERUP:
+                               case KEV_ATALK_ROUTERUP_INVALID:
+                               case KEV_ATALK_ROUTERDOWN:
+                                       interface_update_appletalk(NULL, ifr_name);
+                                       break;
+
+                               case KEV_ATALK_ZONELISTCHANGED:
+                                       break;
+
+                               default :
+                                       handled = FALSE;
+                                       break;
+                       }
+                       break;
+               }
+               default :
+                       handled = FALSE;
+                       break;
+       }
+
+       if (handled == FALSE) {
+               CFStringRef     evStr;
+
+               evStr = CFStringCreateWithCString(NULL,
+                                                 (eventName != NULL) ? eventName : "New Apple network subclass",
+                                                 kCFStringEncodingASCII);
+               logEvent(evStr, ev_msg);
+               CFRelease(evStr);
+       }
+       return;
+}
+
+
+static void
+processEvent_Apple_IOKit(struct kern_event_msg *ev_msg)
+{
+       switch (ev_msg->kev_subclass) {
+               default :
+                       logEvent(CFSTR("New Apple IOKit subclass"), ev_msg);
+                       break;
+       }
+
+       return;
+}
+
+
+static void
+eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
+{
+       int                     so              = CFSocketGetNative(s);
+       int                     status;
+       char                    buf[1024];
+       struct kern_event_msg   *ev_msg         = (struct kern_event_msg *)&buf[0];
+       int                     offset          = 0;
+
+       status = recv(so, &buf, sizeof(buf), 0);
+       if (status == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("recv() failed: %s"), strerror(errno));
+               goto error;
+       }
+
+       cache_open();
+
+       while (offset < status) {
+               if ((offset + ev_msg->total_size) > status) {
+                       SCLog(TRUE, LOG_NOTICE, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough"));
+                       break;
+               }
+
+               switch (ev_msg->vendor_code) {
+                       case KEV_VENDOR_APPLE :
+                               switch (ev_msg->kev_class) {
+                                       case KEV_NETWORK_CLASS :
+                                               processEvent_Apple_Network(ev_msg);
+                                               break;
+                                       case KEV_IOKIT_CLASS :
+                                               processEvent_Apple_IOKit(ev_msg);
+                                               break;
+                                       default :
+                                               /* unrecognized (Apple) event class */
+                                               logEvent(CFSTR("New (Apple) class"), ev_msg);
+                                               break;
+                               }
+                               break;
+                       default :
+                               /* unrecognized vendor code */
+                               logEvent(CFSTR("New vendor"), ev_msg);
+                               break;
+               }
+               offset += ev_msg->total_size;
+               ev_msg = (struct kern_event_msg *)&buf[offset];
+       }
+
+       cache_write(store);
+       cache_close();
+
+       return;
+
+    error :
+
+       SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
+       CFSocketInvalidate(s);
+       return;
+
+}
+
+
+__private_extern__
+void
+prime_KernelEventMonitor()
+{
+       struct ifaddrs  *ifap   = NULL;
+       struct ifaddrs  *scan;
+       int             sock    = -1;
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
+
+       cache_open();
+
+       sock = dgram_socket(AF_INET);
+       if (sock == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("could not get interface list, socket() failed: %s"), strerror(errno));
+               goto done;
+       }
+
+       if (getifaddrs(&ifap) < 0) {
+               SCLog(TRUE,
+                     LOG_ERR,
+                     CFSTR("could not get interface info, getifaddrs() failed: %s"),
+                     strerror(errno));
+               goto done;
+       }
+
+       /* update list of interfaces & link status */
+       for (scan = ifap; scan != NULL; scan = scan->ifa_next) {
+               if (scan->ifa_addr == NULL
+                   || scan->ifa_addr->sa_family != AF_LINK) {
+                       continue;
+               }
+               /* get the per-interface link/media information */
+               link_add(scan->ifa_name);
+       }
+
+       /*
+        * update IPv4 network addresses already assigned to
+        * the interfaces.
+        */
+       interface_update_ipv4(ifap, NULL);
+
+       /*
+        * update IPv6 network addresses already assigned to
+        * the interfaces.
+        */
+       interface_update_ipv6(ifap, NULL);
+
+       /*
+        * update AppleTalk network addresses already assigned
+        * to the interfaces.
+        */
+       interface_update_appletalk(ifap, NULL);
+
+       freeifaddrs(ifap);
+
+ done:
+       if (sock >= 0)
+               close(sock);
+
+       cache_write(store);
+       cache_close();
+
+       return;
+}
+
+
+__private_extern__
+void
+load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
+{
+       int                     so;
+       int                     status;
+       struct kev_request      kev_req;
+       CFSocketRef             es;
+       CFSocketContext         context = { 0, NULL, NULL, NULL, NULL };
+       CFRunLoopSourceRef      rls;
+
+       if (bundleVerbose) {
+               _verbose = TRUE;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+       SCLog(_verbose, LOG_DEBUG, CFSTR("  bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+       /* open a "configd" session to allow cache updates */
+       store = SCDynamicStoreCreate(NULL,
+                                    CFSTR("Kernel Event Monitor plug-in"),
+                                    NULL,
+                                    NULL);
+       if (!store) {
+               SCLog(TRUE, LOG_ERR, CFSTR("SCDnamicStoreCreate() failed: %s"), SCErrorString(SCError()));
+               SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
+               return;
+       }
+
+       /* Open an event socket */
+       so = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
+       if (so != -1) {
+               /* establish filter to return all events */
+               kev_req.vendor_code  = 0;
+               kev_req.kev_class    = 0;       /* Not used if vendor_code is 0 */
+               kev_req.kev_subclass = 0;       /* Not used if either kev_class OR vendor_code are 0 */
+               status = ioctl(so, SIOCSKEVFILT, &kev_req);
+               if (status) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("could not establish event filter, ioctl() failed: %s"), strerror(errno));
+                       (void) close(so);
+                       so = -1;
+               }
+       } else {
+               SCLog(TRUE, LOG_ERR, CFSTR("could not open event socket, socket() failed: %s"), strerror(errno));
+       }
+
+       if (so != -1) {
+               int     yes = 1;
+
+               status = ioctl(so, FIONBIO, &yes);
+               if (status) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("could not set non-blocking io, ioctl() failed: %s"), strerror(errno));
+                       (void) close(so);
+                       so = -1;
+               }
+       }
+
+       if (so == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
+               CFRelease(store);
+               return;
+       }
+
+       /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */
+       es  = CFSocketCreateWithNative(NULL,
+                                      so,
+                                      kCFSocketReadCallBack,
+                                      eventCallback,
+                                      &context);
+
+       /* Create and add a run loop source for the event socket */
+       rls = CFSocketCreateRunLoopSource(NULL, es, 0);
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+       CFRelease(rls);
+       CFRelease(es);
+
+       return;
+}
+
+#ifdef MAIN
+
+#include "ev_dlil.c"
+
+#define appendAddress  appendAddress_v4
+#define getIF          getIF_v4
+#define updateStore    updateStore_v4
+#include "ev_ipv4.c"
+#undef appendAddress
+#undef getIF
+#undef updateStore
+
+#define appendAddress  appendAddress_v6
+#define getIF          getIF_v6
+#define updateStore    updateStore_v6
+#include "ev_ipv6.c"
+#undef appendAddress
+#undef getIF
+#undef updateStore
+
+#define getIF          getIF_at
+#define updateStore    updateStore_at
+#include "ev_appletalk.c"
+#undef getIF
+#undef updateStore
+
+int
+main(int argc, char **argv)
+{
+       _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+       load_KernelEventMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+       prime_KernelEventMonitor();
+       CFRunLoopRun();
+       /* not reached */
+       exit(0);
+       return 0;
+}
+#endif
diff --git a/Plugins/KernelEventMonitor/eventmon.h b/Plugins/KernelEventMonitor/eventmon.h
new file mode 100644 (file)
index 0000000..ed6054c
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - split code out from eventmon.c
+ */
+
+
+#ifndef _EVENTMON_H
+#define _EVENTMON_H
+
+#include <sys/cdefs.h>
+#include <unistd.h>
+#include <sys/types.h>
+#define        KERNEL_PRIVATE
+#include <sys/sockio.h>
+#undef KERNEL_PRIVATE
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/filio.h>
+#include <sys/kern_event.h>
+#include <errno.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+
+extern SCDynamicStoreRef       store;
+extern Boolean                 _verbose;
+
+
+__BEGIN_DECLS
+
+int    dgram_socket            (int    domain);
+
+__END_DECLS
+
+#endif /* _EVENTMON_H */
+
diff --git a/Plugins/Kicker/Info.plist b/Plugins/Kicker/Info.plist
new file mode 100644 (file)
index 0000000..d692f89
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>Kicker</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.Kicker</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Requires</key>
+       <array>
+               <string>com.apple.SystemConfiguration.ATconfig</string>
+               <string>com.apple.SystemConfiguration.IPConfiguration</string>
+               <string>com.apple.SystemConfiguration.IPMonitor</string>
+       </array>
+       <key>Builtin</key>
+       <true/>
+</dict>
+</plist>
diff --git a/Plugins/Kicker/Kicker.xml b/Plugins/Kicker/Kicker.xml
new file mode 100644 (file)
index 0000000..182a9aa
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+       <dict>
+               <key>execCommand</key>
+               <string>$BUNDLE/Contents/Resources/enable-network</string>
+               <key>execUID</key>
+               <integer>0</integer>
+               <key>keys</key>
+               <array>
+                       <string>State:/Network/Global/IPv4</string>
+               </array>
+               <key>name</key>
+               <string>enable-network</string>
+       </dict>
+       <dict>
+               <key>keys</key>
+               <array>
+                       <string>State:/Network/Global/DNS</string>
+                       <string>State:/Network/Global/IPv4</string>
+                       <string>State:/Network/Global/IPv6</string>
+                       <string>State:/Network/Global/NetInfo</string>
+               </array>
+               <key>name</key>
+               <string>network_change</string>
+               <key>postName</key>
+               <string>com.apple.system.config.network_change</string>
+       </dict>
+       <dict>
+               <key>execCommand</key>
+               <string>/usr/sbin/AppleFileServer</string>
+               <key>execUID</key>
+               <integer>0</integer>
+               <key>keys</key>
+               <array>
+                       <string>daemon:AppleFileServer</string>
+               </array>
+               <key>name</key>
+               <string>AppleFileServer</string>
+       </dict>
+</array>
+</plist>
diff --git a/Plugins/Kicker/enable-network b/Plugins/Kicker/enable-network
new file mode 100755 (executable)
index 0000000..b68cc8d
--- /dev/null
@@ -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 (file)
index 0000000..efc49aa
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - updated to use _SCDPluginExecCommand()
+ *
+ * June 23, 2001               Allan Nathanson <ajn@apple.com>
+ * - updated to public SystemConfiguration.framework APIs
+ *
+ * June 4, 2001                        Allan Nathanson <ajn@apple.com>
+ * - add changed keys as the arguments to the kicker script
+ *
+ * June 30, 2000               Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <notify.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>     // for SCLog()
+#include <SystemConfiguration/SCDPlugin.h>
+#include <SystemConfiguration/SCValidation.h>
+
+/*
+ * Information maintained for each to-be-kicked registration.
+ */
+typedef struct {
+       boolean_t               active;
+       boolean_t               needsKick;
+
+       /* dictionary associated with this target */
+       CFDictionaryRef         dict;
+
+       /* SCDynamicStore session information for this target */
+       CFRunLoopRef            rl;
+       CFRunLoopSourceRef      rls;
+       SCDynamicStoreRef       store;
+
+       /* changed keys */
+       CFMutableArrayRef       changedKeys;
+} kickee, *kickeeRef;
+
+static CFURLRef        myBundleURL     = NULL;
+static Boolean _verbose        = FALSE;
+
+static void booter(kickeeRef target);
+static void booterExit(pid_t pid, int status, struct rusage *rusage, void *context);
+
+
+static void
+cleanupKicker(kickeeRef target)
+{
+       CFStringRef             name    = CFDictionaryGetValue(target->dict, CFSTR("name"));
+
+       SCLog(TRUE, LOG_NOTICE,
+             CFSTR("  target=%@: disabled"),
+             name);
+       CFRunLoopRemoveSource(target->rl, target->rls, kCFRunLoopDefaultMode);
+       CFRelease(target->rls);
+       CFRelease(target->store);
+       if (target->dict)               CFRelease(target->dict);
+       if (target->changedKeys)        CFRelease(target->changedKeys);
+       CFAllocatorDeallocate(NULL, target);
+}
+
+
+static void
+booter(kickeeRef target)
+{
+       char                    **argv          = NULL;
+       char                    *cmd            = NULL;
+       CFStringRef             execCommand     = CFDictionaryGetValue(target->dict, CFSTR("execCommand"));
+       int                     i;
+       CFArrayRef              keys            = NULL;
+       CFStringRef             name            = CFDictionaryGetValue(target->dict, CFSTR("name"));
+       int                     nKeys           = 0;
+       Boolean                 ok              = FALSE;
+       CFStringRef             postName        = CFDictionaryGetValue(target->dict, CFSTR("postName"));
+
+       if (target->active) {
+               /* we need another kick! */
+               target->needsKick = TRUE;
+
+               SCLog(_verbose, LOG_DEBUG, CFSTR("Kicker callback, target=%@ request queued"), name);
+               return;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("Kicker callback, target=%@"), name);
+
+       if (!isA_CFString(postName) && !isA_CFString(execCommand)) {
+               goto error;     /* if no notifications to post nor commands to execute */
+       }
+
+       if (isA_CFString(postName)) {
+               uint32_t        status;
+
+               /*
+                * post a notification
+                */
+               cmd = _SC_cfstring_to_cstring(postName, NULL, 0, kCFStringEncodingASCII);
+               if (!cmd) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("  could not convert post name to C string"));
+                       goto error;
+               }
+
+               SCLog(TRUE, LOG_NOTICE, CFSTR("posting notification %s"), cmd);
+               status = notify_post(cmd);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("  notify_post() failed: error=%ld"), status);
+                       goto error;
+               }
+
+               CFAllocatorDeallocate(NULL, cmd);       /* clean up */
+               cmd = NULL;
+       }
+
+       /*
+        * get the arguments for the kickee
+        */
+       keys = target->changedKeys;
+       target->changedKeys = NULL;
+
+       if (isA_CFString(execCommand)) {
+               CFRange                 bpr;
+               CFNumberRef             execGID         = CFDictionaryGetValue(target->dict, CFSTR("execGID"));
+               CFNumberRef             execUID         = CFDictionaryGetValue(target->dict, CFSTR("execUID"));
+               CFBooleanRef            passKeys        = CFDictionaryGetValue(target->dict, CFSTR("changedKeysAsArguments"));
+               gid_t                   reqGID          = 0;
+               uid_t                   reqUID          = 0;
+               CFMutableStringRef      str;
+
+               /*
+                * build the kickee command
+                */
+               str = CFStringCreateMutableCopy(NULL, 0, execCommand);
+               bpr = CFStringFind(str, CFSTR("$BUNDLE"), 0);
+               if (bpr.location != kCFNotFound) {
+                       CFStringRef     bundlePath;
+
+                       bundlePath = CFURLCopyFileSystemPath(myBundleURL, kCFURLPOSIXPathStyle);
+                       CFStringReplace(str, bpr, bundlePath);
+                       CFRelease(bundlePath);
+               }
+
+               cmd = _SC_cfstring_to_cstring(str, NULL, 0, kCFStringEncodingASCII);
+               CFRelease(str);
+               if (!cmd) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("  could not convert command to C string"));
+                       goto error;
+               }
+
+               /*
+                * get the UID/GID for the kickee
+                */
+               if (isA_CFNumber(execUID)) {
+                       CFNumberGetValue(execUID, kCFNumberIntType, &reqUID);
+               }
+
+               if (isA_CFNumber(execGID)) {
+                       CFNumberGetValue(execGID, kCFNumberIntType, &reqGID);
+               }
+
+               nKeys = CFArrayGetCount(keys);
+               argv  = CFAllocatorAllocate(NULL, (nKeys + 2) * sizeof(char *), 0);
+               for (i = 0; i < (nKeys + 2); i++) {
+                       argv[i] = NULL;
+               }
+
+               /* create command name argument */
+               if ((argv[0] = rindex(cmd, '/')) != NULL) {
+                       argv[0]++;
+               } else {
+                       argv[0] = cmd;
+               }
+
+               /* create changed key arguments */
+               if (isA_CFBoolean(passKeys) && CFBooleanGetValue(passKeys)) {
+                       for (i = 0; i < nKeys; i++) {
+                               CFStringRef     key = CFArrayGetValueAtIndex(keys, i);
+
+                               argv[i+1] = _SC_cfstring_to_cstring(key, NULL, 0, kCFStringEncodingASCII);
+                               if (!argv[i+1]) {
+                                       SCLog(TRUE, LOG_DEBUG, CFSTR("  could not convert argument to C string"));
+                                       goto error;
+                               }
+                       }
+               }
+
+               SCLog(TRUE,     LOG_NOTICE, CFSTR("executing %s"), cmd);
+               SCLog(_verbose, LOG_DEBUG,  CFSTR("  current uid = %d, requested = %d"), geteuid(), reqUID);
+
+               /* this kicker is now "running" */
+               target->active = TRUE;
+
+               (void)_SCDPluginExecCommand(booterExit,
+                             target,
+                             reqUID,
+                             reqGID,
+                             cmd,
+                             argv);
+
+//             CFAllocatorDeallocate(NULL, cmd);       /* clean up */
+//             cmd = NULL;
+       }
+       ok = TRUE;
+
+    error :
+
+       if (keys)       CFRelease(keys);
+       if (cmd)        CFAllocatorDeallocate(NULL, cmd);
+       if (argv) {
+               for (i = 0; i < nKeys; i++) {
+                       if (argv[i+1]) {
+                               CFAllocatorDeallocate(NULL, argv[i+1]);
+                       }
+               }
+               CFAllocatorDeallocate(NULL, argv);
+       }
+
+       if (!ok) {
+               /*
+                * If the target action can't be performed this time then
+                * there's not much point in trying again. As such, I close
+                * the session and the kickee target released.
+                */
+               cleanupKicker(target);
+       }
+
+       return;
+}
+
+
+static void
+booterExit(pid_t pid, int status, struct rusage *rusage, void *context)
+{
+       CFStringRef     name;
+       Boolean         ok      = TRUE;
+       kickeeRef       target  = (kickeeRef)context;
+
+       name = CFDictionaryGetValue(target->dict, CFSTR("name"));
+       target->active = FALSE;
+       if (WIFEXITED(status)) {
+               SCLog(TRUE, LOG_DEBUG,
+                     CFSTR("  target=%@: exit status = %d"),
+                     name,
+                     WEXITSTATUS(status));
+               if (WEXITSTATUS(status) != 0) {
+                       ok = FALSE;
+               }
+       } else if (WIFSIGNALED(status)) {
+               SCLog(TRUE, LOG_DEBUG,
+                     CFSTR("  target=%@: terminated w/signal = %d"),
+                     name,
+                     WTERMSIG(status));
+               ok = FALSE;
+       } else {
+               SCLog(TRUE, LOG_DEBUG,
+                     CFSTR("  target=%@: exit status = %d"),
+                     name,
+                     status);
+               ok = FALSE;
+       }
+
+       if (!ok) {
+               if (CFDictionaryContainsKey(target->dict, CFSTR("postName"))) {
+                       CFDictionaryRef         oldDict = target->dict;
+                       CFMutableDictionaryRef  newDict = CFDictionaryCreateMutableCopy(NULL, 0, oldDict);
+
+                       /*
+                        * if this target specifies both a BSD notification and
+                        * a script to be executed then we want to continue to
+                        * post the BSD notifications (and not execute the
+                        * script).  As such, remove the script reference from
+                        * the dictionary.
+                        */
+                       CFDictionaryRemoveValue(newDict, CFSTR("execCommand"));
+                       CFDictionaryRemoveValue(newDict, CFSTR("execGID"));
+                       CFDictionaryRemoveValue(newDict, CFSTR("execUID"));
+                       CFDictionaryRemoveValue(newDict, CFSTR("changedKeysAsArguments"));
+                       target->dict = newDict;
+                       CFRelease(oldDict);
+               } else {
+                       /*
+                        * If the target action can't be performed this time then
+                        * there's not much point in trying again. As such, I close
+                        * the session and the kickee target released.
+                        */
+                       cleanupKicker(target);
+                       target = NULL;
+               }
+       } 
+       if (target != NULL && target->needsKick) {
+               target->needsKick = FALSE;
+               booter(target);
+       }
+
+       return;
+}
+
+
+static void
+kicker(SCDynamicStoreRef store, CFArrayRef changedKeys, void *arg)
+{
+       CFIndex         i;
+       CFIndex         n               = CFArrayGetCount(changedKeys);
+       kickeeRef       target          = (kickeeRef)arg;
+
+       /*
+        * Start a new kicker.  If a kicker was already active then flag
+        * the need for a second kick after the active one completes.
+        */
+
+       /* create (or add to) the full list of keys that have changed */
+       if (!target->changedKeys) {
+               target->changedKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+       for (i = 0; i < n; i++) {
+               CFStringRef     key = CFArrayGetValueAtIndex(changedKeys, i);
+
+               if (!CFArrayContainsValue(target->changedKeys,
+                                         CFRangeMake(0, CFArrayGetCount(target->changedKeys)),
+                                         key)) {
+                       CFArrayAppendValue(target->changedKeys, key);
+               }
+       }
+
+       /*
+        * let 'er rip.
+        */
+       booter(target);
+
+       return;
+}
+
+
+/*
+ * startKicker()
+ *
+ * The first argument is a dictionary representing the keys
+ * which need to be monitored for a given "target" and what
+ * action should be taken if a change in one of those keys
+ * is detected.
+ */
+static void
+startKicker(const void *value, void *context)
+{
+       CFMutableStringRef      name;
+       CFArrayRef              keys;
+       CFArrayRef              patterns;
+       kickeeRef               target          = CFAllocatorAllocate(NULL, sizeof(kickee), 0);
+       SCDynamicStoreContext   targetContext   = { 0, (void *)target, NULL, NULL, NULL };
+
+       target->active          = FALSE;
+       target->needsKick       = FALSE;
+       target->dict            = CFRetain((CFDictionaryRef)value);
+       target->store           = NULL;
+       target->rl              = NULL;
+       target->rls             = NULL;
+       target->changedKeys     = NULL;
+
+       name = CFStringCreateMutableCopy(NULL,
+                                        0,
+                                        CFDictionaryGetValue(target->dict, CFSTR("name")));
+       SCLog(TRUE, LOG_DEBUG, CFSTR("Starting kicker for %@"), name);
+
+       CFStringAppend(name, CFSTR(" \"Kicker\""));
+       target->store = SCDynamicStoreCreate(NULL, name, kicker, &targetContext);
+       CFRelease(name);
+       if (!target->store) {
+               SCLog(TRUE,
+                     LOG_NOTICE,
+                     CFSTR("SCDynamicStoreCreate() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       keys     = isA_CFArray(CFDictionaryGetValue(target->dict, CFSTR("keys")));
+       patterns = isA_CFArray(CFDictionaryGetValue(target->dict, CFSTR("regexKeys")));
+       if (!SCDynamicStoreSetNotificationKeys(target->store, keys, patterns)) {
+               SCLog(TRUE,
+                     LOG_NOTICE,
+                     CFSTR("SCDynamicStoreSetNotifications() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       target->rl  = CFRunLoopGetCurrent();
+       target->rls = SCDynamicStoreCreateRunLoopSource(NULL, target->store, 0);
+       if (!target->rls) {
+               SCLog(TRUE,
+                     LOG_NOTICE,
+                     CFSTR("SCDynamicStoreCreateRunLoopSource() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       CFRunLoopAddSource(target->rl, target->rls, kCFRunLoopDefaultMode);
+       return;
+
+    error :
+
+       CFRelease(target->dict);
+       if (target->store)      CFRelease(target->store);
+       CFAllocatorDeallocate(NULL, target);
+       return;
+}
+
+
+static CFArrayRef
+getTargets(CFBundleRef bundle)
+{
+       Boolean                 ok;
+       CFArrayRef              targets;        /* The array of dictionaries
+                                                  representing targets with
+                                                  a "kick me" sign posted on
+                                                  their backs. */
+       CFURLRef                url;
+       CFStringRef             xmlError;
+       CFDataRef               xmlTargets      = NULL;
+
+       /* locate the Kicker targets */
+       url = CFBundleCopyResourceURL(bundle, CFSTR("Kicker"), CFSTR("xml"), NULL);
+       if (url == NULL) {
+               return NULL;
+       }
+
+       /* read the resource data */
+       ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlTargets, NULL, NULL, NULL);
+       CFRelease(url);
+       if (!ok || (xmlTargets == NULL)) {
+               return NULL;
+       }
+
+       /* convert the XML data into a property list */
+       targets = CFPropertyListCreateFromXMLData(NULL,
+                                                 xmlTargets,
+                                                 kCFPropertyListImmutable,
+                                                 &xmlError);
+       CFRelease(xmlTargets);
+       if (targets == NULL) {
+               if (xmlError != NULL) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("getTargets(): %@"), xmlError);
+                       CFRelease(xmlError);
+               }
+               return NULL;
+       }
+
+       if (!isA_CFArray(targets)) {
+               CFRelease(targets);
+               targets = NULL;
+       }
+
+       return targets;
+}
+
+
+__private_extern__
+void
+load_Kicker(CFBundleRef bundle, Boolean bundleVerbose)
+{
+       CFArrayRef      targets;        /* The array of dictionaries representing targets
+                                        * with a "kick me" sign posted on their backs.*/
+
+       if (bundleVerbose) {
+               _verbose = TRUE;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+       SCLog(_verbose, LOG_DEBUG, CFSTR("  bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+       /* get the bundle's URL */
+       myBundleURL = CFBundleCopyBundleURL(bundle);
+       if (myBundleURL == NULL) {
+               return;
+       }
+
+       /* get the targets */
+       targets = getTargets(bundle);
+       if (targets == NULL) {
+               /* if nothing to do */
+               CFRelease(myBundleURL);
+               return;
+       }
+
+       /* start a kicker for each target */
+       CFArrayApplyFunction(targets,
+                            CFRangeMake(0, CFArrayGetCount(targets)),
+                            startKicker,
+                            NULL);
+       CFRelease(targets);
+
+       return;
+}
+
+#ifdef MAIN
+int
+main(int argc, char * const argv[])
+{
+       _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+       load_Kicker(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+       CFRunLoopRun();
+       /* not reached */
+       exit(0);
+       return 0;
+}
+#endif
diff --git a/Plugins/LinkConfiguration/Info.plist b/Plugins/LinkConfiguration/Info.plist
new file mode 100644 (file)
index 0000000..4907af2
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>LinkConfiguration</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.LinkConfiguration</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Requires</key>
+       <array>
+               <string>com.apple.SystemConfiguration.InterfaceNamer</string>
+       </array>
+       <key>Builtin</key>
+       <true/>
+</dict>
+</plist>
diff --git a/Plugins/LinkConfiguration/linkconfig.c b/Plugins/LinkConfiguration/linkconfig.c
new file mode 100644 (file)
index 0000000..75d7262
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <stdio.h>
+#include <unistd.h>
+//#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/LinkConfiguration.h>
+#include <SystemConfiguration/SCDPlugin.h>             // for _SCDPluginExecCommand
+
+
+static CFMutableDictionaryRef  baseSettings    = NULL;
+static SCDynamicStoreRef       store           = NULL;
+static CFRunLoopSourceRef      rls             = NULL;
+
+static Boolean                 _verbose        = FALSE;
+
+
+/* in SystemConfiguration/LinkConfiguration.c */
+int
+__createMediaOptions(CFDictionaryRef media_options);
+
+
+__private_extern__
+Boolean
+_NetworkInterfaceSetMediaOptions(CFStringRef           interface,
+                                CFDictionaryRef        options)
+{
+       CFArrayRef              available       = NULL;
+       CFDictionaryRef         current         = NULL;
+       struct ifmediareq       ifm;
+       struct ifreq            ifr;
+       Boolean                 ok              = FALSE;
+       int                     newOptions;
+       CFMutableDictionaryRef  requested       = NULL;
+       int                     sock            = -1;
+       CFTypeRef               val;
+
+       /* get current & available options */
+       if (!NetworkInterfaceCopyMediaOptions(interface, &current, 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 (file)
index 0000000..0c1b578
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>PreferencesMonitor</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration.PreferencesMonitor</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>BNDL</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>0.0.1d1</string>
+       <key>Builtin</key>
+       <true/>
+</dict>
+</plist>
diff --git a/Plugins/PreferencesMonitor/prefsmon.c b/Plugins/PreferencesMonitor/prefsmon.c
new file mode 100644 (file)
index 0000000..9071ef7
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - use SCPreference notification APIs
+ *
+ * June 24, 2001               Allan Nathanson <ajn@apple.com>
+ * - update to public SystemConfiguration.framework APIs
+ *
+ * November 10, 2000           Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/SCValidation.h>
+
+
+static SCPreferencesRef                prefs           = NULL;
+static SCDynamicStoreRef       store           = NULL;
+
+static CFMutableDictionaryRef  currentPrefs;           /* current prefs */
+static CFMutableDictionaryRef  newPrefs;               /* new prefs */
+static CFMutableArrayRef       unchangedPrefsKeys;     /* new prefs keys which match current */
+static CFMutableArrayRef       removedPrefsKeys;       /* old prefs keys to be removed */
+
+static Boolean                 _verbose        = FALSE;
+
+
+static void
+updateCache(const void *key, const void *value, void *context)
+{
+       CFStringRef             configKey       = (CFStringRef)key;
+       CFPropertyListRef       configData      = (CFPropertyListRef)value;
+       CFPropertyListRef       cacheData;
+       CFIndex                 i;
+
+       cacheData = CFDictionaryGetValue(currentPrefs, configKey);
+       if (cacheData) {
+               /* key exists */
+               if (CFEqual(cacheData, configData)) {
+                       /*
+                        * if the old & new property list values have
+                        * not changed then we don't need to update
+                        * the preference.
+                        */
+                       CFArrayAppendValue(unchangedPrefsKeys, configKey);
+               }
+       }
+
+       /* in any case, this key should not be removed */
+       i = CFArrayGetFirstIndexOfValue(removedPrefsKeys,
+                                       CFRangeMake(0, CFArrayGetCount(removedPrefsKeys)),
+                                       configKey);
+       if (i != kCFNotFound) {
+               CFArrayRemoveValueAtIndex(removedPrefsKeys, i);
+       }
+
+       return;
+}
+
+
+static void
+flatten(SCPreferencesRef       prefs,
+       CFStringRef             key,
+       CFDictionaryRef         base)
+{
+       CFDictionaryRef         subset;
+       CFStringRef             link;
+       CFMutableDictionaryRef  myDict;
+       CFStringRef             myKey;
+       CFIndex                 i;
+       CFIndex                 nKeys;
+       const void              **keys;
+       const void              **vals;
+
+       if (!CFDictionaryGetValueIfPresent(base, kSCResvLink, (const void **)&link)) {
+               /* if this dictionary is not linked */
+               subset = base;
+       } else {
+               /* if __LINK__ key is present */
+               subset = SCPreferencesPathGetValue(prefs, link);
+               if (!subset) {
+                       /* if error with link */
+                       SCLog(TRUE, LOG_ERR,
+                             CFSTR("SCPreferencesPathGetValue(,%@,) failed: %s"),
+                             link,
+                             SCErrorString(SCError()));
+                       return;
+               }
+       }
+
+       if (CFDictionaryContainsKey(subset, kSCResvInactive)) {
+               /* if __INACTIVE__ key is present */
+               return;
+       }
+
+       myKey = CFStringCreateWithFormat(NULL,
+                                        NULL,
+                                        CFSTR("%@%@"),
+                                        kSCDynamicStoreDomainSetup,
+                                        key);
+
+       myDict = (CFMutableDictionaryRef)CFDictionaryGetValue(newPrefs, myKey);
+       if (myDict) {
+               myDict = CFDictionaryCreateMutableCopy(NULL,
+                                                      0,
+                                                      (CFDictionaryRef)myDict);
+       } else {
+               myDict = CFDictionaryCreateMutable(NULL,
+                                                  0,
+                                                  &kCFTypeDictionaryKeyCallBacks,
+                                                  &kCFTypeDictionaryValueCallBacks);
+       }
+
+       nKeys = CFDictionaryGetCount(subset);
+       if (nKeys > 0) {
+               keys  = CFAllocatorAllocate(NULL, nKeys * sizeof(CFStringRef)      , 0);
+               vals  = CFAllocatorAllocate(NULL, nKeys * sizeof(CFPropertyListRef), 0);
+               CFDictionaryGetKeysAndValues(subset, keys, vals);
+               for (i = 0; i < nKeys; i++) {
+                       if (CFGetTypeID((CFTypeRef)vals[i]) != CFDictionaryGetTypeID()) {
+                               /* add this key/value to the current dictionary */
+                               CFDictionarySetValue(myDict, keys[i], vals[i]);
+                       } else {
+                               CFStringRef     subKey;
+
+                               /* flatten [sub]dictionaries */
+                               subKey = CFStringCreateWithFormat(NULL,
+                                                                 NULL,
+                                                                 CFSTR("%@%s%@"),
+                                                                 key,
+                                                                 CFEqual(key, CFSTR("/")) ? "" : "/",
+                                                                 keys[i]);
+                               flatten(prefs, subKey, vals[i]);
+                               CFRelease(subKey);
+                       }
+               }
+               CFAllocatorDeallocate(NULL, keys);
+               CFAllocatorDeallocate(NULL, vals);
+       }
+
+       if (CFDictionaryGetCount(myDict) > 0) {
+               /* add this dictionary to the new preferences */
+               CFDictionarySetValue(newPrefs, myKey, myDict);
+       }
+
+       CFRelease(myDict);
+       CFRelease(myKey);
+
+       return;
+}
+
+
+static void
+updateConfiguration(SCPreferencesRef           prefs,
+                   SCPreferencesNotification   notificationType,
+                   void                        *info)
+{
+       CFStringRef             current         = NULL;
+       CFDateRef               date            = NULL;
+       CFMutableDictionaryRef  dict            = NULL;
+       CFDictionaryRef         global          = NULL;
+       CFIndex                 i;
+       CFArrayRef              keys;
+       CFIndex                 n;
+       CFStringRef             pattern;
+       CFMutableArrayRef       patterns;
+       CFDictionaryRef         set             = NULL;
+
+       if ((notificationType & kSCPreferencesNotificationApply) != kSCPreferencesNotificationApply) {
+               return;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("updating configuration"));
+
+       /*
+        * initialize old preferences, new preferences, an array
+        * of keys which have not changed, and an array of keys
+        * to be removed (cleaned up).
+        */
+
+       patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       pattern  = CFStringCreateWithFormat(NULL,
+                                           NULL,
+                                           CFSTR("^%@.*"),
+                                           kSCDynamicStoreDomainSetup);
+       CFArrayAppendValue(patterns, pattern);
+       dict = (CFMutableDictionaryRef)SCDynamicStoreCopyMultiple(store, NULL, patterns);
+       CFRelease(patterns);
+       CFRelease(pattern);
+       if (dict) {
+               currentPrefs = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+               CFRelease(dict);
+       } else {
+               currentPrefs = CFDictionaryCreateMutable(NULL,
+                                                        0,
+                                                        &kCFTypeDictionaryKeyCallBacks,
+                                                        &kCFTypeDictionaryValueCallBacks);
+       }
+
+       unchangedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       i = CFDictionaryGetCount(currentPrefs);
+       if (i > 0) {
+               const void      **currentKeys;
+               CFArrayRef      array;
+
+               currentKeys = CFAllocatorAllocate(NULL, i * sizeof(CFStringRef), 0);
+               CFDictionaryGetKeysAndValues(currentPrefs, currentKeys, NULL);
+               array = CFArrayCreate(NULL, currentKeys, i, &kCFTypeArrayCallBacks);
+               removedPrefsKeys = CFArrayCreateMutableCopy(NULL, 0, array);
+               CFRelease(array);
+               CFAllocatorDeallocate(NULL, currentKeys);
+       } else {
+               removedPrefsKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       /*
+        * The "newPrefs" dictionary will contain the new / updated
+        * configuration which will be written to the configuration cache.
+        */
+       newPrefs = CFDictionaryCreateMutable(NULL,
+                                                0,
+                                                &kCFTypeDictionaryKeyCallBacks,
+                                                &kCFTypeDictionaryValueCallBacks);
+
+       /*
+        * create status dictionary associated with current configuration
+        * information including:
+        *   - current set "name" to cache
+        *   - time stamp indicating when the cache preferences were
+        *     last updated.
+        */
+       dict = CFDictionaryCreateMutable(NULL,
+                                        0,
+                                        &kCFTypeDictionaryKeyCallBacks,
+                                        &kCFTypeDictionaryValueCallBacks);
+       date = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
+
+       /*
+        * load preferences
+        */
+       keys = SCPreferencesCopyKeyList(prefs);
+       if ((keys == NULL) || (CFArrayGetCount(keys) == 0)) {
+               SCLog(TRUE, LOG_NOTICE, CFSTR("updateConfiguration(): no preferences."));
+               goto done;
+       }
+
+       /*
+        * get "global" system preferences
+        */
+       (CFPropertyListRef)global = SCPreferencesGetValue(prefs, kSCPrefSystem);
+       if (!global) {
+               /* if no global preferences are defined */
+               goto getSet;
+       }
+
+       if (!isA_CFDictionary(global)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("updateConfiguration(): %@ is not a dictionary."),
+                     kSCPrefSystem);
+               goto done;
+       }
+
+       /* flatten property list */
+       flatten(prefs, CFSTR("/"), global);
+
+    getSet :
+
+       /*
+        * get current set name
+        */
+       (CFPropertyListRef)current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+       if (!current) {
+               /* if current set not defined */
+               goto done;
+       }
+
+       if (!isA_CFString(current)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("updateConfiguration(): %@ is not a string."),
+                     kSCPrefCurrentSet);
+               goto done;
+       }
+
+       /*
+        * get current set
+        */
+       (CFPropertyListRef)set = SCPreferencesPathGetValue(prefs, current);
+       if (!set) {
+               /* if error with path */
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("%@ value (%@) not valid"),
+                     kSCPrefCurrentSet,
+                     current);
+               goto done;
+       }
+
+       if (!isA_CFDictionary(set)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("updateConfiguration(): %@ is not a dictionary."),
+                     current);
+               goto done;
+       }
+
+       /* flatten property list */
+       flatten(prefs, CFSTR("/"), set);
+
+       CFDictionarySetValue(dict, kSCDynamicStorePropSetupCurrentSet, current);
+
+    done :
+
+       /* add last updated time stamp */
+       CFDictionarySetValue(dict, kSCDynamicStorePropSetupLastUpdated, date);
+
+       /* add Setup: key */
+       CFDictionarySetValue(newPrefs, kSCDynamicStoreDomainSetup, dict);
+
+       /* compare current and new preferences */
+       CFDictionaryApplyFunction(newPrefs, updateCache, NULL);
+
+       /* remove those keys which have not changed from the update */
+       n = CFArrayGetCount(unchangedPrefsKeys);
+       for (i = 0; i < n; i++) {
+               CFStringRef     key;
+
+               key = CFArrayGetValueAtIndex(unchangedPrefsKeys, i);
+               CFDictionaryRemoveValue(newPrefs, key);
+       }
+
+       /* Update the dynamic store */
+       if (!SCDynamicStoreSetMultiple(store, newPrefs, removedPrefsKeys, NULL)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
+                     SCErrorString(SCError()));
+       }
+
+       /* finished with current prefs, wait for changes */
+       SCPreferencesSynchronize(prefs);
+
+       CFRelease(currentPrefs);
+       CFRelease(newPrefs);
+       CFRelease(unchangedPrefsKeys);
+       CFRelease(removedPrefsKeys);
+       if (dict)       CFRelease(dict);
+       if (date)       CFRelease(date);
+       if (keys)       CFRelease(keys);
+       return;
+}
+
+
+__private_extern__
+void
+stop_PreferencesMonitor(CFRunLoopSourceRef stopRls)
+{
+       // cleanup
+
+       if (prefs != NULL) {
+               if (!SCPreferencesUnscheduleFromRunLoop(prefs,
+                                                       CFRunLoopGetCurrent(),
+                                                       kCFRunLoopDefaultMode)) {
+                       SCLog(TRUE, LOG_ERR,
+                             CFSTR("SCPreferencesUnscheduleFromRunLoop() failed: %s"),
+                             SCErrorString(SCError()));
+               }
+               CFRelease(prefs);
+               prefs = NULL;
+       }
+
+       if (store != NULL) {
+               CFRelease(store);
+               store = NULL;
+       }
+
+       CFRunLoopSourceSignal(stopRls);
+       return;
+}
+
+
+__private_extern__
+void
+prime_PreferencesMonitor()
+{
+       SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
+
+       /* load the initial configuration from the database */
+       updateConfiguration(prefs, kSCPreferencesNotificationApply, (void *)store);
+
+       return;
+}
+
+
+__private_extern__
+void
+load_PreferencesMonitor(CFBundleRef bundle, Boolean bundleVerbose)
+{
+       if (bundleVerbose) {
+               _verbose = TRUE;
+       }
+
+       SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
+       SCLog(_verbose, LOG_DEBUG, CFSTR("  bundle ID = %@"), CFBundleGetIdentifier(bundle));
+
+       /* open a SCDynamicStore session to allow cache updates */
+       store = SCDynamicStoreCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL, NULL);
+       if (store == NULL) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCDynamicStoreCreate() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       /* open a SCPreferences session */
+       prefs = SCPreferencesCreate(NULL, CFSTR("PreferencesMonitor.bundle"), NULL);
+       if (prefs == NULL) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCPreferencesCreate() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       if (!SCPreferencesSetCallback(prefs, updateConfiguration, NULL)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCPreferencesSetCallBack() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       /*
+        * register for change notifications.
+        */
+       if (!SCPreferencesScheduleWithRunLoop(prefs, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("SCPreferencesScheduleWithRunLoop() failed: %s"),
+                     SCErrorString(SCError()));
+               goto error;
+       }
+
+       return;
+
+    error :
+
+       if (store)      CFRelease(store);
+       if (prefs)      CFRelease(prefs);
+
+       return;
+}
+
+
+#ifdef  MAIN
+int
+main(int argc, char **argv)
+{
+       _sc_log     = FALSE;
+       _sc_verbose = (argc > 1) ? TRUE : FALSE;
+
+       load_PreferencesMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
+       prime_PreferencesMonitor();
+       CFRunLoopRun();
+       /* not reached */
+       exit(0);
+       return 0;
+}
+#endif
diff --git a/Plugins/common/cache.c b/Plugins/common/cache.c
new file mode 100644 (file)
index 0000000..04415d6
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPrivate.h>     // for SCLog()
+
+#include "cache.h"
+
+
+static CFMutableDictionaryRef  cached_keys     = NULL;
+static CFMutableDictionaryRef  cached_set      = NULL;
+static CFMutableArrayRef       cached_removals = NULL;
+static CFMutableArrayRef       cached_notifys  = NULL;
+
+
+__private_extern__
+void
+cache_open()
+{
+       cached_keys     = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       cached_set      = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       cached_removals = CFArrayCreateMutable(NULL,
+                                              0,
+                                              &kCFTypeArrayCallBacks);
+       cached_notifys  = CFArrayCreateMutable(NULL,
+                                              0,
+                                              &kCFTypeArrayCallBacks);
+
+       return;
+}
+
+
+__private_extern__
+CFPropertyListRef
+cache_SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
+{
+       CFPropertyListRef       value;
+
+       value = CFDictionaryGetValue(cached_set, key);
+       if (value) {
+               // if we have "set" a new value
+               return (CFRetain(value));
+       }
+
+       if (CFArrayContainsValue(cached_removals,
+                                CFRangeMake(0, CFArrayGetCount(cached_removals)),
+                                key)) {
+               // if we have "removed" the key
+               return NULL;
+       }
+
+       value = CFDictionaryGetValue(cached_keys, key);
+       if (value) {
+               // if we have a cached value
+               return (CFRetain(value));
+       }
+
+       value = SCDynamicStoreCopyValue(store, key);
+       if (value) {
+               CFDictionarySetValue(cached_keys, key, value);
+       }
+
+       return value;
+}
+
+
+__private_extern__
+void
+cache_SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+{
+       CFIndex i;
+
+       i = CFArrayGetFirstIndexOfValue(cached_removals,
+                                       CFRangeMake(0, CFArrayGetCount(cached_removals)),
+                                       key);
+       if (i != kCFNotFound) {
+               // if previously "removed"
+               CFArrayRemoveValueAtIndex(cached_removals, i);
+       }
+
+       CFDictionarySetValue(cached_set, key, value);
+
+       return;
+}
+
+__private_extern__
+void
+cache_SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
+{
+       CFDictionaryRemoveValue(cached_set, key);
+
+       if (!CFArrayContainsValue(cached_removals,
+                                 CFRangeMake(0, CFArrayGetCount(cached_removals)),
+                                 key)) {
+               CFArrayAppendValue(cached_removals, key);
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+cache_SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key)
+{
+       if (!CFArrayContainsValue(cached_notifys,
+                                 CFRangeMake(0, CFArrayGetCount(cached_notifys)),
+                                 key)) {
+               CFArrayAppendValue(cached_notifys, key);
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+cache_write(SCDynamicStoreRef store)
+{
+       if ((CFDictionaryGetCount(cached_set) > 0) ||
+           (CFArrayGetCount(cached_removals) > 0) ||
+           (CFArrayGetCount(cached_notifys)  > 0)) {
+               if (!SCDynamicStoreSetMultiple(store,
+                                cached_set,
+                                cached_removals,
+                                cached_notifys)) {
+                       SCLog(TRUE,
+                             LOG_ERR,
+                             CFSTR("SCDynamicStoreSetMultiple() failed: %s"),
+                             SCErrorString(SCError()));
+               }
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+cache_close()
+{
+       CFRelease(cached_keys);
+       CFRelease(cached_set);
+       CFRelease(cached_removals);
+       CFRelease(cached_notifys);
+
+       return;
+}
diff --git a/Plugins/common/cache.h b/Plugins/common/cache.h
new file mode 100644 (file)
index 0000000..c2847f4
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#ifndef        _CACHE_H
+#define        _CACHE_H
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+
+__BEGIN_DECLS
+
+void                   cache_open                      ();
+
+CFPropertyListRef      cache_SCDynamicStoreCopyValue   (SCDynamicStoreRef      store,
+                                                        CFStringRef            key);
+
+void                   cache_SCDynamicStoreSetValue    (SCDynamicStoreRef      store,
+                                                        CFStringRef            key,
+                                                        CFPropertyListRef      value);
+
+void                   cache_SCDynamicStoreRemoveValue (SCDynamicStoreRef      store,
+                                                        CFStringRef            key);
+
+void                   cache_SCDynamicStoreNotifyValue (SCDynamicStoreRef      store,
+                                                        CFStringRef            key);
+
+void                   cache_write                     (SCDynamicStoreRef      store);
+
+void                   cache_close                     ();
+
+__END_DECLS
+
+#endif /* _CACHE_H */
diff --git a/SystemConfiguration.fproj/BondConfiguration.c b/SystemConfiguration.fproj/BondConfiguration.c
new file mode 100644 (file)
index 0000000..5343842
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include <SystemConfiguration/BondConfiguration.h>
+#include <SystemConfiguration/BondConfigurationPrivate.h>
+
+#include <ifaddrs.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/ethernet.h>
+#define        KERNEL_PRIVATE
+#include <net/if.h>
+#include <net/if_var.h>
+#undef KERNEL_PRIVATE
+#include <net/if_bond_var.h>
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <net/route.h>
+
+/* ---------- Bond support ---------- */
+
+static int
+inet_dgram_socket()
+{
+       int     s;
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
+               _SCErrorSet(kSCStatusFailed);
+       }
+
+       return s;
+}
+
+static int
+siocgifmedia(int s, const char * ifname, int * status, int * active)
+{
+       struct ifmediareq       ifmr;
+
+       *status = 0;
+       *active = 0;
+       bzero(&ifmr, sizeof(ifmr));
+       strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+       if (ioctl(s, SIOCGIFMEDIA, &ifmr) < 0) {
+               SCLog(TRUE, LOG_ERR, CFSTR("SIOCGIFMEDIA(%s) failed, %s\n"),
+                       ifname, strerror(errno));
+               return (-1);
+       }
+       if (ifmr.ifm_count != 0) {
+               *status = ifmr.ifm_status;
+               *active = ifmr.ifm_active;
+       }
+       return (0);
+}
+
+static struct if_bond_status_req *
+if_bond_status_req_copy(int s, const char * ifname)
+{
+       void *                          buf = NULL;
+       struct if_bond_req              ibr;
+       struct if_bond_status_req *     ibsr_p;
+       struct ifreq                    ifr;
+
+       bzero(&ifr, sizeof(ifr));
+       strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+       bzero((char *)&ibr, sizeof(ibr));
+       ibr.ibr_op = IF_BOND_OP_GET_STATUS;
+       ibsr_p = &ibr.ibr_ibru.ibru_status;
+       ibsr_p->ibsr_version = IF_BOND_STATUS_REQ_VERSION;
+       ifr.ifr_data = (caddr_t)&ibr;
+
+       /* how many of them are there? */
+       if (ioctl(s, SIOCGIFBOND, (caddr_t)&ifr) < 0) {
+               SCLog(TRUE, LOG_ERR, CFSTR("SIOCGIFBOND(%s) failed: %s"),
+                     ifname, strerror(errno));
+               goto failed;
+       }
+       buf = malloc(sizeof(struct if_bond_status) * ibsr_p->ibsr_total + sizeof(*ibsr_p));
+       if (buf == NULL) {
+               goto failed;
+       }
+       if (ibsr_p->ibsr_total == 0) {
+               goto done;
+       }
+       ibsr_p->ibsr_count = ibsr_p->ibsr_total;
+       ibsr_p->ibsr_buffer = buf + sizeof(*ibsr_p);
+
+       /* get the list */
+       if (ioctl(s, SIOCGIFBOND, (caddr_t)&ifr) < 0) {
+               SCLog(TRUE, LOG_ERR, CFSTR("SIOCGIFBOND(%s) failed: %s"),
+                     ifname, strerror(errno));
+               goto failed;
+       }
+ done:
+       (*(struct if_bond_status_req *)buf) = *ibsr_p;
+       return ((struct if_bond_status_req *)buf);
+
+ failed:
+       if (buf != NULL) {
+               free(buf);
+       }
+       return (NULL);
+}
+
+static Boolean
+_Bond_addDevice(int s, CFStringRef interface, CFStringRef device)
+{
+       struct if_bond_req      breq;
+       struct ifreq            ifr;
+
+       // bond interface
+       bzero(&ifr, sizeof(ifr));
+       (void) _SC_cfstring_to_cstring(interface,
+                                      ifr.ifr_name,
+                                      sizeof(ifr.ifr_name),
+                                      kCFStringEncodingASCII);
+       ifr.ifr_data = (caddr_t)&breq;
+
+       // new bond member
+       bzero(&breq, sizeof(breq));
+       breq.ibr_op = IF_BOND_OP_ADD_INTERFACE;
+       (void) _SC_cfstring_to_cstring(device,
+                                      breq.ibr_ibru.ibru_if_name,
+                                      sizeof(breq.ibr_ibru.ibru_if_name),
+                                      kCFStringEncodingASCII);
+
+       // add new bond member
+       if (ioctl(s, SIOCSIFBOND, (caddr_t)&ifr) == -1) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("could not add interface \"%@\" to bond \"%@\": %s"),
+                     device,
+                     interface,
+                     strerror(errno));
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       // mark the added interface "up"
+       if (!__markInterfaceUp(s, device)) {
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+static Boolean
+_Bond_removeDevice(int s, CFStringRef interface, CFStringRef device)
+{
+       struct if_bond_req      breq;
+       struct ifreq            ifr;
+
+       // bond interface
+       bzero(&ifr, sizeof(ifr));
+       (void) _SC_cfstring_to_cstring(interface,
+                                      ifr.ifr_name,
+                                      sizeof(ifr.ifr_name),
+                                      kCFStringEncodingASCII);
+       ifr.ifr_data = (caddr_t)&breq;
+
+       // bond member to remove
+       bzero(&breq, sizeof(breq));
+       breq.ibr_op = IF_BOND_OP_REMOVE_INTERFACE;
+       (void) _SC_cfstring_to_cstring(device,
+                                      breq.ibr_ibru.ibru_if_name,
+                                      sizeof(breq.ibr_ibru.ibru_if_name),
+                                      kCFStringEncodingASCII);
+
+       // remove bond member
+       if (ioctl(s, SIOCSIFBOND, (caddr_t)&ifr) == -1) {
+               SCLog(TRUE, LOG_ERR,
+                     CFSTR("could not remove interface \"%@\" from bond \"%@\": %s"),
+                     device,
+                     interface,
+                     strerror(errno));
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+/* ---------- Bond "device" ---------- */
+
+Boolean
+IsBondSupported(CFStringRef device)
+{
+       CFMutableDictionaryRef  entity;
+       SCNetworkInterfaceRef   interface;
+       Boolean                 isBond          = FALSE;
+
+       entity = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+       CFDictionarySetValue(entity, kSCPropNetInterfaceType, kSCValNetInterfaceTypeEthernet);
+       CFDictionarySetValue(entity, kSCPropNetInterfaceDeviceName, device);
+       interface = __SCNetworkInterfaceCreateWithEntity(NULL, entity, NULL);
+       CFRelease(entity);
+
+       if (interface != NULL) {
+               SCNetworkInterfacePrivateRef    interfacePrivate;
+
+               interfacePrivate = (SCNetworkInterfacePrivateRef)interface;
+               if (interfacePrivate->path != NULL) {
+                       isBond = interfacePrivate->supportsBond;
+               }
+               CFRelease(interface);
+       }
+
+       return isBond;
+}
+
+/* ---------- BondInterface ---------- */
+
+typedef struct {
+
+       /* base CFType information */
+       CFRuntimeBase                   cfBase;
+
+       /* bond interface configuration */
+       CFStringRef                     ifname;         // e.g. bond0, bond1, ...
+       CFArrayRef                      devices;        // e.g. en0, en1, ...
+       CFDictionaryRef                 options;        // e.g. UserDefinedName
+
+} BondInterfacePrivate, * BondInterfacePrivateRef;
+
+
+static CFStringRef     __BondInterfaceCopyDescription  (CFTypeRef cf);
+static void            __BondInterfaceDeallocate       (CFTypeRef cf);
+static Boolean         __BondInterfaceEqual            (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static const CFRuntimeClass __BondInterfaceClass = {
+       0,                                      // version
+       "BondInterface",                        // className
+       NULL,                                   // init
+       NULL,                                   // copy
+       __BondInterfaceDeallocate,              // dealloc
+       __BondInterfaceEqual,                   // equal
+       NULL,                                   // hash
+       NULL,                                   // copyFormattingDesc
+       __BondInterfaceCopyDescription          // copyDebugDesc
+};
+
+
+static CFTypeID                __kBondInterfaceTypeID  = _kCFRuntimeNotATypeID;
+
+
+static pthread_once_t  bondInterface_init      = PTHREAD_ONCE_INIT;
+
+
+static CFStringRef
+__BondInterfaceCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef          allocator       = CFGetAllocator(cf);
+       CFMutableStringRef      result;
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)cf;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<BondInterface %p [%p]> {"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR(" if = %@"), bondPrivate->ifname);
+       if (bondPrivate->devices != NULL) {
+               CFIndex i;
+               CFIndex n;
+
+               CFStringAppendFormat(result, NULL, CFSTR(", devices ="));
+
+               n = CFArrayGetCount(bondPrivate->devices);
+               for (i = 0; i < n; i++) {
+                       CFStringAppendFormat(result,
+                                            NULL,
+                                            CFSTR(" %@"),
+                                            CFArrayGetValueAtIndex(bondPrivate->devices, i));
+               }
+       }
+       if (bondPrivate->options != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", options = %@"), bondPrivate->options);
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__BondInterfaceDeallocate(CFTypeRef cf)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)cf;
+
+       /* release resources */
+
+       CFRelease(bondPrivate->ifname);
+       if (bondPrivate->devices)       CFRelease(bondPrivate->devices);
+       if (bondPrivate->options)       CFRelease(bondPrivate->options);
+
+       return;
+}
+
+
+static Boolean
+__BondInterfaceEquiv(CFTypeRef cf1, CFTypeRef cf2)
+{
+       BondInterfacePrivateRef bond1   = (BondInterfacePrivateRef)cf1;
+       BondInterfacePrivateRef bond2   = (BondInterfacePrivateRef)cf2;
+
+       if (bond1 == bond2)
+               return TRUE;
+
+       if (!CFEqual(bond1->ifname, bond2->ifname))
+               return FALSE;   // if not the same interface
+
+       if (!CFEqual(bond1->devices, bond2->devices))
+               return FALSE;   // if not the same device
+
+       return TRUE;
+}
+
+
+static Boolean
+__BondInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+       BondInterfacePrivateRef bond1   = (BondInterfacePrivateRef)cf1;
+       BondInterfacePrivateRef bond2   = (BondInterfacePrivateRef)cf2;
+
+       if (!__BondInterfaceEquiv(bond1, bond2))
+               return FALSE;   // if not the same Bond interface/devices
+
+       if (bond1->options != bond2->options) {
+               // if the options may differ
+               if ((bond1->options != NULL) && (bond2->options != NULL)) {
+                       // if both Bonds have options
+                       if (!CFEqual(bond1->options, bond2->options)) {
+                               // if the options are not equal
+                               return FALSE;
+                       }
+               } else {
+                       // if only one Bond has options
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+
+static void
+__BondInterfaceInitialize(void)
+{
+       __kBondInterfaceTypeID = _CFRuntimeRegisterClass(&__BondInterfaceClass);
+       return;
+}
+
+
+static __inline__ CFTypeRef
+isA_BondInterface(CFTypeRef obj)
+{
+       return (isA_CFType(obj, BondInterfaceGetTypeID()));
+}
+
+
+CFTypeID
+BondInterfaceGetTypeID(void)
+{
+       pthread_once(&bondInterface_init, __BondInterfaceInitialize);   /* initialize runtime */
+       return __kBondInterfaceTypeID;
+}
+
+
+static BondInterfaceRef
+__BondInterfaceCreatePrivate(CFAllocatorRef    allocator,
+                            CFStringRef        ifname)
+{
+       BondInterfacePrivateRef         bondPrivate;
+       uint32_t                        size;
+
+       /* initialize runtime */
+       pthread_once(&bondInterface_init, __BondInterfaceInitialize);
+
+       /* allocate bond */
+       size        = sizeof(BondInterfacePrivate) - sizeof(CFRuntimeBase);
+       bondPrivate = (BondInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                       __kBondInterfaceTypeID,
+                                                                       size,
+                                                                       NULL);
+       if (bondPrivate == NULL) {
+               return NULL;
+       }
+
+       /* establish the bond */
+
+       bondPrivate->ifname  = CFStringCreateCopy(allocator, ifname);
+       bondPrivate->devices = NULL;
+       bondPrivate->options = NULL;
+
+       return (BondInterfaceRef)bondPrivate;
+}
+
+
+CFStringRef
+BondInterfaceGetInterface(BondInterfaceRef bond)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)bond;
+       CFStringRef             bond_if         = NULL;
+
+       if (isA_BondInterface(bond)) {
+               bond_if = bondPrivate->ifname;
+       }
+
+       return bond_if;
+}
+
+
+CFArrayRef
+BondInterfaceGetDevices(BondInterfaceRef bond)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)bond;
+       CFArrayRef              bond_devices    = NULL;
+
+       if (isA_BondInterface(bond)) {
+               bond_devices = bondPrivate->devices;
+       }
+
+       return bond_devices;
+}
+
+
+CFDictionaryRef
+BondInterfaceGetOptions(BondInterfaceRef bond)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)bond;
+       CFDictionaryRef         bond_options    = NULL;
+
+       if (isA_BondInterface(bond)) {
+               bond_options = bondPrivate->options;
+       }
+
+       return bond_options;
+}
+
+
+static void
+BondInterfaceSetDevices(BondInterfaceRef bond, CFArrayRef newDevices)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)bond;
+
+       if (isA_BondInterface(bond)) {
+               CFAllocatorRef  allocator       = CFGetAllocator(bond);
+
+               if (bondPrivate->devices != NULL)       CFRelease(bondPrivate->devices);
+               if ((newDevices != NULL) && (CFArrayGetCount(newDevices) > 0)) {
+                       bondPrivate->devices = CFArrayCreateCopy(allocator, newDevices);
+               } else {
+                       bondPrivate->devices = NULL;
+               }
+       }
+
+       return;
+}
+
+
+static void
+BondInterfaceSetOptions(BondInterfaceRef bond, CFDictionaryRef newOptions)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)bond;
+
+       if (isA_BondInterface(bond)) {
+               CFAllocatorRef  allocator       = CFGetAllocator(bond);
+
+               if (bondPrivate->options)       CFRelease(bondPrivate->options);
+               if (newOptions != NULL) {
+                       bondPrivate->options = CFDictionaryCreateCopy(allocator, newOptions);
+               } else {
+                       bondPrivate->options = NULL;
+               }
+       }
+
+       return;
+}
+
+
+/* ---------- BondPreferences ---------- */
+
+#define        BOND_PREFERENCES_BONDS          CFSTR("Bonds")
+
+#define        __kBondInterface_interface      CFSTR("interface")      // e.g. bond0, bond1, ...
+#define        __kBondInterface_devices        CFSTR("devices")        // e.g. en0, en1, ...
+#define __kBondInterface_options       CFSTR("options")        // e.g. UserDefinedName
+
+typedef struct {
+
+       /* base CFType information */
+       CFRuntimeBase                   cfBase;
+
+       /* lock */
+       pthread_mutex_t                 lock;
+
+       /* underlying preferences */
+       SCPreferencesRef                prefs;
+
+       /* base Bonds (before any commits) */
+       CFArrayRef                      bBase;
+
+} BondPreferencesPrivate, * BondPreferencesPrivateRef;
+
+
+static CFStringRef     __BondPreferencesCopyDescription        (CFTypeRef cf);
+static void            __BondPreferencesDeallocate             (CFTypeRef cf);
+
+
+static const CFRuntimeClass __BondPreferencesClass = {
+       0,                                      // version
+       "BondPreferences",                      // className
+       NULL,                                   // init
+       NULL,                                   // copy
+       __BondPreferencesDeallocate,            // dealloc
+       NULL,                                   // equal
+       NULL,                                   // hash
+       NULL,                                   // copyFormattingDesc
+       __BondPreferencesCopyDescription        // copyDebugDesc
+};
+
+
+static CFTypeID                __kBondPreferencesTypeID        = _kCFRuntimeNotATypeID;
+
+
+static pthread_once_t  bondPreferences_init            = PTHREAD_ONCE_INIT;
+
+
+static CFStringRef
+__BondPreferencesCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef                  allocator       = CFGetAllocator(cf);
+       CFIndex                         i;
+       CFArrayRef                      keys;
+       CFIndex                         n;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)cf;
+       CFMutableStringRef              result;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<BondPreferences %p [%p]> {"), cf, allocator);
+
+       keys = SCPreferencesCopyKeyList(prefsPrivate->prefs);
+       n = CFArrayGetCount(keys);
+       for (i = 0; i < n; i++) {
+               CFStringRef             key;
+               CFPropertyListRef       val;
+
+               key = CFArrayGetValueAtIndex(keys, i);
+               val = SCPreferencesGetValue(prefsPrivate->prefs, key);
+
+               CFStringAppendFormat(result, NULL, CFSTR("%@ : %@"), key, val);
+       }
+       CFRelease(keys);
+
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__BondPreferencesDeallocate(CFTypeRef cf)
+{
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)cf;
+
+       /* release resources */
+
+       pthread_mutex_destroy(&prefsPrivate->lock);
+
+       if (prefsPrivate->prefs)        CFRelease(prefsPrivate->prefs);
+       if (prefsPrivate->bBase)        CFRelease(prefsPrivate->bBase);
+
+       return;
+}
+
+
+static void
+__BondPreferencesInitialize(void)
+{
+       __kBondPreferencesTypeID = _CFRuntimeRegisterClass(&__BondPreferencesClass);
+       return;
+}
+
+
+static __inline__ CFTypeRef
+isA_BondPreferences(CFTypeRef obj)
+{
+       return (isA_CFType(obj, BondPreferencesGetTypeID()));
+}
+
+
+CFArrayRef
+_BondPreferencesCopyActiveInterfaces()
+{
+       CFArrayCallBacks        callbacks;
+       struct ifaddrs          *ifap;
+       struct ifaddrs          *ifp;
+       int                     s;
+       CFMutableArrayRef       bonds   = NULL;
+
+       if (getifaddrs(&ifap) == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
+               _SCErrorSet(kSCStatusFailed);
+               return NULL;
+       }
+
+       s = inet_dgram_socket();
+       if (s == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("socket() failed: %s"), strerror(errno));
+               _SCErrorSet(kSCStatusFailed);
+               goto done;
+       }
+
+       callbacks = kCFTypeArrayCallBacks;
+       callbacks.equal = __BondInterfaceEquiv;
+       bonds = CFArrayCreateMutable(NULL, 0, &callbacks);
+
+       for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) {
+               BondInterfaceRef                bond;
+               CFStringRef                     bond_if;
+               CFMutableArrayRef               devices = NULL;
+               struct if_bond_status_req       *ibsr_p;
+               struct if_data                  *if_data;
+
+               if_data = (struct if_data *)ifp->ifa_data;
+               if (if_data == NULL
+                   || ifp->ifa_addr->sa_family != AF_LINK
+                   || if_data->ifi_type != IFT_IEEE8023ADLAG) {
+                       continue;
+               }
+               ibsr_p = if_bond_status_req_copy(s, ifp->ifa_name);
+               if (ibsr_p == NULL) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("if_bond_status_req_copy(%s) failed: %s"),
+                             ifp->ifa_name, strerror(errno));
+                       _SCErrorSet(kSCStatusFailed);
+                       CFRelease(bonds);
+                       goto done;
+               }
+               if (ibsr_p->ibsr_total > 0) {
+                       int                     i;
+                       struct if_bond_status * ibs_p;
+                       devices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+                       // iterate over each member device
+                       ibs_p = (struct if_bond_status *)ibsr_p->ibsr_buffer;
+                       for (i = 0; i < ibsr_p->ibsr_total; i++) {
+                               CFStringRef     device;
+                               char            if_name[IFNAMSIZ+1];
+
+                               strlcpy(if_name, ibs_p[i].ibs_if_name, sizeof(if_name));
+                               device = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
+                               CFArrayAppendValue(devices, device);
+                               CFRelease(device);
+                       }
+               }
+               free(ibsr_p);
+               bond_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII);
+               bond    = __BondInterfaceCreatePrivate(NULL, bond_if);
+               CFRelease(bond_if);
+
+               if (devices != NULL) {
+                       BondInterfaceSetDevices(bond, devices);
+                       CFRelease(devices);
+               }
+               CFArrayAppendValue(bonds, bond);
+               CFRelease(bond);
+       }
+
+    done :
+
+       (void) close(s);
+       freeifaddrs(ifap);
+       return bonds;
+}
+
+
+static CFIndex
+findBond(CFArrayRef bonds, CFStringRef interface)
+{
+       CFIndex found   = kCFNotFound;
+       CFIndex i;
+       CFIndex n;
+
+       n = isA_CFArray(bonds) ? CFArrayGetCount(bonds) : 0;
+       for (i = 0; i < n; i++) {
+               CFDictionaryRef bond_dict;
+               CFStringRef     bond_if;
+
+               bond_dict = CFArrayGetValueAtIndex(bonds, i);
+               if (!isA_CFDictionary(bond_dict)) {
+                       break;  // if the prefs are confused
+               }
+
+               bond_if = CFDictionaryGetValue(bond_dict, __kBondInterface_interface);
+               if (!isA_CFString(bond_if)) {
+                       break;  // if the prefs are confused
+               }
+
+               if (!CFEqual(bond_if, interface)) {
+                       continue;       // if not a match
+               }
+
+               // if we have found a match
+               found = i;
+               break;
+       }
+
+       return found;
+}
+
+
+static void
+setConfigurationChanged(BondPreferencesRef prefs)
+{
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       /*
+        * to facilitate device configuration we will take
+        * a snapshot of the Bond preferences before any
+        * changes are made.  Then, when the changes are
+        * applied we can compare what we had to what we
+        * want and configured the system accordingly.
+        */
+       if (prefsPrivate->bBase == NULL) {
+               prefsPrivate->bBase = BondPreferencesCopyInterfaces(prefs);
+       }
+
+       return;
+}
+
+
+CFTypeID
+BondPreferencesGetTypeID(void)
+{
+       pthread_once(&bondPreferences_init, __BondPreferencesInitialize);       /* initialize runtime */
+       return __kBondPreferencesTypeID;
+}
+
+
+BondPreferencesRef
+BondPreferencesCreate(CFAllocatorRef allocator)
+{
+       CFBundleRef                     bundle;
+       CFStringRef                     bundleID        = NULL;
+       CFStringRef                     name            = CFSTR("BondConfiguration");
+       BondPreferencesPrivateRef       prefsPrivate;
+       uint32_t                        size;
+
+       /* initialize runtime */
+       pthread_once(&bondPreferences_init, __BondPreferencesInitialize);
+
+       /* allocate preferences */
+       size         = sizeof(BondPreferencesPrivate) - sizeof(CFRuntimeBase);
+       prefsPrivate = (BondPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                          __kBondPreferencesTypeID,
+                                                                          size,
+                                                                          NULL);
+       if (prefsPrivate == NULL) {
+               return NULL;
+       }
+
+       /* establish the prefs */
+
+       pthread_mutex_init(&prefsPrivate->lock, NULL);
+
+       bundle = CFBundleGetMainBundle();
+       if (bundle) {
+               bundleID = CFBundleGetIdentifier(bundle);
+               if (bundleID) {
+                       CFRetain(bundleID);
+               } else {
+                       CFURLRef        url;
+
+                       url = CFBundleCopyExecutableURL(bundle);
+                       if (url) {
+                               bundleID = CFURLCopyPath(url);
+                               CFRelease(url);
+                       }
+               }
+       }
+
+       if (bundleID) {
+               CFStringRef     fullName;
+
+               if (CFEqual(bundleID, CFSTR("/"))) {
+                       CFRelease(bundleID);
+                       bundleID = CFStringCreateWithFormat(allocator, NULL, CFSTR("(%d)"), getpid());
+               }
+
+               fullName = CFStringCreateWithFormat(allocator, NULL, CFSTR("%@:%@"), bundleID, name);
+               name = fullName;
+               CFRelease(bundleID);
+       } else {
+               CFRetain(name);
+       }
+
+       prefsPrivate->prefs = SCPreferencesCreate(allocator, name, BOND_PREFERENCES_ID);
+       CFRelease(name);
+
+       prefsPrivate->bBase = NULL;
+
+       return (BondPreferencesRef)prefsPrivate;
+}
+
+
+CFArrayRef
+BondPreferencesCopyInterfaces(BondPreferencesRef prefs)
+{
+       CFAllocatorRef                  allocator;
+       CFArrayCallBacks                callbacks;
+       CFIndex                         i;
+       CFIndex                         n;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+       CFMutableArrayRef               result;
+       CFArrayRef                      bonds;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       allocator = CFGetAllocator(prefs);
+       callbacks = kCFTypeArrayCallBacks;
+       callbacks.equal = __BondInterfaceEquiv;
+       result = CFArrayCreateMutable(allocator, 0, &callbacks);
+
+       bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+       if ((bonds != NULL) && !isA_CFArray(bonds)) {
+               goto error;     // if the prefs are confused
+       }
+
+       n = (bonds != NULL) ? CFArrayGetCount(bonds) : 0;
+       for (i = 0; i < n; i++) {
+               BondInterfaceRef        bond;
+               CFDictionaryRef         bond_dict;
+               CFStringRef             bond_if;
+               CFArrayRef              devices;
+               CFDictionaryRef         options;
+
+               bond_dict = CFArrayGetValueAtIndex(bonds, i);
+               if (!isA_CFDictionary(bond_dict)) {
+                       goto error;     // if the prefs are confused
+               }
+
+               bond_if = CFDictionaryGetValue(bond_dict, __kBondInterface_interface);
+               if (!isA_CFString(bond_if)) {
+                       goto error;     // if the prefs are confused
+               }
+
+
+               devices = CFDictionaryGetValue(bond_dict, __kBondInterface_devices);
+               if ((devices != NULL) && !isA_CFArray(devices)) {
+                       goto error;     // if the prefs are confused
+               }
+
+               options = CFDictionaryGetValue(bond_dict, __kBondInterface_options);
+               if ((options != NULL) && !isA_CFDictionary(options)) {
+                       goto error;     // if the prefs are confused
+               }
+
+               bond = __BondInterfaceCreatePrivate(allocator, bond_if);
+               BondInterfaceSetDevices(bond, devices);
+               BondInterfaceSetOptions(bond, options);
+               CFArrayAppendValue(result, bond);
+               CFRelease(bond);
+       }
+
+       return result;
+
+    error :
+
+       _SCErrorSet(kSCStatusFailed);
+       CFRelease(result);
+       return NULL;
+}
+
+
+BondInterfaceRef
+BondPreferencesCreateInterface(BondPreferencesRef      prefs)
+{
+       CFArrayRef                      active_bonds    = NULL;
+       CFAllocatorRef                  allocator;
+       CFArrayRef                      config_bonds;
+       CFIndex                         i;
+       CFIndex                         nActive;
+       CFIndex                         nConfig;
+       BondInterfaceRef                newBond         = NULL;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return NULL;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       /* get "configured" Bonds (and check to ensure the device is available) */
+       config_bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+       if ((config_bonds != NULL) && !isA_CFArray(config_bonds)) {
+               // if the prefs are confused
+               _SCErrorSet(kSCStatusFailed);
+               goto done;
+       }
+
+       nConfig = (config_bonds != NULL) ? CFArrayGetCount(config_bonds) : 0;
+
+       /* get "active" Bonds */
+       active_bonds = _BondPreferencesCopyActiveInterfaces();
+       nActive      = isA_CFArray(active_bonds) ? CFArrayGetCount(active_bonds) : 0;
+
+       /* create a new bond using an unused interface name */
+       allocator = CFGetAllocator(prefs);
+
+       for (i = 0; newBond == NULL; i++) {
+               CFIndex                 j;
+               CFMutableDictionaryRef  newDict;
+               CFMutableArrayRef       newBonds;
+               CFStringRef             bond_if;
+
+               bond_if = CFStringCreateWithFormat(allocator, NULL, CFSTR("bond%d"), i);
+
+               for (j = 0; j < nActive; j++) {
+                       CFStringRef             active_if;
+                       BondInterfaceRef        active_bond;
+
+                       active_bond = CFArrayGetValueAtIndex(active_bonds, j);
+                       active_if   = BondInterfaceGetInterface(active_bond);
+
+                       if (CFEqual(bond_if, active_if)) {
+                               goto next_if;   // if bond interface name not available
+                       }
+               }
+
+               for (j = 0; j < nConfig; j++) {
+                       CFDictionaryRef config;
+                       CFStringRef     config_if;
+
+                       config = CFArrayGetValueAtIndex(config_bonds, j);
+                       if (!isA_CFDictionary(config)) {
+                               // if the prefs are confused
+                               _SCErrorSet(kSCStatusFailed);
+                               CFRelease(bond_if);
+                               goto done;
+                       }
+
+                       config_if = CFDictionaryGetValue(config, __kBondInterface_interface);
+                       if (!isA_CFString(config_if)) {
+                               // if the prefs are confused
+                               _SCErrorSet(kSCStatusFailed);
+                               CFRelease(bond_if);
+                               goto done;
+                       }
+
+                       if (CFEqual(bond_if, config_if)) {
+                               goto next_if;   // if bond interface name not available
+                       }
+               }
+
+               /* create the bond */
+
+               newDict = CFDictionaryCreateMutable(allocator,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+               CFDictionaryAddValue(newDict, __kBondInterface_interface, bond_if);
+
+               /* create the accessor handle to be returned */
+
+               newBond = __BondInterfaceCreatePrivate(allocator, bond_if);
+
+               /* save in the prefs */
+
+               if (nConfig > 0) {
+                       newBonds = CFArrayCreateMutableCopy(allocator, 0, config_bonds);
+               } else {
+                       newBonds = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
+               }
+               CFArrayAppendValue(newBonds, newDict);
+               CFRelease(newDict);
+
+               /* yes, we're going to be changing the configuration */
+               setConfigurationChanged(prefs);
+
+               (void) SCPreferencesSetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS, newBonds);
+               CFRelease(newBonds);
+
+           next_if :
+               CFRelease(bond_if);
+       }
+
+    done :
+
+       if (active_bonds != NULL)       CFRelease(active_bonds);
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return (BondInterfaceRef) newBond;
+}
+
+
+static Boolean
+_BondPreferencesUpdate(BondPreferencesRef prefs, BondInterfaceRef bond)
+{
+       CFAllocatorRef                  allocator;
+       CFIndex                         bond_index;
+       CFArrayRef                      devices;
+       CFStringRef                     interface;
+       CFMutableDictionaryRef          newDict;
+       CFMutableArrayRef               newBonds;
+       CFDictionaryRef                 options;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+       CFArrayRef                      bonds;
+
+       bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+       if ((bonds != NULL) && !isA_CFArray(bonds)) {
+               // if the prefs are confused
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       interface = BondInterfaceGetInterface(bond);
+       bond_index = findBond(bonds, interface);
+       if (bond_index == kCFNotFound) {
+               _SCErrorSet(kSCStatusNoKey);
+               return FALSE;
+       }
+
+       /* create the bond dictionary */
+
+       allocator = CFGetAllocator(prefs);
+       newDict = CFDictionaryCreateMutable(allocator,
+                                           0,
+                                           &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+       CFDictionaryAddValue(newDict, __kBondInterface_interface, interface);
+
+       devices = BondInterfaceGetDevices(bond);
+       if (devices != NULL) {
+               CFDictionaryAddValue(newDict, __kBondInterface_devices, devices);
+       }
+
+       options = BondInterfaceGetOptions(bond);
+       if (options != NULL) {
+               CFDictionaryAddValue(newDict, __kBondInterface_options, options);
+       }
+
+       /* yes, we're going to be changing the configuration */
+       setConfigurationChanged(prefs);
+
+       /* update the prefs */
+
+       newBonds = CFArrayCreateMutableCopy(allocator, 0, bonds);
+       CFArraySetValueAtIndex(newBonds, bond_index, newDict);
+       CFRelease(newDict);
+       (void) SCPreferencesSetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS, newBonds);
+       CFRelease(newBonds);
+
+       return TRUE;
+}
+
+
+Boolean
+BondPreferencesAddDevice(BondPreferencesRef    prefs,
+                        BondInterfaceRef       bond,
+                        CFStringRef            device)
+{
+       CFArrayRef                      config_bonds;
+       CFIndex                         i;
+       CFIndex                         nConfig;
+       Boolean                         ok              = TRUE;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!isA_BondInterface(bond)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!isA_CFString(device)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!IsBondSupported(device)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       /* get "configured" bonds */
+       config_bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+       if ((config_bonds != NULL) && !isA_CFArray(config_bonds)) {
+               _SCErrorSet(kSCStatusFailed);
+               ok = FALSE;
+               goto done;
+       }
+
+       nConfig = (config_bonds != NULL) ? CFArrayGetCount(config_bonds) : 0;
+
+       /* check to ensure the requested device is available */
+       for (i = 0; ok && (i < nConfig); i++) {
+               CFDictionaryRef config_bond;
+               CFArrayRef      devices;
+
+               config_bond = CFArrayGetValueAtIndex(config_bonds, i);
+               if (!isA_CFDictionary(config_bond)) {
+                       ok = FALSE;     // if the prefs are confused
+                       break;
+               }
+
+               devices = CFDictionaryGetValue(config_bond, __kBondInterface_devices);
+               if ((devices != NULL) && !isA_CFArray(devices)) {
+                       ok = FALSE;     // if the prefs are confused
+                       break;
+               }
+
+               if (devices == NULL) {
+                       continue;       // if no devices
+               }
+
+               ok = !CFArrayContainsValue(devices,
+                                          CFRangeMake(0, CFArrayGetCount(devices)),
+                                          device);
+       }
+
+       if (ok) {
+               CFArrayRef              devices;
+               CFMutableArrayRef       newDevices;
+
+               devices = BondInterfaceGetDevices(bond);
+               if (devices != NULL) {
+                       devices = CFArrayCreateCopy(NULL, devices);
+                       newDevices = CFArrayCreateMutableCopy(NULL, 0, devices);
+               } else {
+                       newDevices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+               }
+               CFArrayAppendValue(newDevices, device);
+               BondInterfaceSetDevices(bond, newDevices);
+               CFRelease(newDevices);
+
+               ok = _BondPreferencesUpdate(prefs, bond);
+               if (!ok) {
+                       BondInterfaceSetDevices(bond, devices);
+               }
+
+               if (devices != NULL) {
+                       CFRelease(devices);
+               }
+       } else {
+               _SCErrorSet(kSCStatusKeyExists);
+       }
+
+    done :
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return ok;
+}
+
+
+Boolean
+BondPreferencesRemoveDevice(BondPreferencesRef prefs,
+                           BondInterfaceRef    bond,
+                           CFStringRef         device)
+{
+       CFIndex                         bond_index;
+       CFArrayRef                      devices;
+       Boolean                         ok              = FALSE;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!isA_BondInterface(bond)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!isA_CFString(device)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       devices = BondInterfaceGetDevices(bond);
+       if (devices != NULL) {
+               bond_index = CFArrayGetFirstIndexOfValue(devices,
+                                                        CFRangeMake(0, CFArrayGetCount(devices)),
+                                                        device);
+               if (bond_index != kCFNotFound) {
+                       CFMutableArrayRef       newDevices;
+
+                       devices = CFArrayCreateCopy(NULL, devices);
+                       newDevices = CFArrayCreateMutableCopy(NULL, 0, devices);
+                       CFArrayRemoveValueAtIndex(newDevices, bond_index);
+                       BondInterfaceSetDevices(bond, newDevices);
+                       CFRelease(newDevices);
+
+                       ok = _BondPreferencesUpdate(prefs, bond);
+                       if (!ok) {
+                               BondInterfaceSetDevices(bond, devices);
+                       }
+
+                       CFRelease(devices);
+               } else {
+                       _SCErrorSet(kSCStatusNoKey);
+               }
+       }
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return ok;
+}
+
+
+Boolean
+BondPreferencesSetOptions(BondPreferencesRef prefs, BondInterfaceRef bond, CFDictionaryRef newOptions)
+{
+       Boolean                         ok              = FALSE;
+       CFDictionaryRef                 options;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!isA_BondInterface(bond)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       options = BondInterfaceGetOptions(bond);
+       if (options != NULL) {
+               options = CFDictionaryCreateCopy(NULL, options);
+       }
+
+       BondInterfaceSetOptions(bond, newOptions);
+       ok = _BondPreferencesUpdate(prefs, bond);
+       if (!ok) {
+               BondInterfaceSetOptions(bond, options);
+       }
+
+       if (options != NULL) {
+               CFRelease(options);
+       }
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return ok;
+}
+
+
+Boolean
+BondPreferencesRemoveInterface(BondPreferencesRef      prefs,
+                              BondInterfaceRef         bond)
+{
+       CFIndex                         bond_index;
+       Boolean                         ok              = FALSE;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+       CFArrayRef                      bonds;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       if (!isA_BondInterface(bond)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       bonds = SCPreferencesGetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+       if (!isA_CFArray(bonds)) {
+               // if the prefs are confused
+               _SCErrorSet(kSCStatusFailed);
+               goto done;
+       }
+
+       bond_index = findBond(bonds, BondInterfaceGetInterface(bond));
+       if (bond_index == kCFNotFound) {
+               _SCErrorSet(kSCStatusNoKey);
+               goto done;
+       }
+
+       /* yes, we're going to be changing the configuration */
+       setConfigurationChanged(prefs);
+
+       /* remove the bond */
+
+       if (CFArrayGetCount(bonds) > 1) {
+               CFAllocatorRef          allocator;
+               CFMutableArrayRef       newBonds;
+
+               allocator = CFGetAllocator(prefs);
+               newBonds = CFArrayCreateMutableCopy(allocator, 0, bonds);
+               CFArrayRemoveValueAtIndex(newBonds, bond_index);
+               (void) SCPreferencesSetValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS, newBonds);
+               CFRelease(newBonds);
+       } else {
+               (void) SCPreferencesRemoveValue(prefsPrivate->prefs, BOND_PREFERENCES_BONDS);
+       }
+
+       ok = TRUE;
+
+    done :
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return ok;
+}
+
+
+Boolean
+BondPreferencesCommitChanges(BondPreferencesRef        prefs)
+{
+       Boolean                         ok              = FALSE;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       ok = SCPreferencesCommitChanges(prefsPrivate->prefs);
+       if (!ok) {
+               return ok;
+       }
+
+       if (prefsPrivate->bBase != NULL)  {
+               CFRelease(prefsPrivate->bBase);
+               prefsPrivate->bBase = NULL;
+       }
+
+       return TRUE;
+}
+
+
+Boolean
+_BondPreferencesUpdateConfiguration(BondPreferencesRef prefs)
+{
+       CFArrayRef                      active          = NULL;
+       CFArrayRef                      config          = NULL;
+       CFIndex                         i;
+       CFIndex                         nActive;
+       CFIndex                         nConfig;
+       Boolean                         ok              = FALSE;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+       int                             s               = -1;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       /* configured Bonds */
+       if (prefsPrivate->bBase != NULL) {
+               /*
+                * updated Bond preferences have not been committed
+                * so we ignore any in-progress changes and apply the
+                * saved preferences.
+                */
+               config = CFRetain(prefsPrivate->bBase);
+       } else {
+               /*
+                * apply the saved preferences
+                */
+               config = BondPreferencesCopyInterfaces(prefs);
+       }
+       nConfig = CFArrayGetCount(config);
+
+       /* active Bonds */
+       active  = _BondPreferencesCopyActiveInterfaces();
+       nActive = CFArrayGetCount(active);
+
+       /*
+        * remove any no-longer-configured bond interfaces and
+        * any devices associated with a bond that are no longer
+        * associated with a bond.
+        */
+       for (i = 0; i < nActive; i++) {
+               BondInterfaceRef        a_bond;
+               CFStringRef             a_bond_if;
+               CFIndex                 j;
+               Boolean                 found   = FALSE;
+
+               a_bond    = CFArrayGetValueAtIndex(active, i);
+               a_bond_if = BondInterfaceGetInterface(a_bond);
+
+               for (j = 0; j < nConfig; j++) {
+                       BondInterfaceRef        c_bond;
+                       CFStringRef             c_bond_if;
+
+                       c_bond    = CFArrayGetValueAtIndex(config, j);
+                       c_bond_if = BondInterfaceGetInterface(c_bond);
+
+                       if (CFEqual(a_bond_if, c_bond_if)) {
+                               CFIndex         a;
+                               CFIndex         a_count;
+                               CFArrayRef      a_bond_devices;
+                               CFIndex         c_count;
+                               CFArrayRef      c_bond_devices;
+
+                               c_bond_devices = BondInterfaceGetDevices(c_bond);
+                               c_count        = (c_bond_devices != NULL) ? CFArrayGetCount(c_bond_devices) : 0;
+
+                               a_bond_devices = BondInterfaceGetDevices(a_bond);
+                               a_count        = (a_bond_devices != NULL) ? CFArrayGetCount(a_bond_devices) : 0;
+
+                               for (a = 0; a < a_count; a++) {
+                                       CFStringRef     a_device;
+
+                                       a_device = CFArrayGetValueAtIndex(a_bond_devices, a);
+                                       if ((c_count == 0) ||
+                                           !CFArrayContainsValue(c_bond_devices,
+                                                                 CFRangeMake(0, c_count),
+                                                                 a_device)) {
+                                               /*
+                                                * if this device is no longer part
+                                                * of the bond.
+                                                */
+                                               if (s == -1) {
+                                                       s = inet_dgram_socket();
+                                               }
+
+                                               ok = _Bond_removeDevice(s, a_bond_if, a_device);
+                                               if (!ok) {
+                                                       goto done;
+                                               }
+                                       }
+                               }
+
+                               found = TRUE;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       /*
+                        * if this interface is no longer configured
+                        */
+                       if (s == -1) {
+                               s = inet_dgram_socket();
+                       }
+
+                       ok = __destroyInterface(s, a_bond_if);
+                       if (!ok) {
+                               _SCErrorSet(kSCStatusFailed);
+                               goto done;
+                       }
+               }
+       }
+
+       /*
+        * add any newly-configured bond interfaces and add any
+        * devices that should now be associated with the bond.
+        */
+       for (i = 0; i < nConfig; i++) {
+               BondInterfaceRef        c_bond;
+               CFArrayRef              c_bond_devices;
+               CFStringRef             c_bond_if;
+               CFIndex                 c_count;
+               Boolean                 found           = FALSE;
+               CFIndex                 j;
+
+               c_bond         = CFArrayGetValueAtIndex(config, i);
+               c_bond_if      = BondInterfaceGetInterface(c_bond);
+               c_bond_devices = BondInterfaceGetDevices(c_bond);
+               c_count        = (c_bond_devices != NULL) ? CFArrayGetCount(c_bond_devices) : 0;
+
+               for (j = 0; j < nActive; j++) {
+                       BondInterfaceRef        a_bond;
+                       CFArrayRef              a_bond_devices;
+                       CFStringRef             a_bond_if;
+                       CFIndex                 a_count;
+
+                       a_bond         = CFArrayGetValueAtIndex(active, j);
+                       a_bond_if      = BondInterfaceGetInterface(a_bond);
+                       a_bond_devices = BondInterfaceGetDevices(a_bond);
+                       a_count         = (a_bond_devices != NULL) ? CFArrayGetCount(a_bond_devices) : 0;
+
+                       if (CFEqual(c_bond_if, a_bond_if)) {
+                               CFIndex c;
+
+                               found = TRUE;
+
+                               if ((c_bond_devices == NULL) &&
+                                   (a_bond_devices == NULL)) {
+                                       break;  // if no change
+                               }
+
+                               if ((c_bond_devices != NULL) &&
+                                   (a_bond_devices != NULL) &&
+                                   CFEqual(c_bond_devices, a_bond_devices)) {
+                                       break;  // if no change
+                               }
+
+                               if (s == -1) {
+                                       s = inet_dgram_socket();
+                               }
+
+                               /*
+                                * ensure that the first device of the bond matches, if
+                                * not then we remove all current devices and add them
+                                * back in the preferred order.
+                                */
+                               if ((c_count > 0) &&
+                                   (a_count > 0) &&
+                                   !CFEqual(CFArrayGetValueAtIndex(c_bond_devices, 0),
+                                            CFArrayGetValueAtIndex(a_bond_devices, 0))) {
+                                       CFIndex a;
+
+                                       for (a = 0; a < a_count; a++) {
+                                               CFStringRef     a_device;
+
+                                               a_device = CFArrayGetValueAtIndex(a_bond_devices, a);
+
+                                               if (!CFArrayContainsValue(c_bond_devices,
+                                                                        CFRangeMake(0, c_count),
+                                                                        a_device)) {
+                                                       continue;       // if already removed
+                                               }
+
+                                               ok = _Bond_removeDevice(s, a_bond_if, a_device);
+                                               if (!ok) {
+                                                       goto done;
+                                               }
+                                       }
+
+                                       a_count = 0;    // all active devices have been removed
+                               }
+
+                               /*
+                                * add any devices which are not currently associated
+                                * with the bond interface.
+                                */
+                               for (c = 0; c < c_count; c++) {
+                                       CFStringRef     c_device;
+
+                                       c_device = CFArrayGetValueAtIndex(c_bond_devices, c);
+                                       if ((a_count == 0) ||
+                                           !CFArrayContainsValue(a_bond_devices,
+                                                                 CFRangeMake(0, a_count),
+                                                                 c_device)) {
+                                               /*
+                                                * check if this device can be added to
+                                                * a bond.
+                                                */
+                                               if (!IsBondSupported(c_device)) {
+                                                       // if not supported
+                                                       continue;
+                                               }
+
+                                               /*
+                                                * if this device is not currently part
+                                                * of the bond.
+                                                */
+
+                                               ok = _Bond_addDevice(s, c_bond_if, c_device);
+                                               if (!ok) {
+                                                       goto done;
+                                               }
+                                       }
+                               }
+
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       CFIndex c;
+
+                       if (s == -1) {
+                               s = inet_dgram_socket();
+                       }
+
+                       /*
+                        * establish the new bond interface.
+                        */
+                       ok = __createInterface(s, c_bond_if);
+                       if (!ok) {
+                               _SCErrorSet(kSCStatusFailed);
+                               goto done;
+                       }
+
+                       /*
+                        * add any devices which are not currently associated
+                        * with the bond interface.
+                        */
+                       for (c = 0; c < c_count; c++) {
+                               CFStringRef     c_device;
+
+                               c_device = CFArrayGetValueAtIndex(c_bond_devices, c);
+
+                               if (!IsBondSupported(c_device)) {
+                                       // if not supported
+                                       continue;
+                               }
+
+                               ok = _Bond_addDevice(s, c_bond_if, c_device);
+                               if (!ok) {
+                                       goto done;
+                               }
+                       }
+               }
+
+       }
+
+       ok = TRUE;
+
+    done :
+
+       if (active != NULL)     CFRelease(active);
+       if (config != NULL)     CFRelease(config);
+       if (s != -1)            (void) close(s);
+
+       return ok;
+}
+
+
+Boolean
+BondPreferencesApplyChanges(BondPreferencesRef prefs)
+{
+       Boolean                         ok              = FALSE;
+       BondPreferencesPrivateRef       prefsPrivate    = (BondPreferencesPrivateRef)prefs;
+
+       if (!isA_BondPreferences(prefs)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       /* apply the preferences */
+       ok = SCPreferencesApplyChanges(prefsPrivate->prefs);
+       if (!ok) {
+               goto done;
+       }
+
+       /* apply the Bond configuration */
+       ok = _BondPreferencesUpdateConfiguration(prefs);
+       if (!ok) {
+               goto done;
+       }
+
+    done :
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return ok;
+}
+
+
+/* ---------- BondStatus ---------- */
+
+typedef struct {
+
+       /* base CFType information */
+       CFRuntimeBase                   cfBase;
+
+       /* bond interface */
+       BondInterfaceRef                bond;
+
+       /* bond status */
+       CFDictionaryRef                 status_interface;       // interface status
+       CFArrayRef                      devices;                // per-device status
+       CFDictionaryRef                 status_devices;
+
+} BondStatusPrivate, * BondStatusPrivateRef;
+
+
+const CFStringRef kSCBondStatusDeviceAggregationStatus = CFSTR("AggregationStatus");
+const CFStringRef kSCBondStatusDeviceCollecting                = CFSTR("Collecting");
+const CFStringRef kSCBondStatusDeviceDistributing      = CFSTR("Distributing");
+
+
+static CFStringRef     __BondStatusCopyDescription     (CFTypeRef cf);
+static void            __BondStatusDeallocate          (CFTypeRef cf);
+static Boolean         __BondStatusEqual               (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static const CFRuntimeClass __BondStatusClass = {
+       0,                              // version
+       "BondStatus",                   // className
+       NULL,                           // init
+       NULL,                           // copy
+       __BondStatusDeallocate,         // dealloc
+       __BondStatusEqual,              // equal
+       NULL,                           // hash
+       NULL,                           // copyFormattingDesc
+       __BondStatusCopyDescription     // copyDebugDesc
+};
+
+
+static CFTypeID                __kBondStatusTypeID     = _kCFRuntimeNotATypeID;
+
+
+static pthread_once_t  bondStatus_init         = PTHREAD_ONCE_INIT;
+
+
+static CFStringRef
+__BondStatusCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef          allocator       = CFGetAllocator(cf);
+       CFMutableStringRef      result;
+       BondStatusPrivateRef    statusPrivate   = (BondStatusPrivateRef)cf;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<BondStatus %p [%p]> {"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR(" bond = %@"), statusPrivate->bond);
+       CFStringAppendFormat(result, NULL, CFSTR(" interface = %@"), statusPrivate->status_interface);
+       CFStringAppendFormat(result, NULL, CFSTR(" devices = %@"),   statusPrivate->status_devices);
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__BondStatusDeallocate(CFTypeRef cf)
+{
+       BondStatusPrivateRef    statusPrivate   = (BondStatusPrivateRef)cf;
+
+       /* release resources */
+
+       CFRelease(statusPrivate->bond);
+       CFRelease(statusPrivate->status_interface);
+       if (statusPrivate->devices != NULL) CFRelease(statusPrivate->devices);
+       CFRelease(statusPrivate->status_devices);
+       return;
+}
+
+
+static Boolean
+__BondStatusEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+       BondStatusPrivateRef    status1 = (BondStatusPrivateRef)cf1;
+       BondStatusPrivateRef    status2 = (BondStatusPrivateRef)cf2;
+
+       if (status1 == status2)
+               return TRUE;
+
+       if (!CFEqual(status1->bond, status2->bond))
+               return FALSE;   // if not the same bond
+
+       if (!CFEqual(status1->status_interface, status2->status_interface))
+               return FALSE;   // if not the same interface status
+
+       if (!CFEqual(status1->status_devices, status2->status_devices))
+               return FALSE;   // if not the same device status
+
+       return TRUE;
+}
+
+
+static void
+__BondStatusInitialize(void)
+{
+       __kBondStatusTypeID = _CFRuntimeRegisterClass(&__BondStatusClass);
+       return;
+}
+
+
+static __inline__ CFTypeRef
+isA_BondStatus(CFTypeRef obj)
+{
+       return (isA_CFType(obj, BondStatusGetTypeID()));
+}
+
+
+CFTypeID
+BondStatusGetTypeID(void)
+{
+       pthread_once(&bondStatus_init, __BondStatusInitialize); /* initialize runtime */
+       return __kBondStatusTypeID;
+}
+
+
+static BondStatusRef
+__BondStatusCreatePrivate(CFAllocatorRef       allocator,
+                         BondInterfaceRef      bond,
+                         CFDictionaryRef       status_interface,
+                         CFDictionaryRef       status_devices)
+{
+       BondStatusPrivateRef    statusPrivate;
+       uint32_t                size;
+
+       /* initialize runtime */
+       pthread_once(&bondStatus_init, __BondStatusInitialize);
+
+       /* allocate bond */
+       size          = sizeof(BondStatusPrivate) - sizeof(CFRuntimeBase);
+       statusPrivate = (BondStatusPrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                      __kBondStatusTypeID,
+                                                                      size,
+                                                                      NULL);
+       if (statusPrivate == NULL) {
+               return NULL;
+       }
+
+       /* establish the bond status */
+
+       statusPrivate->bond             = CFRetain(bond);
+       statusPrivate->status_interface = CFDictionaryCreateCopy(allocator, status_interface);
+       statusPrivate->devices          = NULL;
+       statusPrivate->status_devices   = CFDictionaryCreateCopy(allocator, status_devices);
+
+       return (BondStatusRef)statusPrivate;
+}
+
+
+BondStatusRef
+BondInterfaceCopyStatus(BondInterfaceRef bond)
+{
+       BondInterfacePrivateRef bondPrivate     = (BondInterfacePrivateRef)bond;
+       int                     bond_if_active;
+       int                     bond_if_status;
+       char                    bond_ifname[IFNAMSIZ + 1];
+       CFIndex                 i;
+       struct if_bond_status_req *ibsr_p = NULL;
+       CFIndex                 n;
+       CFNumberRef             num;
+       int                     s;
+       struct if_bond_status * scan_p;
+       BondStatusRef           status          = NULL;
+       CFMutableDictionaryRef  status_devices;
+       CFMutableDictionaryRef  status_interface;
+
+       if (!isA_BondInterface(bond)) {
+               return NULL;
+       }
+
+       s = inet_dgram_socket();
+       if (s < 0) {
+               goto done;
+       }
+       _SC_cfstring_to_cstring(bondPrivate->ifname, bond_ifname,
+                               sizeof(bond_ifname), kCFStringEncodingASCII);
+       (void)siocgifmedia(s, bond_ifname, &bond_if_status, &bond_if_active);
+       ibsr_p = if_bond_status_req_copy(s, bond_ifname);
+       if (ibsr_p == NULL) {
+               goto done;
+       }
+       status_interface = CFDictionaryCreateMutable(NULL,
+                                                    0,
+                                                    &kCFTypeDictionaryKeyCallBacks,
+                                                    &kCFTypeDictionaryValueCallBacks);
+
+       status_devices = CFDictionaryCreateMutable(NULL,
+                                                  0,
+                                                  &kCFTypeDictionaryKeyCallBacks,
+                                                  &kCFTypeDictionaryValueCallBacks);
+       n = ibsr_p->ibsr_total;
+       for (i = 0, scan_p = (struct if_bond_status *)ibsr_p->ibsr_buffer; i < n; i++, scan_p++) {
+               CFStringRef                     bond_if;
+               int                             collecting = 0;
+               int                             distributing = 0;
+               struct if_bond_partner_state *  ps;
+               CFMutableDictionaryRef          status_device;
+               int                             status_val;
+
+               ps = &scan_p->ibs_partner_state;
+
+               status_device = CFDictionaryCreateMutable(NULL,
+                                                         0,
+                                                         &kCFTypeDictionaryKeyCallBacks,
+                                                         &kCFTypeDictionaryValueCallBacks);
+               if (lacp_actor_partner_state_in_sync(scan_p->ibs_state)) {
+                       /* we're in-sync */
+                       status_val = kSCBondStatusOK;
+                       if (lacp_actor_partner_state_in_sync(ps->ibps_state)) {
+                               /* partner is also in-sync */
+                               if (lacp_actor_partner_state_collecting(scan_p->ibs_state)
+                                   && lacp_actor_partner_state_distributing(ps->ibps_state)) {
+                                       /* we're able to collect (receive) frames */
+                                       collecting = 1;
+                               }
+                               if (lacp_actor_partner_state_distributing(scan_p->ibs_state)
+                                   && lacp_actor_partner_state_collecting(ps->ibps_state)) {
+                                       /* we're able to distribute (transmit) frames */
+                                       distributing = 1;
+                               }
+                       }
+               }
+               else {
+                       int             active = 0;
+                       int             status = 0;
+                       lacp_system     zeroes = {{0,0,0,0,0,0}};
+
+                       (void)siocgifmedia(s, scan_p->ibs_if_name, &status, &active);
+                       if ((status & IFM_AVALID) == 0 || (status & IFM_ACTIVE) == 0
+                           || (active & IFM_FDX) == 0) {
+                               /* link down or not full-duplex */
+                               status_val = kSCBondStatusLinkInvalid;
+                       }
+                       else if (ps->ibps_system_priority == 0
+                                && bcmp(&zeroes, &ps->ibps_system, sizeof(zeroes)) == 0) {
+                               /* no one on the other end of the link */
+                               status_val = kSCBondStatusNoPartner;
+                       }
+                       else if (active != bond_if_active) {
+                               /* the link speed was different */
+                               status_val = kSCBondStatusLinkInvalid;
+                       }
+                       else {
+                               /* partner is not in the active group */
+                               status_val = kSCBondStatusNotInActiveGroup;
+                       }
+               }
+               num = CFNumberCreate(NULL, kCFNumberIntType, &status_val);
+               CFDictionarySetValue(status_device, kSCBondStatusDeviceAggregationStatus, num);
+               CFRelease(num);
+               num = CFNumberCreate(NULL, kCFNumberIntType, &collecting);
+               CFDictionarySetValue(status_device, kSCBondStatusDeviceCollecting, num);
+               CFRelease(num);
+               num = CFNumberCreate(NULL, kCFNumberIntType, &distributing);
+               CFDictionarySetValue(status_device, kSCBondStatusDeviceDistributing, num);
+               CFRelease(num);
+               bond_if = CFArrayGetValueAtIndex(bondPrivate->devices, i);
+               CFDictionarySetValue(status_devices, bond_if, status_device);
+               CFRelease(status_device);
+       }
+
+       status = __BondStatusCreatePrivate(NULL, bond, status_interface, status_devices);
+
+       CFRelease(status_interface);
+       CFRelease(status_devices);
+ done:
+       if (s >= 0) {
+               close(s);
+       }
+       if (ibsr_p != NULL) {
+               free(ibsr_p);
+       }
+       return status;
+}
+
+
+#define        N_QUICK 16
+
+
+CFArrayRef
+BondStatusGetDevices(BondStatusRef bondStatus)
+{
+       BondStatusPrivateRef    statusPrivate   = (BondStatusPrivateRef)bondStatus;
+
+       if (!isA_BondStatus(bondStatus)) {
+               return NULL;
+       }
+
+       if (statusPrivate->devices == NULL) {
+               const void *    keys_q[N_QUICK];
+               const void **   keys    = keys_q;
+               CFIndex         n;
+
+               n = CFDictionaryGetCount(statusPrivate->status_devices);
+               if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+                       keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+               }
+               CFDictionaryGetKeysAndValues(statusPrivate->status_devices, keys, NULL);
+               statusPrivate->devices = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(NULL, keys);
+               }
+       }
+
+       return statusPrivate->devices;
+}
+
+
+CFDictionaryRef
+BondStatusGetInterfaceStatus(BondStatusRef bondStatus)
+{
+       BondStatusPrivateRef    statusPrivate   = (BondStatusPrivateRef)bondStatus;
+
+       if (!isA_BondStatus(bondStatus)) {
+               return NULL;
+       }
+
+       return statusPrivate->status_interface;
+}
+
+
+CFDictionaryRef
+BondStatusGetDeviceStatus(BondStatusRef bondStatus, CFStringRef device)
+{
+       BondStatusPrivateRef    statusPrivate   = (BondStatusPrivateRef)bondStatus;
+
+       if (!isA_BondStatus(bondStatus)) {
+               return NULL;
+       }
+
+       return CFDictionaryGetValue(statusPrivate->status_devices, device);
+}
diff --git a/SystemConfiguration.fproj/BondConfiguration.h b/SystemConfiguration.fproj/BondConfiguration.h
new file mode 100644 (file)
index 0000000..f634ed7
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+
+
+typedef const struct __BondInterface *         BondInterfaceRef;
+
+typedef const struct __BondPreferences *       BondPreferencesRef;
+
+typedef const struct __BondStatus *            BondStatusRef;
+
+
+enum {
+       kSCBondStatusOK                 = 0,    /* enabled, active, running, ... */
+       kSCBondStatusLinkInvalid        = 1,    /* The link state was not valid (i.e. down, half-duplex, wrong speed) */
+       kSCBondStatusNoPartner          = 2,    /* The port on the switch that the device is connected doesn't seem to have 802.3ad Link Aggregation enabled */
+       kSCBondStatusNotInActiveGroup   = 3,    /* We're talking to a partner, but the link aggregation group is different from the one that's active */
+       kSCBondStatusUnknown            = 999   /* Non-specific failure */
+};
+
+extern const CFStringRef kSCBondStatusDeviceAggregationStatus  /* CFNumber */          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern const CFStringRef kSCBondStatusDeviceCollecting         /* CFNumber (0 or 1) */ AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern const CFStringRef kSCBondStatusDeviceDistributing       /* CFNumber (0 or 1) */ AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+__BEGIN_DECLS
+
+// ----------
+
+extern const CFStringRef kSCNetworkInterfaceTypeBOND;
+
+Boolean
+SCNetworkInterfaceSupportsBonding      (SCNetworkInterfaceRef  interface)              AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithBond       (BondInterfaceRef       bond)                   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+// ----------
+
+Boolean
+IsBondSupported                                (CFStringRef            device)                 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      // e.g. "en0", "en1", ...
+
+// ----------
+
+CFTypeID
+BondInterfaceGetTypeID                 (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFStringRef
+BondInterfaceGetInterface              (BondInterfaceRef       bond)                   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      // returns "bond0", "bond1", ...
+
+CFArrayRef /* of CFStringRef's */
+BondInterfaceGetDevices                        (BondInterfaceRef       bond)                   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFDictionaryRef
+BondInterfaceGetOptions                        (BondInterfaceRef       bond)                   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      // e.g. UserDefinedName, ...
+
+// ----------
+
+CFTypeID
+BondPreferencesGetTypeID               (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+BondPreferencesRef
+BondPreferencesCreate                  (CFAllocatorRef         allocator)              AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFArrayRef /* of BondInterfaceRef's */
+BondPreferencesCopyInterfaces          (BondPreferencesRef     prefs)                  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+BondInterfaceRef
+BondPreferencesCreateInterface         (BondPreferencesRef     prefs)                  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesRemoveInterface         (BondPreferencesRef     prefs,
+                                        BondInterfaceRef       bond)                   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesAddDevice               (BondPreferencesRef     prefs,
+                                        BondInterfaceRef       bond,
+                                        CFStringRef            device)                 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      // e.g. "en0", "en1", ...
+
+Boolean
+BondPreferencesRemoveDevice            (BondPreferencesRef     prefs,
+                                        BondInterfaceRef       bond,
+                                        CFStringRef            device)                 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      // e.g. "en0", "en1", ...
+
+Boolean
+BondPreferencesSetOptions              (BondPreferencesRef     prefs,
+                                        BondInterfaceRef       bond,
+                                        CFDictionaryRef        newOptions)             AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesCommitChanges           (BondPreferencesRef     prefs)                  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+Boolean
+BondPreferencesApplyChanges            (BondPreferencesRef     prefs)                  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+// ----------
+
+CFTypeID
+BondStatusGetTypeID                    (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+BondStatusRef
+BondInterfaceCopyStatus                        (BondInterfaceRef       bond)                   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFArrayRef
+BondStatusGetDevices                   (BondStatusRef          bondStatus)             AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFDictionaryRef
+BondStatusGetInterfaceStatus           (BondStatusRef          bondStatus)             AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+CFDictionaryRef
+BondStatusGetDeviceStatus              (BondStatusRef          bondStatus,
+                                        CFStringRef            device)                 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+__END_DECLS
+
+#endif /* _BONDCONFIGURATION_H */
diff --git a/SystemConfiguration.fproj/BondConfigurationPrivate.h b/SystemConfiguration.fproj/BondConfigurationPrivate.h
new file mode 100644 (file)
index 0000000..4e6d4d5
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <SystemConfiguration/BondConfiguration.h>
+
+
+/*!
+       @header BONDConfigurationPrivate
+ */
+
+
+#define BOND_PREFERENCES_ID    CFSTR("VirtualNetworkInterfaces.plist")
+
+
+__BEGIN_DECLS
+
+CFArrayRef
+_BondPreferencesCopyActiveInterfaces   ();
+
+Boolean
+_BondPreferencesUpdateConfiguration    (BondPreferencesRef     prefs);
+
+__END_DECLS
+
+#endif /* _BONDCONFIGURATIONPRIVATE_H */
diff --git a/SystemConfiguration.fproj/CustomInfo.plist b/SystemConfiguration.fproj/CustomInfo.plist
deleted file mode 100644 (file)
index b2deea5..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-       CFBundleName = "SystemConfiguration";
-       CFBundleIdentifier = "com.apple.SystemConfiguration";
-       CFBundleShortVersionString = "1.7.1";
-}
index 7b6d1d724dbdf9c87a579b56bdb42e9a1e7c386f..2adc1949a17fbccd84d31c3ebfd8e8e5689bee76 100644 (file)
@@ -106,7 +106,7 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
 {
     CFMutableDictionaryRef     dict = NULL;
     CFStringRef                        path = NULL;
 {
     CFMutableDictionaryRef     dict = NULL;
     CFStringRef                        path = NULL;
-    SCPreferencesRef           session = NULL;
+    SCPreferencesRef           prefs = NULL;
     Boolean                    success = FALSE;
 
     if (applicationID == NULL) {
     Boolean                    success = FALSE;
 
     if (applicationID == NULL) {
@@ -116,12 +116,12 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
     if (path == NULL) {
        goto done;
     }
     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;
     }
        goto done;
     }
-    dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(session, path);
+    dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(prefs, path);
     if (dict == NULL) {
        dict = CFDictionaryCreateMutable(NULL, 0,
                                         &kCFTypeDictionaryKeyCallBacks,
     if (dict == NULL) {
        dict = CFDictionaryCreateMutable(NULL, 0,
                                         &kCFTypeDictionaryKeyCallBacks,
@@ -165,19 +165,19 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
     else {
        CFDictionaryRemoveValue(dict, CFSTR(DHCP_REQUESTED_PARAMETER_LIST));
     }
     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) {
        if (success) {
-           success = SCPreferencesCommitChanges(session);
+           success = SCPreferencesCommitChanges(prefs);
            if (success) {
            if (success) {
-               (void)SCPreferencesApplyChanges(session);
+               (void)SCPreferencesApplyChanges(prefs);
            }
        }
            }
        }
-       (void)SCPreferencesUnlock(session);
+       (void)SCPreferencesUnlock(prefs);
     }
  done:
     }
  done:
-    if (session) {
-       CFRelease(session);
+    if (prefs) {
+       CFRelease(prefs);
     }
     if (path) {
        CFRelease(path);
     }
     if (path) {
        CFRelease(path);
@@ -196,7 +196,7 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID,
     UInt8 *                    options = NULL;
     CFArrayRef                 parms;
     CFStringRef                        path = NULL;
     UInt8 *                    options = NULL;
     CFArrayRef                 parms;
     CFStringRef                        path = NULL;
-    SCPreferencesRef           session = NULL;
+    SCPreferencesRef           prefs = NULL;
 
     if (applicationID == NULL) {
        goto done;
 
     if (applicationID == NULL) {
        goto done;
@@ -205,12 +205,12 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID,
     if (path == NULL) {
        goto done;
     }
     if (path == NULL) {
        goto done;
     }
-    session = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"),
-                                 CFSTR(DHCPCLIENT_PREFERENCES_ID));
-    if (session == NULL) {
+    prefs = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"),
+                               CFSTR(DHCPCLIENT_PREFERENCES_ID));
+    if (prefs == NULL) {
        goto done;
     }
        goto done;
     }
-    dict = SCPreferencesPathGetValue(session, path);
+    dict = SCPreferencesPathGetValue(prefs, path);
     if (dict == NULL) {
        goto done;
     }
     if (dict == NULL) {
        goto done;
     }
@@ -222,8 +222,8 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID,
     options = S_get_char_array(parms, count);
 
  done:
     options = S_get_char_array(parms, count);
 
  done:
-    if (session) {
-       CFRelease(session);
+    if (prefs) {
+       CFRelease(prefs);
     }
     if (path) {
        CFRelease(path);
     }
     if (path) {
        CFRelease(path);
index 7ba074a5ea57fa6d70c1e11bb397e116c53b9631..5e0d0054e10a1758d904c1f1afab90898900bf8c 100644 (file)
@@ -28,7 +28,9 @@
 #include <CoreFoundation/CFString.h>
 
 /*!
 #include <CoreFoundation/CFString.h>
 
 /*!
-       @header DHCPClientPreferences.h
+       @header DHCPClientPreferences
+       @discussion The DHCPClientPreferences API allows applications to get and update DHCP preferences.
+               DHCP preferences are in the form of DHCP option codes, which are defined in RFC 2132.
  */
 
 __BEGIN_DECLS
  */
 
 __BEGIN_DECLS
@@ -36,15 +38,15 @@ __BEGIN_DECLS
 /*!
        @function DHCPClientPreferencesSetApplicationOptions
        @discussion Updates the DHCP client preferences to include the
 /*!
        @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
        @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.
                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
  */
 
 Boolean
@@ -55,14 +57,14 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
 /*!
        @function DHCPClientPreferencesCopyApplicationOptions
        @discussion Copies the requested DHCP options for the
 /*!
        @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.
        @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.
 
                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 *
  */
 
 UInt8 *
index 0ee06ce981e4c2f1fe867f178d14abb00b62d6a5..b904d0f3ba024ba30f5b7a532ddc926bad545874 100644 (file)
@@ -82,8 +82,6 @@ __DeviceOnHoldDeallocate(CFTypeRef cf)
 {
        DeviceOnHoldPrivateRef  DeviceOnHoldPrivate     = (DeviceOnHoldPrivateRef)cf;
 
 {
        DeviceOnHoldPrivateRef  DeviceOnHoldPrivate     = (DeviceOnHoldPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__DeviceOnHoldDeallocate:"));
-
        /* release resources */
        if (DeviceOnHoldPrivate->name)          CFRelease(DeviceOnHoldPrivate->name);
        if (DeviceOnHoldPrivate->sock != -1) {
        /* 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;
        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;
 
        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");
                }
 
                deviceToMatch = IOServiceMatching("InternalModemSupport");
-               if (!deviceToMatch) {
-                       goto errorExit;
+               if (deviceToMatch == NULL) {
+                       return FALSE;
                }
 
                kr = IOServiceGetMatchingServices(masterPort, deviceToMatch, &matchingServices);
                if (kr != KERN_SUCCESS) {
                }
 
                kr = IOServiceGetMatchingServices(masterPort, deviceToMatch, &matchingServices);
                if (kr != KERN_SUCCESS) {
-                       goto errorExit;
+                       return FALSE;
                }
 
                for ( ; (service = IOIteratorNext(matchingServices)) ; IOObjectRelease(service)) {
                }
 
                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;
        //       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;
 
        DeviceOnHoldPrivateRef  devicePrivate;
        int                     status;
 
-       if (CFStringCompare(deviceName, CFSTR("modem"), NULL) != kCFCompareEqualTo) {
+       if (CFStringCompare(deviceName, CFSTR("modem"), 0) != kCFCompareEqualTo) {
                return NULL;
        }
 
                return NULL;
        }
 
index 7cd4902bff6660cfaf5244e833313f234658d2c3..0d88c539558b1b25ead79f5d56c363e2a90a8a7f 100644 (file)
 #include <CoreFoundation/CoreFoundation.h>
 
 
 #include <CoreFoundation/CoreFoundation.h>
 
 
+/*!
+       @header DeviceOnHold
+ */
+
+
 /*!
        @enum
        @discussion Returned status codes from DeviceOnHoldGetStatus()
 /*!
        @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 (file)
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 (file)
index 0000000..65f8955
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundleGetInfoString</key>
+       <string>1.8.0</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.apple.SystemConfiguration</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleName</key>
+       <string>SystemConfiguration</string>
+       <key>CFBundlePackageType</key>
+       <string>FMWK</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.8.0</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>1.8.0</string>
+</dict>
+</plist>
index b88db0e8a4f3ba0a4e8a98526880da89d80b6440..202e6507e2873fab30cfb9c962bc18ee014cdc44 100644 (file)
@@ -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;
        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 */
 
        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' */
        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) {
 
        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;
        }
 
                goto done;
        }
 
@@ -552,38 +559,22 @@ NetworkInterfaceCopyMTU(CFStringRef       interface,
 
        /* get valid MTU range */
 
 
        /* 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;
        }
 
        ok = TRUE;
index f33f8c714fc0555ace0eb33a0ddb72526669b4b4..cb598fda7d92f3c36f9a6384f4f2860e5841fff5 100644 (file)
@@ -28,6 +28,9 @@
 #include <sys/cdefs.h>
 #include <CoreFoundation/CoreFoundation.h>
 
 #include <sys/cdefs.h>
 #include <CoreFoundation/CoreFoundation.h>
 
+/*!
+       @header LinkConfiguration
+*/
 
 __BEGIN_DECLS
 
 
 __BEGIN_DECLS
 
index 1b406d47e3534b32476dec03806a0c7d27390839..dad23e63b4cd16868c8f2c7e49bb2de66ebcd978 100644 (file)
@@ -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 (file)
index 6b3aedf..0000000
+++ /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 (file)
index ac111af..0000000
+++ /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: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-# DSTROOT = $(HOME)
-
-# Additional flags for MiG generated files
-OTHER_PRIVATE_HEADERS += config.defs config.h
-
-OTHER_PRIVATE_HEADERS += SCPrivate.h
-OTHER_PRIVATE_HEADERS += SCDynamicStorePrivate.h
-OTHER_PRIVATE_HEADERS += SCDynamicStoreCopySpecificPrivate.h
-OTHER_PRIVATE_HEADERS += SCDynamicStoreSetSpecificPrivate.h
-OTHER_PRIVATE_HEADERS += SCPreferencesPrivate.h
-OTHER_PRIVATE_HEADERS += SCValidation.h
-OTHER_PRIVATE_HEADERS += SCDPlugin.h
-OTHER_PRIVATE_HEADERS += DeviceOnHold.h
-OTHER_PRIVATE_HEADERS += LinkConfiguration.h
-OTHER_PRIVATE_HEADERS += VLANConfiguration.h
-OTHER_PRIVATE_HEADERS += VLANConfigurationPrivate.h
-
-#
-# MiG generated files
-#
-OTHER_OFILES          += configUser.o
-
-# Additional options to create generated headers, source
-BEFORE_INSTALLHDRS       =  before_installhdrs
-OTHER_SOURCEFILES        += genSCPreferences.c
-OTHER_GENERATED_SRCFILES += SCSchemaDefinitions_10_1.h
-OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.h
-OTHER_GENERATED_SRCFILES += SCSchemaDefinitions.c
-OTHER_PUBLIC_HEADERS     += SCSchemaDefinitions_10_1.h
-OTHER_PUBLIC_HEADERS     += SCSchemaDefinitions.h
-OTHER_OFILES             += SCSchemaDefinitions.o
-
-# Additional build flags
-ifeq "$(PLATFORM_OS)" "macos"
-ifneq "$(RC_RELEASE)" "Darwin"
-       APPLE_INTERNAL_DIR ?= /AppleInternal
-       APPLE_INTERNAL_DEVELOPER_DIR ?= /AppleInternal/Developer
-       OTHER_LDFLAGS += -seg_addr_table $(APPLE_INTERNAL_DEVELOPER_DIR)/seg_addr_table
-       SECTORDER_FLAGS = -sectorder __TEXT __text $(APPLE_INTERNAL_DIR)/OrderFiles/SystemConfiguration.order
-endif
-endif
diff --git a/SystemConfiguration.fproj/NetworkConfiguration.plist b/SystemConfiguration.fproj/NetworkConfiguration.plist
new file mode 100644 (file)
index 0000000..a56f100
--- /dev/null
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Interface</key>
+       <dict>
+               <key>6to4-IPv4</key>
+               <dict/>
+               <key>Bluetooth</key>
+               <dict/>
+               <key>Bond</key>
+               <dict/>
+               <key>Ethernet</key>
+               <dict/>
+               <key>FireWire</key>
+               <dict/>
+               <key>IEEE80211</key>
+               <dict/>
+               <key>IrDA</key>
+               <dict/>
+               <key>L2TP-IPv4</key>
+               <dict/>
+               <key>Modem</key>
+               <dict>
+                       <key>ConnectionScript</key>
+                       <string>Apple Internal 56K Modem (v.92)</string>
+                       <key>DataCompression</key>
+                       <integer>1</integer>
+                       <key>DialMode</key>
+                       <string>WaitForDialTone</string>
+                       <key>ErrorCorrection</key>
+                       <integer>1</integer>
+                       <key>HoldCallWaitingAudibleAlert</key>
+                       <integer>1</integer>
+                       <key>HoldDisconnectOnAnswer</key>
+                       <integer>0</integer>
+                       <key>HoldEnabled</key>
+                       <integer>0</integer>
+                       <key>HoldReminder</key>
+                       <integer>1</integer>
+                       <key>HoldReminderTime</key>
+                       <integer>10</integer>
+                       <key>PulseDial</key>
+                       <integer>0</integer>
+                       <key>Speaker</key>
+                       <integer>1</integer>
+               </dict>
+               <key>PPP-Bluetooth</key>
+               <dict/>
+               <key>PPP-Ethernet</key>
+               <dict>
+                       <key>ACSPEnabled</key>
+                       <integer>0</integer>
+                       <key>CommDisplayTerminalWindow</key>
+                       <integer>0</integer>
+                       <key>CommRedialCount</key>
+                       <integer>1</integer>
+                       <key>CommRedialEnabled</key>
+                       <integer>1</integer>
+                       <key>CommRedialInterval</key>
+                       <integer>5</integer>
+                       <key>CommUseTerminalScript</key>
+                       <integer>0</integer>
+                       <key>DialOnDemand</key>
+                       <integer>0</integer>
+                       <key>DisconnectOnIdle</key>
+                       <integer>0</integer>
+                       <key>DisconnectOnIdleTimer</key>
+                       <integer>1800</integer>
+                       <key>DisconnectOnLogout</key>
+                       <integer>1</integer>
+                       <key>DisconnectOnSleep</key>
+                       <integer>1</integer>
+                       <key>IPCPCompressionVJ</key>
+                       <integer>1</integer>
+                       <key>IdleReminder</key>
+                       <integer>0</integer>
+                       <key>IdleReminderTimer</key>
+                       <integer>1800</integer>
+                       <key>LCPEchoEnabled</key>
+                       <integer>1</integer>
+                       <key>LCPEchoFailure</key>
+                       <integer>4</integer>
+                       <key>LCPEchoInterval</key>
+                       <integer>10</integer>
+                       <key>Logfile</key>
+                       <string>/var/log/ppp.log</string>
+                       <key>VerboseLogging</key>
+                       <integer>0</integer>
+               </dict>
+               <key>PPP-IrDA</key>
+               <dict/>
+               <key>PPP-L2TP</key>
+               <dict/>
+               <key>PPP-Modem</key>
+               <dict>
+                       <key>ACSPEnabled</key>
+                       <integer>0</integer>
+                       <key>CommDisplayTerminalWindow</key>
+                       <integer>0</integer>
+                       <key>CommRedialCount</key>
+                       <integer>1</integer>
+                       <key>CommRedialEnabled</key>
+                       <integer>1</integer>
+                       <key>CommRedialInterval</key>
+                       <integer>5</integer>
+                       <key>CommUseTerminalScript</key>
+                       <integer>0</integer>
+                       <key>DialOnDemand</key>
+                       <integer>0</integer>
+                       <key>DisconnectOnIdle</key>
+                       <integer>1</integer>
+                       <key>DisconnectOnIdleTimer</key>
+                       <integer>600</integer>
+                       <key>DisconnectOnLogout</key>
+                       <integer>1</integer>
+                       <key>DisconnectOnSleep</key>
+                       <integer>1</integer>
+                       <key>IPCPCompressionVJ</key>
+                       <integer>1</integer>
+                       <key>IdleReminder</key>
+                       <integer>0</integer>
+                       <key>IdleReminderTimer</key>
+                       <integer>1800</integer>
+                       <key>LCPEchoEnabled</key>
+                       <integer>1</integer>
+                       <key>LCPEchoFailure</key>
+                       <integer>4</integer>
+                       <key>LCPEchoInterval</key>
+                       <integer>10</integer>
+                       <key>Logfile</key>
+                       <string>/var/log/ppp.log</string>
+                       <key>VerboseLogging</key>
+                       <integer>0</integer>
+               </dict>
+               <key>PPP-PPTP</key>
+               <dict/>
+               <key>PPP-Serial</key>
+               <dict/>
+               <key>PPTP-IPv4</key>
+               <dict/>
+               <key>Serial</key>
+               <dict/>
+               <key>VLAN</key>
+               <dict/>
+       </dict>
+       <key>Protocol</key>
+       <dict>
+               <key>6to4-IPv4</key>
+               <dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>6to4</string>
+                       </dict>
+               </dict>
+               <key>Bond</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>DHCP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>Ethernet</key>
+               <dict>
+                       <key>AppleTalk</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Node</string>
+                       </dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>DHCP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>FireWire</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>DHCP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>IEEE80211</key>
+               <dict>
+                       <key>AppleTalk</key>
+                       <dict/>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>DHCP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict/>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-Bluetooth</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-Ethernet</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-IrDA</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-L2TP</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-Modem</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-PPTP</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPP-Serial</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>PPP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+               <key>PPTP-IPv4</key>
+               <dict/>
+               <key>PPTP-L2TP</key>
+               <dict/>
+               <key>VLAN</key>
+               <dict>
+                       <key>DNS</key>
+                       <dict/>
+                       <key>IPv4</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>DHCP</string>
+                       </dict>
+                       <key>IPv6</key>
+                       <dict>
+                               <key>ConfigMethod</key>
+                               <string>Automatic</string>
+                       </dict>
+                       <key>Proxies</key>
+                       <dict>
+                               <key>FTPPassive</key>
+                               <integer>1</integer>
+                       </dict>
+               </dict>
+       </dict>
+</dict>
+</plist>
diff --git a/SystemConfiguration.fproj/PB.project b/SystemConfiguration.fproj/PB.project
deleted file mode 100644 (file)
index 3d2e5a7..0000000
+++ /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"; 
-}
index 50c0f86bb819753ba3a6f893998d7aed8da16fa6..188bfaaa328667b9dd422d5a5ce150d67af661db 100644 (file)
@@ -475,7 +475,7 @@ typedef struct {
 
 
 static pthread_once_t  tsKeyInitialized        = PTHREAD_ONCE_INIT;
 
 
 static pthread_once_t  tsKeyInitialized        = PTHREAD_ONCE_INIT;
-static pthread_key_t   tsDataKey               = NULL;
+static pthread_key_t   tsDataKey;
 
 
 static void
 
 
 static void
index 00503ab652b223a19fde5376b79a6bf6626da97c..0e12fbb20e21028fc72aff1a43bd672ea12a3b6b 100644 (file)
@@ -40,7 +40,7 @@
 #include "config.h"            /* MiG generated file */
 
 Boolean
 #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;
 {
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        kern_return_t                   status;
@@ -53,13 +53,77 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR
        int                             newInstance;
        int                             sc_status;
 
        int                             newInstance;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), value);
+       if (store == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoStoreSession);
+       }
+
+       if (storePrivate->server == MACH_PORT_NULL) {
+               /* sorry, you must have an open session to play */
+               _SCErrorSet(kSCStatusNoStoreServer);
+               return FALSE;
+       }
+
+       /* serialize the key */
+       if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       /* serialize the data */
+       if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) {
+               CFRelease(utfKey);
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       /* send the key & data to the server */
+       status = configadd_s(storePrivate->server,
+                            myKeyRef,
+                            myKeyLen,
+                            myDataRef,
+                            myDataLen,
+                            &newInstance,
+                            (int *)&sc_status);
+
+       /* clean up */
+       CFRelease(utfKey);
+       CFRelease(xmlData);
+
+       if (status != KERN_SUCCESS) {
+#ifdef DEBUG
+               if (status != MACH_SEND_INVALID_DEST)
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue configadd_s(): %s"), mach_error_string(status));
+#endif /* DEBUG */
+               (void) mach_port_destroy(mach_task_self(), storePrivate->server);
+               storePrivate->server = MACH_PORT_NULL;
+               _SCErrorSet(status);
+               return FALSE;
        }
 
        }
 
-       if (!store) {
+       if (sc_status != kSCStatusOK) {
+               _SCErrorSet(sc_status);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+Boolean
+SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+{
+       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
+       kern_return_t                   status;
+       CFDataRef                       utfKey;         /* serialized key */
+       xmlData_t                       myKeyRef;
+       CFIndex                         myKeyLen;
+       CFDataRef                       xmlData;        /* serialized data */
+       xmlData_t                       myDataRef;
+       CFIndex                         myDataLen;
+       int                             newInstance;
+       int                             sc_status;
+
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        CFRelease(xmlData);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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 (file)
index 7957db1..0000000
+++ /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 <ajn@apple.com>
- * - public API conversion
- *
- * October 17, 2000            Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-#include "SCDynamicStoreInternal.h"
-#include "config.h"            /* MiG generated file */
-
-Boolean
-SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
-{
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
-       kern_return_t                   status;
-       CFDataRef                       utfKey;         /* serialized key */
-       xmlData_t                       myKeyRef;
-       CFIndex                         myKeyLen;
-       CFDataRef                       xmlData;        /* serialized data */
-       xmlData_t                       myDataRef;
-       CFIndex                         myDataLen;
-       int                             newInstance;
-       int                             sc_status;
-
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), value);
-       }
-
-       if (!store) {
-               /* sorry, you must provide a session */
-               _SCErrorSet(kSCStatusNoStoreSession);
-               return FALSE;
-       }
-
-       if (storePrivate->server == MACH_PORT_NULL) {
-               /* sorry, you must have an open session to play */
-               _SCErrorSet(kSCStatusNoStoreServer);
-               return FALSE;
-       }
-
-       /* serialize the key */
-       if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
-       }
-
-       /* serialize the data */
-       if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) {
-               CFRelease(utfKey);
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
-       }
-
-       /* send the key & data to the server */
-       status = configadd_s(storePrivate->server,
-                           myKeyRef,
-                           myKeyLen,
-                           myDataRef,
-                           myDataLen,
-                           &newInstance,
-                           (int *)&sc_status);
-
-       /* clean up */
-       CFRelease(utfKey);
-       CFRelease(xmlData);
-
-       if (status != KERN_SUCCESS) {
-               if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configadd_s(): %s"), mach_error_string(status));
-               (void) mach_port_destroy(mach_task_self(), storePrivate->server);
-               storePrivate->server = MACH_PORT_NULL;
-               _SCErrorSet(status);
-               return FALSE;
-       }
-
-       if (sc_status != kSCStatusOK) {
-               _SCErrorSet(sc_status);
-               return FALSE;
-       }
-
-       return TRUE;
-}
index ad97b87c5320e375f4930965ce3ade9edd43a471..6fc7bc62aabbce7de37824ce5f53fe949a92c501 100644 (file)
 #endif
 
 
 #endif
 
 
-const CFStringRef kSCConsoleSessionID          = CFSTR("kCGSSessionIDKey");            /* value is CFNumber */
-const CFStringRef kSCConsoleSessionUserName    = CFSTR("kCGSSessionUserNameKey");      /* value is CFString */
-const CFStringRef kSCConsoleSessionUID         = CFSTR("kCGSSessionUserIDKey");        /* value is CFNumber */
-const CFStringRef kSCConsoleSessionConsoleSet  = CFSTR("kCGSSessionConsoleSetKey");    /* value is CFNumber */
-const CFStringRef kSCConsoleSessionOnConsole   = CFSTR("kCGSSessionOnConsoleKey");     /* value is CFBoolean */
+// from CoreGraphics (CGSession.h)
+const CFStringRef kSCConsoleSessionUserName            = CFSTR("kCGSSessionUserNameKey");              /* value is CFString */
+const CFStringRef kSCConsoleSessionUID                 = CFSTR("kCGSSessionUserIDKey");                /* value is CFNumber (a uid_t) */
+const CFStringRef kSCConsoleSessionConsoleSet          = CFSTR("kCGSSessionConsoleSetKey");            /* value is CFNumber */
+const CFStringRef kSCConsoleSessionOnConsole           = CFSTR("kCGSSessionOnConsoleKey");             /* value is CFBoolean */
+const CFStringRef kSCConsoleSessionLoginDone           = CFSTR("kCGSessionLoginDoneKey");              /* value is CFBoolean */
+
+// from CoreGraphics (CGSSession.h)
+const CFStringRef kSCConsoleSessionID                  = CFSTR("kCGSSessionIDKey");                    /* value is CFNumber */
+
+// from loginwindow
+const CFStringRef kSCConsoleSessionSystemSafeBoot      = CFSTR("kCGSSessionSystemSafeBoot");           /* value is CFBoolean */
+const CFStringRef kSCConsoleSessionLoginwindowSafeLogin        = CFSTR("kCGSSessionLoginwindowSafeLogin");     /* value is CFBoolean */
 
 
 CFStringRef
 
 
 CFStringRef
@@ -84,13 +92,12 @@ SCDynamicStoreCopyConsoleUser(SCDynamicStoreRef     store,
        CFStringRef             key;
        Boolean                 tempSession     = FALSE;
 
        CFStringRef             key;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyConsoleUser"),
                                             NULL,
                                             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;
                        return NULL;
                }
                tempSession = TRUE;
@@ -153,13 +160,12 @@ SCDynamicStoreCopyConsoleInformation(SCDynamicStoreRef store)
        CFStringRef             key;
        Boolean                 tempSession     = FALSE;
 
        CFStringRef             key;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyConsoleUser"),
                                             NULL,
                                             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;
                        return NULL;
                }
                tempSession = TRUE;
@@ -200,24 +206,22 @@ SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef     store,
        CFStringRef             consoleUser;
        CFMutableDictionaryRef  dict            = NULL;
        CFStringRef             key             = SCDynamicStoreKeyCreateConsoleUser(NULL);
        CFStringRef             consoleUser;
        CFMutableDictionaryRef  dict            = NULL;
        CFStringRef             key             = SCDynamicStoreKeyCreateConsoleUser(NULL);
-       CFNumberRef             num;
        Boolean                 ok              = TRUE;
        Boolean                 tempSession     = FALSE;
 
        Boolean                 ok              = TRUE;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreSetConsoleUser"),
                                             NULL,
                                             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;
        }
 
                        return FALSE;
                }
                tempSession = TRUE;
        }
 
-       if (user == NULL) {
-               ok = SCDynamicStoreRemoveValue(store, key);
+       if ((user == NULL) && (sessions == NULL)) {
+               (void) SCDynamicStoreRemoveValue(store, key);
                goto done;
        }
 
                goto done;
        }
 
@@ -226,19 +230,25 @@ SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef     store,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
 
                                         &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);
 
 
        ok = SCDynamicStoreSetValue(store, key, dict);
 
@@ -264,20 +274,19 @@ SCDynamicStoreSetConsoleUser(SCDynamicStoreRef    store,
        Boolean                 ok              = TRUE;
        Boolean                 tempSession     = FALSE;
 
        Boolean                 ok              = TRUE;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreSetConsoleUser"),
                                             NULL,
                                             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) {
                        return FALSE;
                }
                tempSession = TRUE;
        }
 
        if (user == NULL) {
-               ok = SCDynamicStoreRemoveValue(store, key);
+               (void) SCDynamicStoreRemoveValue(store, key);
                goto done;
        }
 
                goto done;
        }
 
index 1d566af5dd3c465b054a17e824779fad7850cc9d..dcc82a1e9da990171249418280af25031cd777ab 100644 (file)
@@ -59,13 +59,7 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store,
        CFDictionaryRef                 expDict         = NULL; /* dict (un-serialized / expanded) */
        int                             sc_status;
 
        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;
                /* 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) {
        if (xmlPatterns)        CFRelease(xmlPatterns);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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);
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDictRef, xmlDictLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
                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 */
                }
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
                _SCErrorSet(sc_status);
                return NULL;
        }
@@ -135,8 +133,6 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef        store,
        expDict = _SCUnserializeMultiple(dict);
        CFRelease(dict);
 
        expDict = _SCUnserializeMultiple(dict);
        CFRelease(dict);
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value    = %@"), expDict);
-
        return expDict;
 }
 
        return expDict;
 }
 
@@ -155,12 +151,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
        int                             newInstance;
        int                             sc_status;
 
        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;
                /* 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) {
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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);
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
                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 */
                }
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
                _SCErrorSet(sc_status);
                return NULL;
        }
@@ -214,7 +209,5 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
                return NULL;
        }
 
                return NULL;
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value    = %@"), data);
-
        return data;
 }
        return data;
 }
index 7bd5fe1894612395daa9e2de5c04096859d3b91b..5d6fc59e70407eb2c2fc783a5f4fa9e2395f2128 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -49,18 +49,17 @@ CFStringRef
 SCDynamicStoreCopyComputerName(SCDynamicStoreRef       store,
                               CFStringEncoding         *nameEncoding)
 {
 SCDynamicStoreCopyComputerName(SCDynamicStoreRef       store,
                               CFStringEncoding         *nameEncoding)
 {
-       CFDictionaryRef         dict            = NULL;
+       CFDictionaryRef         dict;
        CFStringRef             key;
        CFStringRef             name            = NULL;
        Boolean                 tempSession     = FALSE;
 
        CFStringRef             key;
        CFStringRef             name            = NULL;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyComputerName"),
                                             NULL,
                                             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;
                        return NULL;
                }
                tempSession = TRUE;
@@ -69,7 +68,7 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef      store,
        key  = SCDynamicStoreKeyCreateComputerName(NULL);
        dict = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
        key  = SCDynamicStoreKeyCreateComputerName(NULL);
        dict = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
-       if (!dict) {
+       if (dict == NULL) {
                goto done;
        }
        if (!isA_CFDictionary(dict)) {
                goto done;
        }
        if (!isA_CFDictionary(dict)) {
@@ -78,13 +77,13 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef    store,
        }
 
        name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
        }
 
        name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
-       if (!name) {
+       if (name == NULL) {
                _SCErrorSet(kSCStatusNoKey);
                goto done;
        }
        CFRetain(name);
 
                _SCErrorSet(kSCStatusNoKey);
                goto done;
        }
        CFRetain(name);
 
-       if (nameEncoding) {
+       if (nameEncoding != NULL) {
                CFNumberRef     num;
 
                num = CFDictionaryGetValue(dict,
                CFNumberRef     num;
 
                num = CFDictionaryGetValue(dict,
@@ -99,21 +98,21 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef    store,
     done :
 
        if (tempSession)        CFRelease(store);
     done :
 
        if (tempSession)        CFRelease(store);
-       if (dict)               CFRelease(dict);
+       if (dict != NULL)       CFRelease(dict);
        return name;
 }
 
 
 Boolean
        return name;
 }
 
 
 Boolean
-SCPreferencesSetComputerName(SCPreferencesRef  session,
+SCPreferencesSetComputerName(SCPreferencesRef  prefs,
                             CFStringRef        name,
                             CFStringEncoding   encoding)
 {
        CFDictionaryRef         dict;
                             CFStringRef        name,
                             CFStringEncoding   encoding)
 {
        CFDictionaryRef         dict;
-       CFMutableDictionaryRef  newDict = NULL;
+       CFMutableDictionaryRef  newDict;
        CFNumberRef             num;
        CFNumberRef             num;
-       Boolean                 ok      = FALSE;
-       CFStringRef             path    = NULL;
+       Boolean                 ok;
+       CFStringRef             path;
 
        if (!isA_CFString(name)) {
                _SCErrorSet(kSCStatusInvalidArgument);
 
        if (!isA_CFString(name)) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -126,8 +125,8 @@ SCPreferencesSetComputerName(SCPreferencesRef       session,
                                        kSCPrefSystem,
                                        kSCCompSystem);
 
                                        kSCPrefSystem,
                                        kSCCompSystem);
 
-       dict = SCPreferencesPathGetValue(session, path);
-       if (dict) {
+       dict = SCPreferencesPathGetValue(prefs, path);
+       if (dict != NULL) {
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        } else {
                newDict = CFDictionaryCreateMutable(NULL,
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        } else {
                newDict = CFDictionaryCreateMutable(NULL,
@@ -142,13 +141,103 @@ SCPreferencesSetComputerName(SCPreferencesRef    session,
        CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
        CFRelease(num);
 
        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;
 }
 
        return ok;
 }
@@ -168,18 +257,17 @@ SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator)
 CFStringRef
 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
 {
 CFStringRef
 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
 {
-       CFDictionaryRef         dict            = NULL;
+       CFDictionaryRef         dict;
        CFStringRef             key;
        CFStringRef             name            = NULL;
        Boolean                 tempSession     = FALSE;
 
        CFStringRef             key;
        CFStringRef             name            = NULL;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyLocalHostName"),
                                             NULL,
                                             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;
                        return NULL;
                }
                tempSession = TRUE;
@@ -188,7 +276,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
        key  = SCDynamicStoreKeyCreateHostNames(NULL);
        dict = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
        key  = SCDynamicStoreKeyCreateHostNames(NULL);
        dict = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
-       if (!dict) {
+       if (dict == NULL) {
                goto done;
        }
        if (!isA_CFDictionary(dict)) {
                goto done;
        }
        if (!isA_CFDictionary(dict)) {
@@ -197,7 +285,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
        }
 
        name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
        }
 
        name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
-       if (!name) {
+       if (name == NULL) {
                _SCErrorSet(kSCStatusNoKey);
                goto done;
        }
                _SCErrorSet(kSCStatusNoKey);
                goto done;
        }
@@ -206,7 +294,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
     done :
 
        if (tempSession)        CFRelease(store);
     done :
 
        if (tempSession)        CFRelease(store);
-       if (dict)               CFRelease(dict);
+       if (dict != NULL)       CFRelease(dict);
        return name;
 }
 
        return name;
 }
 
@@ -275,21 +363,21 @@ _SC_CFStringIsValidDNSName(CFStringRef name)
 
        clean = _SC_stringIsValidDNSName(str);
 
 
        clean = _SC_stringIsValidDNSName(str);
 
-       if (str)        CFAllocatorDeallocate(NULL, str);
+       if (str != NULL)        CFAllocatorDeallocate(NULL, str);
        return clean;
 }
 
 
 Boolean
        return clean;
 }
 
 
 Boolean
-SCPreferencesSetLocalHostName(SCPreferencesRef session,
+SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
                              CFStringRef       name)
 {
        CFDictionaryRef         dict;
                              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)) {
                CFIndex len;
 
                if (!isA_CFString(name)) {
@@ -320,8 +408,8 @@ SCPreferencesSetLocalHostName(SCPreferencesRef      session,
                                        kSCCompNetwork,
                                        kSCCompHostNames);
 
                                        kSCCompNetwork,
                                        kSCCompHostNames);
 
-       dict = SCPreferencesPathGetValue(session, path);
-       if (dict) {
+       dict = SCPreferencesPathGetValue(prefs, path);
+       if (dict != NULL) {
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        } else {
                newDict = CFDictionaryCreateMutable(NULL,
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        } else {
                newDict = CFDictionaryCreateMutable(NULL,
@@ -330,26 +418,20 @@ SCPreferencesSetLocalHostName(SCPreferencesRef    session,
                                                    &kCFTypeDictionaryValueCallBacks);
        }
 
                                                    &kCFTypeDictionaryValueCallBacks);
        }
 
-       if (name) {
+       if (name != NULL) {
                CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
        } else {
                CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
        }
 
        if (CFDictionaryGetCount(newDict) > 0) {
                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 {
        } 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;
 }
 
        return ok;
 }
index 4ab3068433cfe2774efb6b451fe386d1b4e57ff6..406f85989b4b28a21d07f05356c0bc63a208460d 100644 (file)
@@ -52,12 +52,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern)
        int                             sc_status;
        CFArrayRef                      allKeys;
 
        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;
                /* 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) {
        CFRelease(utfPattern);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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);
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
                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 */
                }
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
                _SCErrorSet(sc_status);
                return NULL;
        }
index c478dc83f1a3d015613e5144f3be1df8eccf590c..8279699bf3c3b2b5340b60c0caf1e006e858b35d 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreLock(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
        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;
                /* 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) {
        status = configlock(storePrivate->server, (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 85c2969d4ba682313aaf77333329dcbab2058d8f..04a17df578a25b1ed7467beea17bc1e7c786840d 100644 (file)
@@ -49,13 +49,7 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is
        CFIndex                         myKeyLen;
        int                             sc_status;
 
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 41613e03d6975e113a95ba6ad8ecb8d681d4e76e..b3f139bcb5b73fd467559da68d29dbf3ba4a9d41 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCancel:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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 :
                        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;
                        CFMachPortInvalidate(storePrivate->callbackPort);
                        CFRelease(storePrivate->callbackPort);
                        storePrivate->callbackPort              = NULL;
@@ -96,8 +89,10 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
        storePrivate->notifyStatus = NotifierNotRegistered;
 
        if (status != KERN_SUCCESS) {
        storePrivate->notifyStatus = NotifierNotRegistered;
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 871131275593705c3c130ee1f7730d27b9d7c89e..6684826ce245bc708974085d15f718bd789521ff 100644 (file)
@@ -49,9 +49,7 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store)
        int                             sc_status;
        CFArrayRef                      allKeys;
 
        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;
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -69,8 +67,10 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store)
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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);
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
                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 */
                }
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
                _SCErrorSet(sc_status);
                return NULL;
        }
index f5cac0806bf071542a354f2f7a134cdae3dfd6a2..d64572bf29087fa83c752098e0de62bf0da00274 100644 (file)
@@ -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 */
 
        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"));
                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 */
        } 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"));
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  no callback function, disabling notifier"));
+#endif /* DEBUG */
        } else {
        } 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 {
                if ((*cbFunc)(store, cbArg)) {
                        /*
                         * callback function returned success.
                         */
                        return;
                } else {
+#ifdef DEBUG
                        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  callback returned error, disabling notifier"));
                        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 */
 
        }
 #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);
 
        /* invalidate port */
        CFMachPortInvalidate(storePrivate->callbackPort);
@@ -113,9 +118,7 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef              store,
                                                  , NULL
                                                  };
 
                                                  , NULL
                                                  };
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
                                                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;
        }
 
                CFMachPortInvalidate(storePrivate->callbackPort);
                CFRelease(storePrivate->callbackPort);
                _SCErrorSet(status);
                return FALSE;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
        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,
 
        /* Requesting notification via mach port */
        status = notifyviaport(storePrivate->server,
@@ -167,8 +172,10 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef             store,
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                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->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;
 }
 
        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 */
 
        if (msgid == MACH_NOTIFY_NO_SENDERS) {
                /* the server died, disable additional callbacks */
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_INFO, CFSTR("  rlsCallback(), notifier port closed"));
                SCLog(_sc_verbose, LOG_INFO, CFSTR("  rlsCallback(), notifier port closed"));
+#endif /* DEBUG */
 
 #ifdef DEBUG
                if (port != storePrivate->callbackPort) {
 
 #ifdef DEBUG
                if (port != storePrivate->callbackPort) {
@@ -218,10 +222,10 @@ rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
                }
 #endif /* DEBUG */
 
                }
 #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);
 
                /* 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
        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);
        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);
 }
 
        (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;
 
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)info;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
+#ifdef DEBUG
        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("schedule notifications for mode %@"), mode);
        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("schedule notifications for mode %@"), mode);
+#endif /* DEBUG */
 
        if (storePrivate->rlsRefs++ == 0) {
                CFMachPortContext       context = { 0
 
        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;
 
                int                     sc_status;
                kern_return_t           status;
 
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  activate callback runloop source"));
                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) {
 
                /* 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;
                }
                        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) {
 
                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;
                }
                        (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) {
                                                        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;
                }
 
                        (void) mach_port_destroy(mach_task_self(), port);
                        return;
                }
 
+#ifdef DEBUG
                if (oldNotify != MACH_PORT_NULL) {
                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) {
 
                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));
                        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);
                        (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->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;
        }
 
        return;
@@ -335,36 +348,43 @@ rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode)
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)info;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)info;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
+#ifdef DEBUG
        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("cancel notifications for mode %@"), mode);
        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;
 
        }
 
        if (--storePrivate->rlsRefs == 0) {
                int             sc_status;
                kern_return_t   status;
 
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  cancel callback runloop source"));
                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;
                }
 
                        /* 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) {
                        status = notifycancel(storePrivate->server, (int *)&sc_status);
                        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                                if (status != MACH_SEND_INVALID_DEST)
                                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;
                                (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;
 
        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);
 
        changedKeys = SCDynamicStoreCopyNotifiedKeys(store);
-       if (!changedKeys) {
-               /* something happened to the server */
+       if (changedKeys == NULL) {
+               /* if no changes or something happened to the server */
                return;
        }
 
                return;
        }
 
+       if (CFArrayGetCount(changedKeys) == 0) {
+               goto done;
+       }
+
        rlsFunction = storePrivate->rlsFunction;
 
        if (NULL != storePrivate->rlsContext.retain) {
        rlsFunction = storePrivate->rlsFunction;
 
        if (NULL != storePrivate->rlsContext.retain) {
@@ -407,6 +433,8 @@ rlsPerform(void *info)
                context_release(context_info);
        }
 
                context_release(context_info);
        }
 
+    done :
+
        CFRelease(changedKeys);
        return;
 }
        CFRelease(changedKeys);
        return;
 }
@@ -453,9 +481,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef    allocator,
 {
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
 {
        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;
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -478,7 +504,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef    allocator,
                        return NULL;
        }
 
                        return NULL;
        }
 
-       if (storePrivate->rls) {
+       if (storePrivate->rls != NULL) {
                CFRetain(storePrivate->rls);
        } else {
                CFRunLoopSourceContext  context = { 0                   // version
                CFRetain(storePrivate->rls);
        } else {
                CFRunLoopSourceContext  context = { 0                   // version
@@ -496,7 +522,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef    allocator,
                storePrivate->rls = CFRunLoopSourceCreate(allocator, order, &context);
        }
 
                storePrivate->rls = CFRunLoopSourceCreate(allocator, order, &context);
        }
 
-       if (!storePrivate->rls) {
+       if (storePrivate->rls == NULL) {
                _SCErrorSet(kSCStatusFailed);
                return NULL;
        }
                _SCErrorSet(kSCStatusFailed);
                return NULL;
        }
index 7aec2213dded341904239272bc491135d13fc626..6e3521e290c1b79a343802c493b92a05a38756f7 100644 (file)
@@ -56,9 +56,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef  store,
        struct sockaddr_un              un;
        int                             sock;
 
        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;
                /* 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);
 
        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;
        }
 
                return FALSE;
        }
 
@@ -94,14 +92,14 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef        store,
 
        if (bind(sock, (struct sockaddr *)&un, sizeof(un)) == -1) {
                _SCErrorSet(errno);
 
        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);
                (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;
        }
                (void) close(sock);
                return FALSE;
        }
@@ -113,8 +111,10 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef       store,
                             (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
                             (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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);
        *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;
        }
                (void) close(sock);
                return FALSE;
        }
index bef3896cbead994547f82c98b2cfcc02f7345b20..10b4aa0af0c5bc16c1858b6d4524894a908ee2a1 100644 (file)
@@ -47,9 +47,7 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier,
        mach_port_t                     oldNotify;
        int                             sc_status;
 
        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;
                /* 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) {
        /* 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;
        }
                _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) {
 
        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);
                (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) {
                                                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;
        }
 
                (void) mach_port_destroy(mach_task_self(), *port);
                *port = MACH_PORT_NULL;
                _SCErrorSet(status);
                return FALSE;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
        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,
 
        status = notifyviaport(storePrivate->server,
                               *port,
@@ -114,8 +113,10 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier,
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), *port);
                *port = MACH_PORT_NULL;
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
index 4356c6e87627bd6d42aa2d76e37dd64b8234ae9b..96464a13a69ae2b46b8d830394ad413fd946325e 100644 (file)
@@ -47,11 +47,7 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig)
        int                             sc_status;
        task_t                          task;
 
        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;
                /* 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) {
 
        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;
        }
                _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) {
        status = notifyviasignal(storePrivate->server, task, sig, (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 06f81b9ee059526f14cd6f8e92aae04f96340171..5278a57da987c14a3c33623b62aa724aca57dc38 100644 (file)
@@ -49,13 +49,7 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean
        CFIndex                         myKeyLen;
        int                             sc_status;
 
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index c9eb908ad009b2415486b6036ce691f9e23a754c..ad5626d48031d5557f84dbbccb0960af4c659e35 100644 (file)
@@ -52,13 +52,7 @@ SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef  store,
        CFIndex                         myPatternsLen   = 0;
        int                             sc_status;
 
        CFIndex                         myPatternsLen   = 0;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keys     = %@"), keys);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  patterns = %@"), patterns);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        if (xmlPatterns)        CFRelease(xmlPatterns);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 2417fd293d585f26d853d6aca8789e0a9515901c..7597e93e265a7c8e34e68918146ccc77c21aac26 100644 (file)
@@ -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) {
 
        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;
        }
 
                return -1;
        }
 
@@ -61,7 +61,7 @@ waitForMachMessage(mach_port_t port)
                          MACH_MSG_TIMEOUT_NONE,        /* timeout */
                          MACH_PORT_NULL);              /* notify */
        if (status != KERN_SUCCESS) {
                          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;
        }
 
                return -1;
        }
 
@@ -79,9 +79,7 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store)
        int                             sc_status;
        mach_msg_id_t                   msgid;
 
        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;
                /* 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) {
        /* 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;
        }
                _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) {
 
        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;
                (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) {
                                                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;
        }
 
                (void) mach_port_destroy(mach_task_self(), port);
                _SCErrorSet(status);
                return FALSE;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
        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) {
        status = notifyviaport(storePrivate->server,
                               port,
                               0,
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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;
 
        /* set notifier active */
        storePrivate->notifyStatus = Using_NotifierWait;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Waiting..."));
-
        msgid = waitForMachMessage(port);
 
        /* set notifier inactive */
        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 */
 
        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 */
                _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;
        }
 
                (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) {
        status = notifycancel(storePrivate->server,
                              (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 409523b13204829074cf9c864f1cd7a87a5ad718..c06615b8e425789f017c1676537dc024800241d9 100644 (file)
@@ -47,12 +47,7 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef  store,
        CFIndex                         myKeyLen;
        int                             sc_status;
 
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -80,8 +75,10 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef  store,
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 1ce5cfb5cd2f3993922d8cfdb99a4f1538fd3a2a..77352f520aed4688e9a4616b97783d6d41ab97bd 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -32,6 +32,8 @@
  */
 
 #include <stdlib.h>
  */
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include <mach/mach.h>
 #include <mach/mach_error.h>
 #include <servers/bootstrap.h>
 #include <mach/mach.h>
 #include <mach/mach_error.h>
 #include <servers/bootstrap.h>
 #include "SCDynamicStoreInternal.h"
 #include "config.h"            /* MiG generated file */
 
 #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) {
 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);
 
        result = CFStringCreateMutable(allocator, 0);
-       CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf, allocator);
-       CFStringAppendFormat(result, NULL, CFSTR("}"));
+       CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> { "), cf, allocator);
+       if (storePrivate->server != MACH_PORT_NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR("server port=%d"), storePrivate->server);
+       } else {
+               CFStringAppendFormat(result, NULL, CFSTR("server not (no longer) available"));
+       }
+       if (storePrivate->locked) {
+               CFStringAppendFormat(result, NULL, CFSTR(", locked"));
+       }
+       switch (storePrivate->notifyStatus) {
+               case Using_NotifierWait :
+                       CFStringAppendFormat(result, NULL, CFSTR(", waiting for a notification"));
+                       break;
+               case Using_NotifierInformViaMachPort :
+                       CFStringAppendFormat(result, NULL, CFSTR(", mach port notifications"));
+                       break;
+               case Using_NotifierInformViaFD :
+                       CFStringAppendFormat(result, NULL, CFSTR(", FD notifications"));
+                       break;
+               case Using_NotifierInformViaSignal :
+                       CFStringAppendFormat(result, NULL, CFSTR(", BSD signal notifications"));
+                       break;
+               case Using_NotifierInformViaRunLoop :
+               case Using_NotifierInformViaCallback :
+                       if (storePrivate->notifyStatus == Using_NotifierInformViaRunLoop) {
+                               CFStringAppendFormat(result, NULL, CFSTR(", runloop notifications"));
+                               CFStringAppendFormat(result, NULL, CFSTR(" (func=0x%8.8x"), storePrivate->rlsFunction);
+                               CFStringAppendFormat(result, NULL, CFSTR(", info=0x%8.8x"), storePrivate->rlsContext.info);
+                               CFStringAppendFormat(result, NULL, CFSTR(", rls=0x%8.8x" ), storePrivate->rls);
+                               CFStringAppendFormat(result, NULL, CFSTR(", refs=%d"     ), storePrivate->rlsRefs);
+                       } else {
+                               CFStringAppendFormat(result, NULL, CFSTR(", mach port/callback notifications"));
+                               CFStringAppendFormat(result, NULL, CFSTR(" (func=0x%8.8x"), storePrivate->callbackFunction);
+                               CFStringAppendFormat(result, NULL, CFSTR(", info=0x%8.8x"), storePrivate->callbackArgument);
+                       }
+                       if (storePrivate->callbackRLS != NULL) {
+                               CFStringAppendFormat(result, NULL, CFSTR(", notify rls=%@" ), storePrivate->callbackRLS);
+                       }
+                       CFStringAppendFormat(result, NULL, CFSTR(")"));
+                       break;
+               default :
+                       CFStringAppendFormat(result, NULL, CFSTR(", notification delivery not requested%s"),
+                                            storePrivate->rlsFunction ? " (yet)" : "");
+                       break;
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
 
        return result;
 }
 
        return result;
 }
@@ -63,23 +117,23 @@ __SCDynamicStoreDeallocate(CFTypeRef cf)
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)cf;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
        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);
 
        (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);
                (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)
                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;
 
                (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 */
        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);
 
        }
 
        /* 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;
 }
 
        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) {
 static pthread_once_t initialized      = PTHREAD_ONCE_INIT;
 
 static void
 __SCDynamicStoreInitialize(void) {
+       CFBundleRef     bundle;
+
+       /* register with CoreFoundation */
        __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass);
        __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;
 }
 
        return;
 }
 
@@ -132,6 +239,7 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef                allocator,
                             SCDynamicStoreCallBack     callout,
                             SCDynamicStoreContext      *context)
 {
                             SCDynamicStoreCallBack     callout,
                             SCDynamicStoreContext      *context)
 {
+       int                             sc_status       = kSCStatusOK;
        uint32_t                        size;
        SCDynamicStorePrivateRef        storePrivate;
 
        uint32_t                        size;
        SCDynamicStorePrivateRef        storePrivate;
 
@@ -144,15 +252,17 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef              allocator,
                                                                          __kSCDynamicStoreTypeID,
                                                                          size,
                                                                          NULL);
                                                                          __kSCDynamicStoreTypeID,
                                                                          size,
                                                                          NULL);
-       if (!storePrivate) {
+       if (storePrivate == NULL) {
+               _SCErrorSet(kSCStatusFailed);
                return NULL;
        }
 
        /* server side of the "configd" session */
                return NULL;
        }
 
        /* server side of the "configd" session */
-       storePrivate->server = MACH_PORT_NULL;
+       storePrivate->server                            = MACH_PORT_NULL;
 
        /* flags */
 
        /* flags */
-       storePrivate->locked = FALSE;
+       storePrivate->locked                            = FALSE;
+       storePrivate->useSessionKeys                    = FALSE;
 
        /* Notification status */
        storePrivate->notifyStatus                      = NotifierNotRegistered;
 
        /* Notification status */
        storePrivate->notifyStatus                      = NotifierNotRegistered;
@@ -167,8 +277,8 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef                allocator,
        storePrivate->rlsContext.copyDescription        = NULL;
        if (context) {
                bcopy(context, &storePrivate->rlsContext, sizeof(SCDynamicStoreContext));
        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->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);
 
        /* "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;
 
        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;
 }
 
 
        return storePrivate;
 }
 
 
+const CFStringRef      kSCDynamicStoreUseSessionKeys   = CFSTR("UseSessionKeys");      /* CFBoolean */
+
+
 SCDynamicStoreRef
 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;
 {
        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;
        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);
 
        /*
         * 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;
        }
 
                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;
 
                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;
                name = fullName;
-               CFRelease(bundleID);
        } else {
                CFRetain(name);
        }
 
        if (!_SCSerializeString(name, &utfName, (void **)&myNameRef, &myNameLen)) {
                CFRelease(name);
        } else {
                CFRetain(name);
        }
 
        if (!_SCSerializeString(name, &utfName, (void **)&myNameRef, &myNameLen)) {
                CFRelease(name);
-               _SCErrorSet(kSCStatusFailed);
-               return NULL;
+               goto done;
        }
        CFRelease(name);
 
        }
        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 */
        /* 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);
 
        /* clean up */
        CFRelease(utfName);
+       if (xmlOptions) CFRelease(xmlOptions);
 
        if (status != KERN_SUCCESS) {
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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) {
        if (sc_status != kSCStatusOK) {
-               CFRelease(storePrivate);
                _SCErrorSet(sc_status);
                _SCErrorSet(sc_status);
-               return NULL;
+               CFRelease(storePrivate);
+               storePrivate = NULL;
        }
 
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  server port = %d"), storePrivate->server);
        return (SCDynamicStoreRef)storePrivate;
 }
 
 
        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 */
 CFTypeID
 SCDynamicStoreGetTypeID(void) {
        pthread_once(&initialized, __SCDynamicStoreInitialize); /* initialize runtime */
index a92f51d40dbc57d819511142b3a8f0766a384ddb..c14e62d42201a2483c746c48b37d02e3b68ad92f 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -135,6 +135,9 @@ reaper(int sigraised)
                          MACH_PORT_NULL,               /* rcv_name */
                          0,                            /* timeout */
                          MACH_PORT_NULL);              /* notify */
                          MACH_PORT_NULL,               /* rcv_name */
                          0,                            /* timeout */
                          MACH_PORT_NULL);              /* notify */
+       if (status == MACH_SEND_TIMED_OUT) {
+               mach_msg_destroy(&msg.header);
+       }
 
        return;
 }
 
        return;
 }
@@ -298,19 +301,9 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack       callout,
 
                case 0 : {      /* if child */
 
 
                case 0 : {      /* if child */
 
-                       uid_t   curUID  = geteuid();
-                       gid_t   curGID  = getegid();
                        int     i;
                        int     status;
 
                        int     i;
                        int     status;
 
-                       if (curUID != uid) {
-                               (void) setuid(uid);
-                       }
-
-                       if (curGID != gid) {
-                               (void) setgid(gid);
-                       }
-
                        if (setup) {
                                (setup)(pid, setupContext);
                        } else {
                        if (setup) {
                                (setup)(pid, setupContext);
                        } else {
@@ -321,6 +314,14 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack       callout,
                                dup(0);
                        }
 
                                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));
                        /* 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));
index 24955c460095012b18f852d6d0474ce59d540257..9aa8f1dfaf781c118871e1c4faf1a415dcc78693 100644 (file)
 
 
 /*
 
 
 /*
-       @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.
                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,
                been enabled for this bundle.
  */
 typedef void   (*SCDynamicStoreBundleLoadFunction)     (CFBundleRef    bundle,
@@ -86,6 +92,19 @@ typedef void (*SCDynamicStoreBundleStartFunction)    (const char     *bundleName,
 typedef void   (*SCDynamicStoreBundlePrimeFunction)    ();
 
 
 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
 /*!
        @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().
  */
        @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().
  */
        @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
 
 
 __BEGIN_DECLS
index 4248bd6bd22ed49d9a861db2b58bfc12e8f07736..ed1e0cb0dcc2b74b657c0f08b67c083366f3fd65 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
 #include <mach/mach.h>
 #include <mach/notify.h>
 #include <mach/mach_error.h>
 #include <mach/mach.h>
 #include <mach/notify.h>
 #include <mach/mach_error.h>
@@ -59,7 +66,13 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi
                               0,
                               &len);
 
                               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) {
                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,
        (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;
 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;
        }
 
 
        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) {
        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;
                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) {
                *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;
                        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) {
 
                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 {
                        /* non-fatal???, proceed */
                }
        } else {
@@ -165,10 +222,7 @@ _SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dat
 
        if (*obj == NULL) {
                if (xmlError) {
 
        if (*obj == NULL) {
                if (xmlError) {
-                       SCLog(TRUE,
-                             LOG_ERR,
-                             CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
-                             xmlError);
+                       SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserialize(): %@"), xmlError);
                        CFRelease(xmlError);
                }
                _SCErrorSet(kSCStatusFailed);
                        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) {
 
        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;
                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) {
                *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;
                        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) {
 
                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 {
                        /* non-fatal???, proceed */
                }
        } else {
@@ -255,7 +306,7 @@ _SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex da
        }
 
        if (*str == NULL) {
        }
 
        if (*str == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateFromExternalRepresentation() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserializeString() failed"));
                return FALSE;
        }
 
                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) {
        *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;
                *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) {
        *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;
        }
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
@@ -391,7 +439,7 @@ _SCUnserializeMultiple(CFDictionaryRef dict)
 
                CFDictionaryGetKeysAndValues(dict, keys, values);
                for (i = 0; i < nElements; i++) {
 
                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;
                        }
                }
                                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()
 {
 void
 __showMachPortStatus()
 {
index b523f567de491853c3df9ab7d964fd028fe6a988..d3a997c2df249b587cd7ed63d016b2a3c4890265 100644 (file)
@@ -49,12 +49,7 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
        CFIndex                         myKeyLen;
        int                             sc_status;
 
        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;
                /* 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) {
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index aba8569882fcfa2c0cf7984228de7d69d95c0d8f..5b26a4c9b80b972faa2f8aa0760346b3e04197ce 100644 (file)
@@ -59,22 +59,15 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store,
        CFIndex                         myNotifyLen     = 0;
        int                             sc_status;
 
        CFIndex                         myNotifyLen     = 0;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToSet    = %@"), keysToSet);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToRemove = %@"), keysToRemove);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToNotify = %@"), keysToNotify);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
-               return NULL;
+               return FALSE;
        }
 
        if (storePrivate->server == MACH_PORT_NULL) {
                _SCErrorSet(kSCStatusNoStoreServer);
        }
 
        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*/
        }
 
        /* serialize the key/value pairs to set*/
@@ -85,7 +78,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef   store,
                newInfo = _SCSerializeMultiple(keysToSet);
                if (!newInfo) {
                        _SCErrorSet(kSCStatusFailed);
                newInfo = _SCSerializeMultiple(keysToSet);
                if (!newInfo) {
                        _SCErrorSet(kSCStatusFailed);
-                       return NULL;
+                       return FALSE;
                }
 
                ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen);
                }
 
                ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen);
@@ -93,7 +86,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef   store,
 
                if (!ok) {
                        _SCErrorSet(kSCStatusFailed);
 
                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);
                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);
                        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) {
        if (xmlNotify)  CFRelease(xmlNotify);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (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;
 
        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;
                /* 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) {
        CFRelease(xmlData);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 13e069d14ed4852167576507e93ab63ee6ce13a2..5f69bb748e668fcbc21bdf36b54aeeeb8e2fbd1e 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSnapshot:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        status = snapshot(storePrivate->server, (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 4450e9ed361ec9d02cc48b5148bc860daf7ab2f6..8b71a7bea0aa7c6daf9b2d47ecca3b28bad2273f 100644 (file)
@@ -49,12 +49,7 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
        CFIndex                         myKeyLen;
        int                             sc_status;
 
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index c847c3fe1abc86aedcf8040602eb611768ad962a..d90117128a0bff315eb7092aa560ac5ffd215c02 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreUnlock(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreUnlock:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
                /* 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) {
        /* (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)
                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);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index ea0d504e7f4839965c9c8a73d30be8877939db7a..babb95c4c92be425e3f8c74b0a58b9642f1b2672 100644 (file)
 #define _SCDYNAMICSTORE_H
 
 #include <sys/cdefs.h>
 #define _SCDYNAMICSTORE_H
 
 #include <sys/cdefs.h>
-#include <sys/syslog.h>
-#include <mach/message.h>
 #include <CoreFoundation/CoreFoundation.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 
-
 /*!
        @header SCDynamicStore
 /*!
        @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
  */
 
 
 /*!
        @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
                with the system configuration daemon.
  */
 typedef const struct __SCDynamicStore *        SCDynamicStoreRef;
 
 /*!
        @typedef SCDynamicStoreContext
+       Structure containing user-specified data and callbacks for an
+       SCDynamicStore session.
+       @field version The version number of the structure type being passed
+               in as a parameter to the SCDynamicStore creation function.
+               This structure is version 0.
+       @field info A C pointer to a user-specified block of data.
+       @field retain The callback used to add a retain for the info field.
+               If this parameter is not a pointer to a function of the correct
+               prototype, the behavior is undefined.  The value may be NULL.
+       @field release The calllback used to remove a retain previously added
+               for the info field.  If this parameter is not a pointer to a
+               function of the correct prototype, the behavior is undefined.
+               The value may be NULL.
+       @field copyDescription The callback used to provide a description of
+               the info field.
  */
 typedef struct {
        CFIndex         version;
  */
 typedef struct {
        CFIndex         version;
@@ -67,11 +82,11 @@ typedef struct {
 
 /*!
        @typedef SCDynamicStoreCallBack
 
 /*!
        @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 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,
  */
 typedef void (*SCDynamicStoreCallBack) (
                                        SCDynamicStoreRef       store,
@@ -84,7 +99,7 @@ __BEGIN_DECLS
 
 /*!
        @function SCDynamicStoreGetTypeID
 
 /*!
        @function SCDynamicStoreGetTypeID
-       Returns the type identifier of all SCDynamicStore instances.
+       @discussion Returns the type identifier of all SCDynamicStore instances.
  */
 CFTypeID
 SCDynamicStoreGetTypeID                        (void);
  */
 CFTypeID
 SCDynamicStoreGetTypeID                        (void);
@@ -93,21 +108,21 @@ SCDynamicStoreGetTypeID                    (void);
 /*!
        @function SCDynamicStoreCreate
        @discussion Creates a new session used to interact with the dynamic
 /*!
        @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
                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.
                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                   (
  */
 SCDynamicStoreRef
 SCDynamicStoreCreate                   (
@@ -118,23 +133,71 @@ SCDynamicStoreCreate                      (
                                        );
 
 /*!
                                        );
 
 /*!
-       @function SCDynamicStoreCreateRunLoopSource
+       @function SCDynamicStoreCreateWithOptions
        @discussion Creates a new session used to interact with the dynamic
        @discussion Creates a new session used to interact with the dynamic
-               store maintained by the SystemConfiguration server.
-       @param allocator The CFAllocator which should be used to allocate
-               memory for the local "dynamic store" and its storage for
-               values.
+               store maintained by the System Configuration server.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for the local dynamic store object.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param name A string that describes the name of the calling
+               process or plug-in of the caller.
+       @param storeOptions A CFDictionary containing options for the
+               dynamic store session (such as whether all keys added or set
+               into the dynamic store should be per-session keys).
+
+               Currently available options include:
+
+               <TABLE BORDER>
+               <TR>
+                       <TH>key</TD>
+                       <TH>value</TD>
+               </TR>
+               <TR>
+                       <TD>kSCDynamicStoreUseSessionKeys</TD>
+                       <TD>CFBooleanRef</TD>
+               </TR>
+               </TABLE>
+
+               A NULL value can be specified if no options are desired.
+       @param callout The function to be called when a watched value
+               in the dynamic store is changed.
+               A NULL value can be specified if no callouts are
+               desired.
+       @param context The SCDynamicStoreContext associated with the callout.
+       @result Returns a reference to the new SCDynamicStore session.
+               You must release the returned value.
+ */
+SCDynamicStoreRef
+SCDynamicStoreCreateWithOptions                (
+                                       CFAllocatorRef                  allocator,
+                                       CFStringRef                     name,
+                                       CFDictionaryRef                 storeOptions,
+                                       SCDynamicStoreCallBack          callout,
+                                       SCDynamicStoreContext           *context
+                                       );
+
+extern const CFStringRef       kSCDynamicStoreUseSessionKeys;  /* CFBoolean */
+
+/*!
+       @function SCDynamicStoreCreateRunLoopSource
+       @discussion Creates a CFRunLoopSource object that can be added to the
+               application's run loop.  All dynamic store notifications are
+               delivered using this run loop source.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this run loop source.
                This parameter may be NULL in which case the current
                default CFAllocator is used. If this reference is not
                a valid CFAllocator, the behavior is undefined.
                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.
                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
 /*!
        @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.
                You must release the returned value.
-               A NULL value will be returned if the list could not be obtained.
  */
 CFArrayRef
 SCDynamicStoreCopyKeyList              (
  */
 CFArrayRef
 SCDynamicStoreCopyKeyList              (
@@ -167,13 +229,13 @@ SCDynamicStoreCopyKeyList         (
 
 /*!
        @function SCDynamicStoreAddValue
 
 /*!
        @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.
                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                 (
  */
 Boolean
 SCDynamicStoreAddValue                 (
@@ -184,15 +246,15 @@ SCDynamicStoreAddValue                    (
 
 /*!
        @function SCDynamicStoreAddTemporaryValue
 
 /*!
        @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                (
  */
 Boolean
 SCDynamicStoreAddTemporaryValue                (
@@ -203,15 +265,12 @@ SCDynamicStoreAddTemporaryValue           (
 
 /*!
        @function SCDynamicStoreCopyValue
 
 /*!
        @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.
                You must release the returned value.
-               If no value was located, NULL is returned.
  */
 CFPropertyListRef
 SCDynamicStoreCopyValue                        (
  */
 CFPropertyListRef
 SCDynamicStoreCopyValue                        (
@@ -221,15 +280,15 @@ SCDynamicStoreCopyValue                   (
 
 /*!
        @function SCDynamicStoreCopyMultiple
 
 /*!
        @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.
                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
                You must release the returned value.
  */
 CFDictionaryRef
@@ -241,12 +300,12 @@ SCDynamicStoreCopyMultiple                (
 
 /*!
        @function SCDynamicStoreSetValue
 
 /*!
        @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.
                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                 (
  */
 Boolean
 SCDynamicStoreSetValue                 (
@@ -257,12 +316,12 @@ SCDynamicStoreSetValue                    (
 
 /*!
        @function SCDynamicStoreSetMultiple
 
 /*!
        @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              (
  */
 Boolean
 SCDynamicStoreSetMultiple              (
@@ -275,10 +334,10 @@ SCDynamicStoreSetMultiple         (
 /*!
        @function SCDynamicStoreRemoveValue
        @discussion Removes the value of the specified key from the
 /*!
        @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
                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.
        @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              (
  */
 Boolean
 SCDynamicStoreNotifyValue              (
@@ -304,14 +365,14 @@ SCDynamicStoreNotifyValue         (
 /*!
        @function SCDynamicStoreSetNotificationKeys
        @discussion Specifies a set of specific keys and key patterns
 /*!
        @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.
                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      (
  */
 Boolean
 SCDynamicStoreSetNotificationKeys      (
@@ -323,12 +384,14 @@ SCDynamicStoreSetNotificationKeys (
 /*!
        @function SCDynamicStoreCopyNotifiedKeys
        @discussion Returns an array of CFString keys representing the
 /*!
        @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.
                You must release the returned value.
-               A NULL value will be returned if the list could not be obtained.
  */
 CFArrayRef
 SCDynamicStoreCopyNotifiedKeys         (
  */
 CFArrayRef
 SCDynamicStoreCopyNotifiedKeys         (
index 088b4089a73e60e297b1c2fc17ce4af44d51b1ce..5cab3e1c435f0338f66d9386f9a3d110eeac1fc6 100644 (file)
 
 
 /*!
 
 
 /*!
-       @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
 
 /*!
        @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.
                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.
                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().
                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
 
 /*!
        @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 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.
                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.
  */
 
                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,
 /*!
        @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.
        @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.
  */
 
                The return value must NOT be released.
  */
index e95c460a3da352109ae6559e866fe80f6b6b661c..36f5f63b61ef1600038db255c2a40a41f65d3ba9 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #define _SCDYNAMICSTORECOPYSPECIFIC_H
 
 #include <sys/cdefs.h>
 #define _SCDYNAMICSTORECOPYSPECIFIC_H
 
 #include <sys/cdefs.h>
+#include <sys/types.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 /*!
        @header SCDynamicStoreCopySpecific
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 /*!
        @header SCDynamicStoreCopySpecific
-       The following APIs allow an application to determine specific
-       configuration information about the current system (e.g. the
-       computer/sharing name, the currently logged in user, etc).
+       @discussion The functions of the SCDynamicStoreCopySpecific API
+               allow an application to determine specific configuration
+               information about the current system (for example, the
+               computer or sharing name, the currently logged-in user, etc.).
  */
 
 
  */
 
 
@@ -41,13 +43,14 @@ __BEGIN_DECLS
 
 /*!
        @function SCDynamicStoreCopyComputerName
 
 /*!
        @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
                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.
  */
                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
 /*!
        @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
                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
                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.
                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.
  */
                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.
 /*!
        @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.
                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.
  */
                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
 
 /*!
        @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.
                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.
  */
                was encountered.
                You must release the returned value.
  */
@@ -118,12 +123,81 @@ SCDynamicStoreCopyLocation                (
 /*!
        @function SCDynamicStoreCopyProxies
        @discussion Gets the current internet proxy settings.
 /*!
        @function SCDynamicStoreCopyProxies
        @discussion Gets the current internet proxy settings.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+               The returned proxy settings dictionary includes:
+
+               <TABLE BORDER>
+               <TR>
+                       <TH>key</TD>
+                       <TH>type</TD>
+                       <TH>description</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesExceptionsList</TD>
+                       <TD>CFArray[CFString]</TD>
+                       <TD>Host name patterns which should bypass the proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPEnable</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enables/disables the use of an HTTP proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPProxy</TD>
+                       <TD>CFString</TD>
+                       <TD>The proxy host</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPPort</TD>
+                       <TD>CFNumber</TD>
+                       <TD>The proxy port number</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPSEnable</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enables/disables the use of an HTTPS proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPSProxy</TD>
+                       <TD>CFString</TD>
+                       <TD>The proxy host</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPSPort</TD>
+                       <TD>CFNumber</TD>
+                       <TD>The proxy port number</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPEnable</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enables/disables the use of an FTP proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPProxy</TD>
+                       <TD>CFString</TD>
+                       <TD>The proxy host</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPPort</TD>
+                       <TD>CFNumber</TD>
+                       <TD>The proxy port number</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPPassive</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enable passive mode operation for use behind connection
+                       filter-ing firewalls.</TD>
+               </TR>
+               </TABLE>
+
+               Other key-value pairs are defined in the SCSchemaDefinitions.h
+               header file.
+       @param store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
                If NULL, a temporary session will be used.
                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
                You must release the returned value.
  */
 CFDictionaryRef
index 5746a819ae971147abc9c81e2d9a8bfe29e4c58d..380f2605334f300f9849597bda8f04a2a15d9aad 100644 (file)
@@ -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
  */
 /*
  * 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
 
 /*!
        @function SCDynamicStoreCopyConsoleInformation
index 51f28b239d01f0f9829d3bd58972ce5d0eac5a3c..6017d207d70aa19b01c0e24e5c0e02ecc4b5adc2 100644 (file)
@@ -56,10 +56,7 @@ typedef struct {
 
        /* per-session flags */
        Boolean                         locked;
 
        /* per-session flags */
        Boolean                         locked;
-
-       /* SCDynamicStoreKeys being watched */
-       CFMutableSetRef                 keys;
-       CFMutableSetRef                 patterns;
+       Boolean                         useSessionKeys;
 
        /* current status of notification requests */
        __SCDynamicStoreNotificationStatus      notifyStatus;
 
        /* current status of notification requests */
        __SCDynamicStoreNotificationStatus      notifyStatus;
@@ -74,8 +71,11 @@ typedef struct {
        SCDynamicStoreCallBack_v1       callbackFunction;
        void                            *callbackArgument;
        CFMachPortRef                   callbackPort;
        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;
 
        /* "server" information associated with SCDynamicStoreNotifyMachPort() */
        mach_port_t                     notifyPort;
index 18bde7d783d3228647c3516ffa827de1bf5ec406..b875558eacae42b84152c719154ae7323a6bed06 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 /*!
        @header SCDynamicStoreKey
 
 /*!
        @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
 
 /*
  */
 
 
 __BEGIN_DECLS
 
 /*
- * SCDynamicStoreKeyCreate*
+ * SCDynamicStoreKeyCreate
  * - convenience routines that create a CFString key for an item in the store
  */
 
 /*!
        @function 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                                (
  */
 CFStringRef
 SCDynamicStoreKeyCreate                                (
@@ -53,6 +65,21 @@ SCDynamicStoreKeyCreate                              (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkGlobalEntity
 
 /*!
        @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     (
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkGlobalEntity     (
@@ -63,6 +90,19 @@ SCDynamicStoreKeyCreateNetworkGlobalEntity   (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkInterface
 
 /*!
        @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                (
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkInterface                (
@@ -72,6 +112,23 @@ SCDynamicStoreKeyCreateNetworkInterface             (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkInterfaceEntity
 
 /*!
        @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  (
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkInterfaceEntity  (
@@ -83,6 +140,24 @@ SCDynamicStoreKeyCreateNetworkInterfaceEntity       (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkServiceEntity
 
 /*!
        @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    (
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkServiceEntity    (
@@ -94,10 +169,16 @@ SCDynamicStoreKeyCreateNetworkServiceEntity        (
 
 /*!
        @function SCDynamicStoreKeyCreateComputerName
 
 /*!
        @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            (
 */
 CFStringRef
 SCDynamicStoreKeyCreateComputerName            (
@@ -106,10 +187,15 @@ SCDynamicStoreKeyCreateComputerName               (
 
 /*!
        @function SCDynamicStoreKeyCreateConsoleUser
 
 /*!
        @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             (
 */
 CFStringRef
 SCDynamicStoreKeyCreateConsoleUser             (
@@ -118,11 +204,16 @@ SCDynamicStoreKeyCreateConsoleUser                (
 
 /*!
        @function SCDynamicStoreKeyCreateHostNames
 
 /*!
        @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
                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               (
 */
 CFStringRef
 SCDynamicStoreKeyCreateHostNames               (
@@ -131,10 +222,16 @@ SCDynamicStoreKeyCreateHostNames          (
 
 /*!
        @function SCDynamicStoreKeyCreateLocation
 
 /*!
        @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                        (
 */
 CFStringRef
 SCDynamicStoreKeyCreateLocation                        (
@@ -143,10 +240,16 @@ SCDynamicStoreKeyCreateLocation                   (
 
 /*!
        @function SCDynamicStoreKeyCreateProxies
 
 /*!
        @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                 (
 */
 CFStringRef
 SCDynamicStoreKeyCreateProxies                 (
index ebf7b284e0d85b83ff7fca4ae51d1e88c07b36e1..7ea34c27ca77581f075942f891d0205a06b84d55 100644 (file)
 #define _SCDYNAMICSTOREPRIVATE_H
 
 #include <sys/cdefs.h>
 #define _SCDYNAMICSTOREPRIVATE_H
 
 #include <sys/cdefs.h>
-#include <sys/types.h>
-#include <regex.h>
+#include <mach/message.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
+/*!
+       @header SCDynamicStorePrivate
+ */
+
 /*!
        @typedef SCDynamicStoreCallBack
        @discussion Type of the callback function used when a
                dynamic store change is delivered.
        @param store The "dynamic store" session.
 /*!
        @typedef SCDynamicStoreCallBack
        @discussion Type of the callback function used when a
                dynamic store change is delivered.
        @param store The "dynamic store" session.
-       @param changedKeys The list of changed keys.
        @param info ....
  */
 typedef boolean_t (*SCDynamicStoreCallBack_v1) (
        @param 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 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
                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
index 76f8c90ae32766711a4e10c061b3e9a0cfb0081f..81e7f87d18cefa47e9b042b62b09ca6c9e5f296c 100644 (file)
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
+/*!
+       @header SCDynamicStoreSetSpecificPrivate
+ */
+
 __BEGIN_DECLS
 
 /*!
 __BEGIN_DECLS
 
 /*!
index 06dd8699af97466f01a34a40a4a6f75cccfaf560..602ab547dfdc406b1363082bed2e8422626f2351 100644 (file)
@@ -47,12 +47,12 @@ SCDynamicStoreCopyLocation(SCDynamicStoreRef store)
        CFStringRef             location        = NULL;
        Boolean                 tempSession     = FALSE;
 
        CFStringRef             location        = NULL;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyLocation"),
                                             NULL,
                                             NULL);
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyLocation"),
                                             NULL,
                                             NULL);
-               if (!store) {
+               if (store == NULL) {
                        SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
                        return NULL;
                }
                        SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
                        return NULL;
                }
index e5f1671604f70c981ba563869c7991e9b0ca12a3..23f6648cc3f1b4615ea237c5c7cc436bc01d2832 100644 (file)
@@ -81,7 +81,7 @@ SCNetworkCheckReachabilityByName(const char                   *nodename,
                                 SCNetworkConnectionFlags       *flags)
 {
        SCNetworkReachabilityRef        networkAddress;
                                 SCNetworkConnectionFlags       *flags)
 {
        SCNetworkReachabilityRef        networkAddress;
-       Boolean         ok;
+       Boolean                         ok;
 
        if (!nodename) {
                _SCErrorSet(kSCStatusInvalidArgument);
 
        if (!nodename) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -98,25 +98,22 @@ Boolean
 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
 {
        CFStringRef             key;
 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) {
 
        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);
        key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                            kSCDynamicStoreDomainState,
                                                            ifName,
                                                            kSCEntNetRefreshConfiguration);
        ret = SCDynamicStoreNotifyValue(store, key);
        CFRelease(key);
-
- done:
-       if (store != NULL) {
-               CFRelease(store);
-       }
+       CFRelease(store);
        return (ret);
 }
        return (ret);
 }
index b9c9ee1019ed9a4c0396e36a10f497e3f8d25e09..8dae0e8f4a564fe9093b547fae102ce375930bcb 100644 (file)
 
 /*!
        @header SCNetwork
 
 /*!
        @header SCNetwork
-
-       SCNetworkCheckReachabilityXXX()
-
-       The SCNetworkCheckReachabilityXXX() APIs allow an application to
-       determine the status of the system's current network configuration
-       and the accessibility of a target host/address.
-
-       The term "reachable" reflects whether a data packet, sent by
-       an application into the network stack, can be sent to the
-       the target host/address.  Please note that their is no
-       guarantee that the data packet will actually be received by
-       the host.
-
-
-       SCNetworkInterfaceRefreshConfiguration()
-
-       This API sends a notification to interested network configuration
-       agents to retry their configuraton immediately. For example, calling
-       this API will cause the DHCP client to contact the DHCP server
-       immediately rather than waiting until its timeout has expired.
-       The utility of this API is to allow the caller to give a hint to
-       the system that the network infrastructure/configuration has changed.
+       @discussion The SCNetwork API contains functions an application can
+               use to determine remote host reachability and notify the
+               system of configuration changes.
+
+               The two SCNetworkCheckReachability functions allow an
+               application to determine the status of the system's current
+               network configuration and the reachability of a target host
+               or address.
+
+               "Reachability" reflects whether a data packet, sent by an
+               application into the network stack, can leave the local
+               computer.  Note that reachability does <i>not</i> guarantee
+               that the data packet will actually be received by the host.
+
+               The SCNetworkInterfaceRefreshConfiguration function sends a
+               notification to interested network configuration agents to
+               retry their configuration immediately. For example, calling
+               this function will cause the DHCP client to contact the DHCP
+               server immediately rather than waiting until its timeout has
+               expired.  The utility of this function is to allow the caller
+               to give a hint to the system that the network infrastructure
+               or configuration has changed.
  */
 
 /*!
        @enum SCNetworkConnectionFlags
        @discussion Flags that indicate whether the specified network
  */
 
 /*!
        @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
        @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
        @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.
                be reached using the current network configuration.
-
        @constant kSCNetworkFlagsConnectionRequired
        @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 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.
                network traffic for the target system.
-
        @constant kSCNetworkFlagsConnectionAutomatic
        @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
                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
        @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
                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
        @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.
                is one associated with a network interface on the current
                system.
-
        @constant kSCNetworkFlagsIsDirect
                This flag indicates that network traffic to the specified
        @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,
  */
 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.
        @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    (
  */
 Boolean
 SCNetworkCheckReachabilityByAddress    (
@@ -139,35 +140,39 @@ SCNetworkCheckReachabilityByAddress       (
 
 /*!
        @function SCNetworkCheckReachabilityByName
 
 /*!
        @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
                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.
        @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
                                        );
  */
 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.
 /*!
        @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
                                        );
  */
 Boolean
 SCNetworkInterfaceRefreshConfiguration (
                                        CFStringRef ifName
                                        );
+
 __END_DECLS
 
 #endif /* _SCNETWORK_H */
 __END_DECLS
 
 #endif /* _SCNETWORK_H */
diff --git a/SystemConfiguration.fproj/SCNetworkConfiguration.h b/SystemConfiguration.fproj/SCNetworkConfiguration.h
new file mode 100644 (file)
index 0000000..a9be635
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <AvailabilityMacros.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+
+/*!
+       @header SCNetworkConfiguration
+       @discussion The SCNetworkConfiguration API provides access to the
+               stored network configuration.  The functions include
+               providing access to the network capable devices on the
+               system, the network sets, network services, and network
+               protocols.
+
+               Note: When using the SCNetworkConfiguraiton APIs you must
+               keep in mind that in order for any of your changes to be
+               committed to permanent storage a call must be made to the
+               SCPreferencesCommitChanges function.
+ */
+
+/*!
+       @group Interface configuration
+ */
+
+/*!
+       @typedef SCNetworkInterfaceRef
+       @discussion This is the type of a reference to an object that represents
+               a network interface.
+ */
+typedef const struct __SCNetworkInterface * SCNetworkInterfaceRef;
+
+/*!
+       @const kSCNetworkInterfaceType6to4
+ */
+extern const CFStringRef kSCNetworkInterfaceType6to4                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeBluetooth
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeBluetooth                                      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeBond
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeBond                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeEthernet
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeEthernet                                       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeFireWire
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeFireWire                                       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeIEEE80211
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeIEEE80211                                      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      // IEEE 802.11, AirPort
+
+/*!
+       @const kSCNetworkInterfaceTypeIrDA
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeIrDA                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeL2TP
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeL2TP                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeModem
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeModem                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypePPP
+ */
+extern const CFStringRef kSCNetworkInterfaceTypePPP                                            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypePPTP
+ */
+extern const CFStringRef kSCNetworkInterfaceTypePPTP                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeSerial
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeSerial                                         AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceTypeVLAN
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeVLAN                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* special network interfaces (and types) */
+
+/*!
+       @const kSCNetworkInterfaceTypeIPv4
+ */
+extern const CFStringRef kSCNetworkInterfaceTypeIPv4                                           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkInterfaceIPv4
+       @discussion A network interface that can used for layering other
+               interfaces (e.g. 6to4, PPP, PPTP, L2TP) over an existing
+               IPv4 network.
+ */
+extern const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4                                     AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+/*!
+       @group Protocol configuration
+ */
+
+/*!
+       @typedef SCNetworkProtocolRef
+       @discussion This is the type of a reference to an object that represents
+               a network protocol.
+ */
+typedef const struct __SCNetworkProtocol * SCNetworkProtocolRef;
+
+/* network "protocol" types */
+
+/*!
+       @const kSCNetworkProtocolTypeAppleTalk
+ */
+extern const CFStringRef kSCNetworkProtocolTypeAppleTalk                                       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkProtocolTypeDNS
+ */
+extern const CFStringRef kSCNetworkProtocolTypeDNS                                             AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkProtocolTypeIPv4
+ */
+extern const CFStringRef kSCNetworkProtocolTypeIPv4                                            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkProtocolTypeIPv6
+ */
+extern const CFStringRef kSCNetworkProtocolTypeIPv6                                            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @const kSCNetworkProtocolTypeProxies
+ */
+extern const CFStringRef kSCNetworkProtocolTypeProxies                                         AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+
+/*!
+       @group Service configuration
+ */
+
+/*!
+       @typedef SCNetworkServiceRef
+       @discussion This is the type of a reference to an object that represents
+               a network service.
+ */
+typedef const struct __SCNetworkService * SCNetworkServiceRef;
+
+
+/*!
+       @group Set configuration
+ */
+
+/*!
+       @typedef SCNetworkSetRef
+       @discussion This is the type of a reference to an object that represents
+               a network set.
+ */
+typedef const struct __SCNetworkSet    * SCNetworkSetRef;
+
+
+__BEGIN_DECLS
+
+
+/* --------------------------------------------------------------------------------
+ * INTERFACES
+ * -------------------------------------------------------------------------------- */
+
+/*!
+       @group Interface configuration
+ */
+
+/*!
+       @function SCNetworkInterfaceGetTypeID
+       @discussion Returns the type identifier of all SCNetworkInterface instances.
+ */
+CFTypeID
+SCNetworkInterfaceGetTypeID                    (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceCopyAll
+       @discussion Returns all network capable devices on the system.
+       @result The list of SCNetworkInterface devices on the system.
+               You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkInterfaceRef's */
+SCNetworkInterfaceCopyAll                      (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetSupportedInterfaceTypes
+       @discussion Identify all of the network interface types (e.g. PPP) that
+               can be layered on top of this interface.
+       @param interface The network interface.
+       @result The list of SCNetworkInterface types supported by the interface;
+               NULL if no interface types are supported.
+ */
+CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedInterfaceTypes   (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetSupportedProtocolTypes
+       @discussion Identify all of the network protocol types (e.g. IPv4, IPv6) that
+               can be layered on top of this interface.
+       @param interface The network interface.
+       @result The list of SCNetworkProtocol types supported by the interface;
+               NULL if no protocol types are supported.
+ */
+CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedProtocolTypes    (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceCreateWithInterface
+       @discussion Create a new network interface layered on top of another.  For
+               example, this function would be used to create a "PPP" interface
+               on top of a "modem".
+       @param interface The network interface.
+       @param interfaceType The type of SCNetworkInterface to be layered on
+               top of the provided interface.
+       @result A reference to the new SCNetworkInterface.
+               You must release the returned value.
+ */
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithInterface          (SCNetworkInterfaceRef          interface,
+                                                CFStringRef                    interfaceType)  AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetBSDName
+       @discussion Returns the BSD interface (en0) or device name (modem)
+               for the interface.
+       @param interface The network interface.
+       @result The BSD name associated with the interface (e.g. "en0");
+               NULL if no BSD name is available.
+ */
+CFStringRef
+SCNetworkInterfaceGetBSDName                   (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetConfiguration
+       @discussion Returns the configuration settings associated with a interface.
+       @param interface The network interface.
+       @result The configuration settings associated with the interface;
+               NULL if no changes to the default configuration have been saved.
+ */
+CFDictionaryRef
+SCNetworkInterfaceGetConfiguration             (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetHardwareAddressString
+       @discussion Returns a displayable link layer address for the interface.
+       @param interface The network interface.
+       @result A string representing the hardware (MAC) address for the interface.
+ */
+CFStringRef
+SCNetworkInterfaceGetHardwareAddressString     (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetInterface
+       @discussion For layered network interfaces, return the underlying interface.
+       @param interface The network interface.
+       @result The underlying network interface;
+               NULL if this is a leaf interface.
+ */
+SCNetworkInterfaceRef
+SCNetworkInterfaceGetInterface                 (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetInterfaceType
+       @discussion Returns the associated network interface type.
+       @param interface The network interface.
+       @result The interface type.
+ */
+CFStringRef
+SCNetworkInterfaceGetInterfaceType             (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceGetLocalizedDisplayName
+       @discussion Returns the localized name (e.g. "Built-in Ethernet") for
+               the interface.
+       @param interface The network interface.
+       @result A localized, display name for the interface;
+               NULL if no name is available.
+ */
+CFStringRef
+SCNetworkInterfaceGetLocalizedDisplayName      (SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkInterfaceSetConfiguration
+       @discussion Stores the configuration settings for the interface.
+       @param interface The network interface.
+       @param config The configuration settings to associate with this interface.
+       @result TRUE if the configuration was stored; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkInterfaceSetConfiguration             (SCNetworkInterfaceRef          interface,
+                                                CFDictionaryRef                config)         AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* --------------------------------------------------------------------------------
+ * PROTOCOLS
+ * -------------------------------------------------------------------------------- */
+
+/*!
+       @group Protocol configuration
+ */
+
+/*!
+       @function SCNetworkProtocolGetTypeID
+       @discussion Returns the type identifier of all SCNetworkProtocol instances.
+ */
+CFTypeID
+SCNetworkProtocolGetTypeID                     (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkProtocolGetConfiguration
+       @discussion Returns the configuration settings associated with the protocol.
+       @param protocol The network protocol.
+       @result The configuration settings associated with the protocol;
+               NULL if no changes to the default configuration have been saved.
+ */
+CFDictionaryRef
+SCNetworkProtocolGetConfiguration              (SCNetworkProtocolRef           protocol)       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkProtocolGetEnabled
+       @discussion Returns whether this protocol has been enabled.
+       @param protocol The network protocol.
+       @result TRUE if the protocol is enabled.
+ */
+Boolean
+SCNetworkProtocolGetEnabled                    (SCNetworkProtocolRef           protocol)       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkProtocolGetProtocolType
+       @discussion Returns the associated network protocol type.
+       @param protocol The network protocol.
+       @result The protocol type.
+ */
+CFStringRef
+SCNetworkProtocolGetProtocolType               (SCNetworkProtocolRef           protocol)       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkProtocolSetConfiguration
+       @discussion Stores the configuration settings for the protocol.
+       @param protocol The network protocol.
+       @param config The configuration settings to associate with this protocol.
+       @result TRUE if the configuration was stored; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkProtocolSetConfiguration              (SCNetworkProtocolRef           protocol,
+                                                CFDictionaryRef                config)         AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkProtocolSetEnabled
+       @discussion Enables or disables the protocol.
+       @param protocol The network protocol.
+       @param enabled TRUE if the protocol should be enabled.
+       @result TRUE if the enabled status was saved; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkProtocolSetEnabled                    (SCNetworkProtocolRef           protocol,
+                                                Boolean                        enabled)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* --------------------------------------------------------------------------------
+ * SERVICES
+ * -------------------------------------------------------------------------------- */
+
+/*!
+       @group Service configuration
+ */
+
+/*!
+       @function SCNetworkServiceGetTypeID
+       @discussion Returns the type identifier of all SCNetworkService instances.
+ */
+CFTypeID
+SCNetworkServiceGetTypeID                      (void);
+
+/*!
+       @function SCNetworkServiceAddProtocolType
+       @discussion Adds a network protocol of the specified type to the
+               service.  The protocal configuration is set to default values
+               that are appropriate for the interface associated with the
+               service.
+       @param service The network service.
+       @param protocolType The type of SCNetworkProtocol to be added to the service.
+       @result TRUE if the protocol was added to the service; FALSE if the
+               protocol was already present or an error was encountered.
+ */
+Boolean
+SCNetworkServiceAddProtocolType                        (SCNetworkServiceRef            service,
+                                                CFStringRef                    protocolType)   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceCopyAll
+       @discussion Returns all available network services for the specified preferences.
+       @param prefs The "preferences" session.
+       @result The list of SCNetworkService services associated with the preferences.
+               You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkServiceCopyAll                                (SCPreferencesRef               prefs)          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceCopyProtocols
+       @discussion Returns all network protocols associated with the service.
+       @param service The network service.
+       @result The list of SCNetworkProtocol protocols associated with the service.
+               You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkProtocolRef's */
+SCNetworkServiceCopyProtocols                  (SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceCreate
+       @discussion Create a new network service for the specified interface in the
+               configuration.
+       @param prefs The "preferences" session.
+       @result A reference to the new SCNetworkService.
+               You must release the returned value.
+ */
+SCNetworkServiceRef
+SCNetworkServiceCreate                         (SCPreferencesRef               prefs,
+                                                SCNetworkInterfaceRef          interface)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceCopy
+       @discussion Returns the network service with the specified identifier.
+       @param prefs The "preferences" session.
+       @param serviceID The unique identifier for the service.
+       @result A reference to the SCNetworkService from the associated preferences;
+               NULL if the serviceID does not exist in the preferences or if an
+               error was encountered.
+               You must release the returned value.
+ */
+SCNetworkServiceRef
+SCNetworkServiceCopy                           (SCPreferencesRef               prefs,
+                                                CFStringRef                    serviceID)      AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceGetEnabled
+       @discussion Returns whether this service has been enabled.
+       @param service The network service.
+       @result TRUE if the service is enabled.
+ */
+Boolean
+SCNetworkServiceGetEnabled                     (SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceGetInterface
+       @discussion Returns the network interface associated with the service.
+       @param service The network service.
+       @result A reference to the SCNetworkInterface associated with the service;
+               NULL if an error was encountered.
+ */
+SCNetworkInterfaceRef
+SCNetworkServiceGetInterface                   (SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceGetName
+       @discussion Returns the [user specified] name associated with the service.
+       @param service The network service.
+       @result The [user specified] name.
+ */
+CFStringRef
+SCNetworkServiceGetName                                (SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceCopyProtocol
+       @discussion Returns the network protocol of the specified type for
+               the service.
+       @param service The network service.
+       @result A reference to the SCNetworkProtocol associated with the service;
+               NULL if this protocol has not been added or if an error was encountered.
+               You must release the returned value.
+ */
+SCNetworkProtocolRef
+SCNetworkServiceCopyProtocol                   (SCNetworkServiceRef            service,
+                                                CFStringRef                    protocolType)   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceGetServiceID
+       @discussion Returns the identifier for the service.
+       @param service The network service.
+       @result The service identifier.
+ */
+CFStringRef
+SCNetworkServiceGetServiceID                   (SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceRemove
+       @discussion Removes the network service from the configuration.
+       @param service The network service.
+       @result TRUE if the service was removed; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkServiceRemove                         (SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceRemoveProtocolType
+       @discussion Removes the network protocol of the specified type from the service.
+       @param service The network service.
+       @param protocolType The type of SCNetworkProtocol to be removed from the service.
+       @result TRUE if the protocol was removed to the service; FALSE if the
+               protocol was not configured or an error was encountered.
+ */
+Boolean
+SCNetworkServiceRemoveProtocolType             (SCNetworkServiceRef            service,
+                                                CFStringRef                    protocolType)   AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceSetEnabled
+       @discussion Enables or disables the service.
+       @param service The network service.
+       @param enabled TRUE if the service should be enabled.
+       @result TRUE if the enabled status was saved; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkServiceSetEnabled                     (SCNetworkServiceRef            service,
+                                                Boolean                        enabled)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkServiceSetName
+       @discussion Stores the [user specified] name for the service.
+       @param service The network service.
+       @param name The [user defined] name to associate with the service.
+       @result TRUE if the name was saved; FALSE if an error was encountered.
+
+       Note: although not technically required, the [user specified] names
+       for all services within any given set should be unique.  As such, an
+       error will be returned if you attemp to name two services with the
+       same string.
+ */
+Boolean
+SCNetworkServiceSetName                                (SCNetworkServiceRef            service,
+                                                CFStringRef                    name)           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/* --------------------------------------------------------------------------------
+ * SETS
+ * -------------------------------------------------------------------------------- */
+
+/*!
+       @group Set configuration
+ */
+
+/*!
+       @function SCNetworkSetGetTypeID
+       @discussion Returns the type identifier of all SCNetworkSet instances.
+ */
+CFTypeID
+SCNetworkSetGetTypeID                          (void)                                          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetAddService
+       @discussion Adds the network service to the set.
+       @param set The network set.
+       @param service The service to be added.
+       @result TRUE if the service was added to the set; FALSE if the
+               service was already present or an error was encountered.
+
+       Note: at the present time, the Network Prefs UI does not
+       support having a single service be a member of more than
+       one set.  As such, an error will be returned if you attempt
+       to add a service to more than one set.
+ */
+Boolean
+SCNetworkSetAddService                         (SCNetworkSetRef                set,
+                                                SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetCopyAll
+       @discussion Returns all available sets for the specified preferences.
+       @param prefs The "preferences" session.
+       @result The list of SCNetworkSet sets associated with the preferences.
+               You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkSetRef's */
+SCNetworkSetCopyAll                            (SCPreferencesRef               prefs)          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetCopyCurrent
+       @discussion Returns the "current" set.
+       @param prefs The "preferences" session.
+       @result The current set; NULL if no current set has been defined.
+ */
+SCNetworkSetRef
+SCNetworkSetCopyCurrent                                (SCPreferencesRef               prefs)          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetCopyServices
+       @discussion Returns all network services associated with the set.
+       @param set The network set.
+       @result The list of SCNetworkService services associated with the set.
+               You must release the returned value.
+ */
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkSetCopyServices                       (SCNetworkSetRef                set)            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetCreate
+       @discussion Create a new set in the configuration.
+       @param prefs The "preferences" session.
+       @result A reference to the new SCNetworkSet.
+               You must release the returned value.
+ */
+SCNetworkSetRef
+SCNetworkSetCreate                             (SCPreferencesRef               prefs)          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetCopy
+       @discussion Returns the set with the specified identifier.
+       @param prefs The "preferences" session.
+       @param setID The unique identifier for the set.
+       @result A reference to the SCNetworkSet from the associated preferences;
+               NULL if the setID does not exist in the preferences or if an
+               error was encountered.
+               You must release the returned value.
+ */
+SCNetworkSetRef
+SCNetworkSetCopy                               (SCPreferencesRef               prefs,
+                                                CFStringRef                    setID)          AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetGetName
+       @discussion Returns the [user specified] name associated with the set.
+       @param set The network set.
+       @result The [user specified] name.
+ */
+CFStringRef
+SCNetworkSetGetName                            (SCNetworkSetRef                set)            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetGetSetID
+       @discussion Returns the identifier for the set.
+       @param set The network set.
+       @result The set identifier.
+ */
+CFStringRef
+SCNetworkSetGetSetID                           (SCNetworkSetRef                set)            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetGetServiceOrder
+       @discussion Returns the [user specified] ordering of network services
+               within the set.
+       @param set The network set.
+       @result The ordered list of CFStringRef service identifiers associated
+               with the set;
+               NULL if no service order has been specified or if an error
+               was encountered.
+ */
+CFArrayRef /* of serviceID CFStringRef's */
+SCNetworkSetGetServiceOrder                    (SCNetworkSetRef                set)            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetRemove
+       @discussion Removes the set from the configuration.
+       @param set The network set.
+       @result TRUE if the set was removed; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkSetRemove                             (SCNetworkSetRef                set)            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetRemoveService
+       @discussion Removes the network service from the set.
+       @param set The network set.
+       @param service The service to be removed.
+       @result TRUE if the service was removed from the set; FALSE if the
+               service was not already present or an error was encountered.
+ */
+Boolean
+SCNetworkSetRemoveService                      (SCNetworkSetRef                set,
+                                                SCNetworkServiceRef            service)        AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetSetCurrent
+       @discussion Specifies the set that should be the "current" set.
+       @param set The network set.
+       @result TRUE if the current set was updated;
+               FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkSetSetCurrent                         (SCNetworkSetRef                set)            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetSetName
+       @discussion Stores the [user specified] name for the set.
+       @param set The network set.
+       @param name The [user defined] name to associate with the set.
+       @result TRUE if the name was saved; FALSE if an error was encountered.
+
+       Note: although not technically required, the [user specified] names
+       for all set should be unique.  As such, an error will be returned if
+       you attemp to name two sets with the same string.
+ */
+Boolean
+SCNetworkSetSetName                            (SCNetworkSetRef                set,
+                                                CFStringRef                    name)           AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCNetworkSetGetServiceOrder
+       @discussion Stores the [user specified] ordering of network services for the set.
+       @param set The network set.
+       @param newOrder The ordered list of CFStringRef service identifiers for the set.
+       @result TRUE if the new service order was saved; FALSE if an error was encountered.
+ */
+Boolean
+SCNetworkSetSetServiceOrder                    (SCNetworkSetRef                set,
+                                                CFArrayRef                     newOrder)       AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;      /* serviceID CFStringRef's */
+
+
+__END_DECLS
+
+#endif /* _SCNETWORKCONFIGURATION_H */
diff --git a/SystemConfiguration.fproj/SCNetworkConfigurationInternal.c b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.c
new file mode 100644 (file)
index 0000000..d9f1579
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+
+__private_extern__ CFDictionaryRef
+__getPrefsConfiguration(SCPreferencesRef prefs, CFStringRef path)
+{
+       CFDictionaryRef config;
+       CFIndex         n;
+
+       config = SCPreferencesPathGetValue(prefs, path);
+
+       n = isA_CFDictionary(config) ? CFDictionaryGetCount(config) : 0;
+       switch (n) {
+               case 0 :
+                       // ignore empty configuration entities
+                       config = NULL;
+                       break;
+               case 1 :
+                       if (CFDictionaryContainsKey(config, kSCResvInactive)) {
+                               // ignore [effectively] empty configuration entities
+                               config = NULL;
+                       }
+                       break;
+               default :
+                       break;
+       }
+
+       return config;
+}
+
+
+__private_extern__ Boolean
+__setPrefsConfiguration(SCPreferencesRef       prefs,
+                       CFStringRef             path,
+                       CFDictionaryRef         config,
+                       Boolean                 keepInactive)
+{
+       CFMutableDictionaryRef  newConfig       = NULL;
+       Boolean                 ok              = FALSE;
+
+       if (config != NULL) {
+               if (!isA_CFDictionary(config)) {
+                       _SCErrorSet(kSCStatusInvalidArgument);
+                       return FALSE;
+               }
+               newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config);
+       } else {
+               newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       }
+
+       if (keepInactive) {
+               CFDictionaryRef curConfig;
+
+               /*
+                * preserve enabled/disabled state
+                */
+
+               curConfig = SCPreferencesPathGetValue(prefs, path);
+               if (isA_CFDictionary(curConfig) && CFDictionaryContainsKey(curConfig, kSCResvInactive)) {
+                       // if currently disabled
+                       CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
+               } else {
+                       // if currently enabled
+                       CFDictionaryRemoveValue(newConfig, kSCResvInactive);
+               }
+       }
+
+       /*
+        * set new configuration
+        */
+
+       if (CFDictionaryGetCount(newConfig) == 0) {
+               CFRelease(newConfig);
+               newConfig = NULL;
+       }
+
+       if (newConfig == NULL) {
+               ok = SCPreferencesPathRemoveValue(prefs, path);
+       } else {
+               ok = SCPreferencesPathSetValue(prefs, path, newConfig);
+       }
+
+       if (newConfig != NULL)  CFRelease(newConfig);
+       return ok;
+}
+
+
+__private_extern__ Boolean
+__getPrefsEnabled(SCPreferencesRef prefs, CFStringRef path)
+{
+       CFDictionaryRef config;
+
+       config = SCPreferencesPathGetValue(prefs, path);
+       if (isA_CFDictionary(config) && CFDictionaryContainsKey(config, kSCResvInactive)) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+__private_extern__ Boolean
+__setPrefsEnabled(SCPreferencesRef      prefs,
+                 CFStringRef           path,
+                 Boolean               enabled)
+{
+       CFDictionaryRef         curConfig       = NULL;
+       CFMutableDictionaryRef  newConfig       = NULL;
+       Boolean                 ok              = FALSE;
+
+       /*
+        * preserve current configuration
+        */
+
+       curConfig = SCPreferencesPathGetValue(prefs, path);
+       if (curConfig != NULL) {
+               if (!isA_CFDictionary(curConfig)) {
+                       _SCErrorSet(kSCStatusFailed);
+                       return FALSE;
+               }
+               newConfig = CFDictionaryCreateMutableCopy(NULL, 0, curConfig);
+       } else {
+               newConfig = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+       }
+
+       if (enabled) {
+               // enable
+               CFDictionaryRemoveValue(newConfig, kSCResvInactive);
+       } else {
+               // disable
+               CFDictionarySetValue(newConfig, kSCResvInactive, kCFBooleanTrue);
+       }
+
+       /*
+        * update configuration
+        */
+
+       if (CFDictionaryGetCount(newConfig) == 0) {
+               CFRelease(newConfig);
+               newConfig = NULL;
+       }
+
+       if (newConfig == NULL) {
+               ok = SCPreferencesPathRemoveValue(prefs, path);
+       } else {
+               ok = SCPreferencesPathSetValue(prefs, path, newConfig);
+       }
+
+       if (newConfig != NULL)  CFRelease(newConfig);
+       return ok;
+}
+
+
+#define SYSTEMCONFIGURATION_BUNDLE_ID   CFSTR("com.apple.SystemConfiguration")
+#define SYSTEMCONFIGURATION_FRAMEWORK   "SystemConfiguration.framework"
+
+
+static CFDictionaryRef
+__copyTemplates()
+{
+       CFBundleRef     bundle;
+       Boolean         ok;
+       CFDictionaryRef templates;
+       CFURLRef        url;
+       CFStringRef     xmlError        = NULL;
+       CFDataRef       xmlTemplates    = NULL;
+
+       bundle = CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID);
+       if (bundle == NULL) {
+               return NULL;
+       }
+
+       url = CFBundleCopyResourceURL(bundle, CFSTR("NetworkConfiguration"), CFSTR("plist"), NULL);
+       if (url == NULL) {
+               return NULL;
+       }
+
+       ok = CFURLCreateDataAndPropertiesFromResource(NULL, url, &xmlTemplates, NULL, NULL, NULL);
+       CFRelease(url);
+       if (!ok || (xmlTemplates == NULL)) {
+               return NULL;
+       }
+
+       /* convert the XML data into a property list */
+       templates = CFPropertyListCreateFromXMLData(NULL, xmlTemplates, kCFPropertyListImmutable, &xmlError);
+       CFRelease(xmlTemplates);
+       if (templates == NULL) {
+               if (xmlError != NULL) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("could not load SCNetworkConfiguration templates: %@"), xmlError);
+                       CFRelease(xmlError);
+               }
+               return NULL;
+       }
+
+       if (!isA_CFDictionary(templates)) {
+               CFRelease(templates);
+               return NULL;
+       }
+
+       return templates;
+}
+
+
+__private_extern__ CFDictionaryRef
+__copyInterfaceTemplate(CFStringRef      interfaceType,
+                       CFStringRef      childInterfaceType)
+{
+       CFDictionaryRef interface       = NULL;
+       CFDictionaryRef interfaces;
+       CFDictionaryRef templates;
+
+       templates = __copyTemplates();
+       if (templates == NULL) {
+               return NULL;
+       }
+
+       interfaces = CFDictionaryGetValue(templates, CFSTR("Interface"));
+       if (!isA_CFDictionary(interfaces)) {
+               CFRelease(templates);
+               return NULL;
+       }
+
+       if (childInterfaceType == NULL) {
+               interface = CFDictionaryGetValue(interfaces, interfaceType);
+       } else {
+               CFStringRef     expandedType;
+
+               expandedType = CFStringCreateWithFormat(NULL,
+                                                       NULL,
+                                                       CFSTR("%@-%@"),
+                                                       interfaceType,
+                                                       childInterfaceType);
+               interface = CFDictionaryGetValue(interfaces, expandedType);
+               CFRelease(expandedType);
+       }
+
+       if (isA_CFDictionary(interface) && (CFDictionaryGetCount(interface) > 0)) {
+               CFRetain(interface);
+       } else {
+               interface = NULL;
+       }
+
+       CFRelease(templates);
+
+       return interface;
+}
+
+
+__private_extern__ CFDictionaryRef
+__copyProtocolTemplate(CFStringRef      interfaceType,
+                      CFStringRef      childInterfaceType,
+                      CFStringRef      protocolType)
+{
+       CFDictionaryRef interface       = NULL;
+       CFDictionaryRef protocol        = NULL;
+       CFDictionaryRef protocols;
+       CFDictionaryRef templates;
+
+       templates = __copyTemplates();
+       if (templates == NULL) {
+               return NULL;
+       }
+
+       protocols = CFDictionaryGetValue(templates, CFSTR("Protocol"));
+       if (!isA_CFDictionary(protocols)) {
+               CFRelease(templates);
+               return NULL;
+       }
+
+       if (childInterfaceType == NULL) {
+               interface = CFDictionaryGetValue(protocols, interfaceType);
+       } else {
+               CFStringRef     expandedType;
+
+               expandedType = CFStringCreateWithFormat(NULL,
+                                                       NULL,
+                                                       CFSTR("%@-%@"),
+                                                       interfaceType,
+                                                       childInterfaceType);
+               interface = CFDictionaryGetValue(protocols, expandedType);
+               CFRelease(expandedType);
+       }
+
+       if (isA_CFDictionary(interface)) {
+               protocol = CFDictionaryGetValue(interface, protocolType);
+               if (isA_CFDictionary(protocol) && (CFDictionaryGetCount(protocol) > 0)) {
+                       CFRetain(protocol);
+               } else {
+                       protocol = NULL;
+               }
+       }
+
+       CFRelease(templates);
+
+       return protocol;
+}
+
+
+__private_extern__ Boolean
+__createInterface(int s, CFStringRef interface)
+{
+       struct ifreq    ifr;
+
+       bzero(&ifr, sizeof(ifr));
+       (void) _SC_cfstring_to_cstring(interface,
+                                      ifr.ifr_name,
+                                      sizeof(ifr.ifr_name),
+                                      kCFStringEncodingASCII);
+
+       if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
+               SCLog(TRUE,
+                     LOG_ERR,
+                     CFSTR("could not create interface \"%@\": %s"),
+                     interface,
+                     strerror(errno));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+__private_extern__ Boolean
+__destroyInterface(int s, CFStringRef interface)
+{
+       struct ifreq    ifr;
+
+       bzero(&ifr, sizeof(ifr));
+       (void) _SC_cfstring_to_cstring(interface,
+                                      ifr.ifr_name,
+                                      sizeof(ifr.ifr_name),
+                                      kCFStringEncodingASCII);
+
+       if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) {
+               SCLog(TRUE,
+                     LOG_ERR,
+                     CFSTR("could not destroy interface \"%@\": %s"),
+                     interface,
+                     strerror(errno));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+__private_extern__ Boolean
+__markInterfaceUp(int s, CFStringRef interface)
+{
+       struct ifreq    ifr;
+
+       bzero(&ifr, sizeof(ifr));
+       (void) _SC_cfstring_to_cstring(interface,
+                                      ifr.ifr_name,
+                                      sizeof(ifr.ifr_name),
+                                      kCFStringEncodingASCII);
+
+       if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) {
+               SCLog(TRUE,
+                     LOG_ERR,
+                     CFSTR("could not get flags for interface \"%@\": %s"),
+                     interface,
+                     strerror(errno));
+               return FALSE;
+       }
+
+       ifr.ifr_flags |= IFF_UP;
+       if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) == -1) {
+               SCLog(TRUE,
+                     LOG_ERR,
+                     CFSTR("could not set flags for interface \"%@\": %s"),
+                     interface,
+                     strerror(errno));
+               return FALSE;
+       }
+
+       return TRUE;
+}
diff --git a/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h b/SystemConfiguration.fproj/SCNetworkConfigurationInternal.h
new file mode 100644 (file)
index 0000000..e0c981b
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCPreferencesPathKey.h>
+#include <IOKit/IOKitLib.h>
+
+#include "SCNetworkConfiguration.h"
+
+typedef struct {
+
+       /* base CFType information */
+       CFRuntimeBase           cfBase;
+
+       /* set id */
+       CFStringRef             setID;
+
+       /* prefs */
+       SCPreferencesRef        prefs;
+
+} SCNetworkSetPrivate, *SCNetworkSetPrivateRef;
+
+
+typedef struct {
+
+       /* base CFType information */
+       CFRuntimeBase           cfBase;
+
+       /* service id */
+       CFStringRef             serviceID;
+
+       /* interface */
+       SCNetworkInterfaceRef   interface;
+
+       /* prefs */
+       SCPreferencesRef        prefs;
+
+} SCNetworkServicePrivate, *SCNetworkServicePrivateRef;
+
+
+typedef struct {
+
+       /* base CFType information */
+       CFRuntimeBase           cfBase;
+
+       /* entity id */
+       CFStringRef             entityID;
+
+       /* service */
+       SCNetworkServiceRef     service;
+
+} SCNetworkProtocolPrivate, *SCNetworkProtocolPrivateRef;
+
+
+typedef struct {
+
+       // base CFType information
+       CFRuntimeBase           cfBase;
+
+       // interface information
+       CFStringRef             interface_type;         // interface type
+
+       // localized name
+       CFStringRef             localized_name;         // localized [display] name
+       CFStringRef             localized_key;
+       CFStringRef             localized_arg1;
+       CFStringRef             localized_arg2;
+
+       /* [layered] interface*/
+       SCNetworkInterfaceRef   interface;
+
+       /* service (NULL if not associated with a service)  */
+       SCNetworkServiceRef     service;
+
+       /* unsaved configuration (when prefs not [yet] available) */
+       CFDictionaryRef         unsaved;
+
+       // [SCPreferences] interface entity information
+       CFStringRef             entity_device;          // interface device
+       CFStringRef             entity_hardware;        // interface hardware
+       CFStringRef             entity_type;            // interface type
+       CFStringRef             entity_subtype;         // interface subtype
+
+       // configuration information
+       CFMutableArrayRef       supported_interface_types;
+       CFMutableArrayRef       supported_protocol_types;
+
+       // IORegistry (service plane) information
+       CFStringRef             address;
+       Boolean                 builtin;
+       CFStringRef             location;
+       CFStringRef             path;
+       Boolean                 supportsDeviceOnHold;
+       Boolean                 supportsBond;
+       Boolean                 supportsVLAN;
+
+       // misc
+       int                     sort_order;             // sort order for this interface
+
+} SCNetworkInterfacePrivate, *SCNetworkInterfacePrivateRef;
+
+
+__BEGIN_DECLS
+
+
+SCNetworkServicePrivateRef
+__SCNetworkServiceCreatePrivate                        (CFAllocatorRef         allocator,
+                                                CFStringRef            serviceID,
+                                                SCNetworkInterfaceRef  interface,
+                                                SCPreferencesRef       prefs);
+
+
+SCNetworkProtocolPrivateRef
+__SCNetworkProtocolCreatePrivate               (CFAllocatorRef         allocator,
+                                                CFStringRef            entityID,
+                                                SCNetworkServiceRef    service);
+
+Boolean
+__SCNetworkProtocolIsValidType                 (CFStringRef            protocolType);
+
+SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreateCopy                 (CFAllocatorRef         allocator,
+                                                SCNetworkInterfaceRef  interface,
+                                                SCNetworkServiceRef    service);
+
+SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreatePrivate              (CFAllocatorRef         allocator,
+                                                SCNetworkInterfaceRef  interface,
+                                                SCNetworkServiceRef    service,
+                                                io_string_t            path);
+
+SCNetworkInterfaceRef
+__SCNetworkInterfaceCreateWithEntity           (CFAllocatorRef         allocator,
+                                                CFDictionaryRef        interface_entity,
+                                                SCNetworkServiceRef    service);
+
+CFArrayRef
+__SCNetworkInterfaceCopyDeepConfiguration       (SCNetworkInterfaceRef  interface);
+
+Boolean
+__SCNetworkInterfaceSetConfiguration           (SCNetworkInterfaceRef  interface,
+                                                CFDictionaryRef        config,
+                                                Boolean                okToHold);
+
+void
+__SCNetworkInterfaceSetDeepConfiguration       (SCNetworkInterfaceRef  interface,
+                                                CFArrayRef             configs);
+
+CFDictionaryRef
+__copyInterfaceTemplate                                (CFStringRef            interfaceType,
+                                                CFStringRef            childInterfaceType);
+
+CFDictionaryRef
+__copyProtocolTemplate                         (CFStringRef            interfaceType,
+                                                CFStringRef            childInterfaceType,
+                                                CFStringRef            protocolType);
+
+CFDictionaryRef
+__getPrefsConfiguration                                (SCPreferencesRef       prefs,
+                                                CFStringRef            path);
+
+Boolean
+__setPrefsConfiguration                                (SCPreferencesRef       prefs,
+                                                CFStringRef            path,
+                                                CFDictionaryRef        config,
+                                                Boolean                keepInactive);
+
+Boolean
+__getPrefsEnabled                              (SCPreferencesRef       prefs,
+                                                CFStringRef            path);
+
+Boolean
+__setPrefsEnabled                              (SCPreferencesRef       prefs,
+                                                CFStringRef            path,
+                                                Boolean                enabled);
+
+Boolean
+__createInterface                              (int                    s,
+                                                CFStringRef            interface);
+
+Boolean
+__destroyInterface                             (int                    s,
+                                                CFStringRef            interface);
+
+Boolean
+__markInterfaceUp                              (int                    s,
+                                                CFStringRef            interface);
+
+__END_DECLS
+
+#endif /* _SCNETWORKCONFIGURATIONINTERNAL_H */
index bd3c33166157aea6e8404b0e9957c3f58f9d2027..2e01b503c716b9a3d73ce52106a3872fa08856f0 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * April 14, 2004              Christophe Allie <callie@apple.com>
+ * - use mach messages
+
  * December 20, 2002           Christophe Allie <callie@apple.com>
  * - initial revision
  */
  * December 20, 2002           Christophe Allie <callie@apple.com>
  * - initial revision
  */
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
 
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
 
+#include <servers/bootstrap.h>
+
 #include <pthread.h>
 #include <pthread.h>
+#include <notify.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <arpa/nameser.h>
 #include <netdb.h>
 #include <netdb.h>
-#include <resolv.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
 
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
 
-#include "ppp.h"
-
+#include <ppp/ppp_msg.h>
+#include <ppp/PPPControllerPriv.h>
+#include "pppcontroller.h"
+#include <ppp/pppcontroller_types.h>
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 typedef struct {
 
        /* base CFType information */
 typedef struct {
 
        /* base CFType information */
-       CFRuntimeBase   cfBase;
+       CFRuntimeBase                   cfBase;
 
        /* service ID */
 
        /* 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;
 
        /* run loop source, callout, context, rl scheduling info */
        CFRunLoopSourceRef              rls;
@@ -78,6 +84,9 @@ typedef struct {
        SCNetworkConnectionContext      rlsContext;
        CFMutableArrayRef               rlList;
 
        SCNetworkConnectionContext      rlsContext;
        CFMutableArrayRef               rlList;
 
+       /* misc info */
+       int                             debug;
+
 } SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef;
 
 /* -------------------------------------------------------------------------------------------
 } SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef;
 
 /* -------------------------------------------------------------------------------------------
@@ -95,9 +104,9 @@ isA_SCNetworkConnection(CFTypeRef obj)
 static CFStringRef
 __SCNetworkConnectionCopyDescription(CFTypeRef cf)
 {
 static CFStringRef
 __SCNetworkConnectionCopyDescription(CFTypeRef cf)
 {
-       CFAllocatorRef                  allocator = CFGetAllocator(cf);
+       CFAllocatorRef                  allocator               = CFGetAllocator(cf);
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)cf;
        CFMutableStringRef              result;
        CFMutableStringRef              result;
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)cf;
 
        result = CFStringCreateMutable(allocator, 0);
        CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkConnection, %p [%p]> {\n"), cf, allocator);
 
        result = CFStringCreateMutable(allocator, 0);
        CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkConnection, %p [%p]> {\n"), cf, allocator);
@@ -109,37 +118,34 @@ __SCNetworkConnectionCopyDescription(CFTypeRef cf)
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
+
 static void
 __SCNetworkConnectionDeallocate(CFTypeRef cf)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)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 */
 
        /* 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);
                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);
 
        if (connectionPrivate->serviceID)
                CFRelease(connectionPrivate->serviceID);
 
@@ -175,26 +181,130 @@ __SCNetworkConnectionInitialize(void)
        return;
 }
 
        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
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 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;
        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);
 
 
        /* 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);
 
        /* 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;
                goto fail;
+       }
 
        /* zero the data structure */
        bzero(((u_char*)connectionPrivate)+sizeof(CFRuntimeBase), size);
 
        /* 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);
 
        /* 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;
                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;
        }
 
                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:
 
 
        /* success, return the connection reference */
        return connectionPrivate;
 
     fail:
 
+
        /* failure, clean up and leave */
        /* 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);
                CFRelease(connectionPrivate);
-       if (stats)
-               CFAllocatorDeallocate(NULL, stats);
+       }
+
+       if (dataRef)            CFRelease(dataRef);
        _SCErrorSet(error);
        return NULL;
 }
        _SCErrorSet(error);
        return NULL;
 }
@@ -234,53 +394,19 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef service
 ------------------------------------------------------------------------------------------- */
 
 CFTypeID
 ------------------------------------------------------------------------------------------- */
 
 CFTypeID
-SCNetworkConnectionGetTypeID (void) {
+SCNetworkConnectionGetTypeID(void) {
        pthread_once(&initialized, __SCNetworkConnectionInitialize);    /* initialize runtime */
        return __kSCNetworkConnectionTypeID;
 }
 
        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
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 SCNetworkConnectionRef
-SCNetworkConnectionCreateWithServiceID (CFAllocatorRef                 allocator,
-                                       CFStringRef                     serviceID,
-                                       SCNetworkConnectionCallBack     callout,
-                                       SCNetworkConnectionContext      *context)
+SCNetworkConnectionCreateWithServiceID(CFAllocatorRef                  allocator,
+                                      CFStringRef                      serviceID,
+                                      SCNetworkConnectionCallBack      callout,
+                                      SCNetworkConnectionContext       *context)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate;
 
 {
        SCNetworkConnectionPrivateRef   connectionPrivate;
 
@@ -289,17 +415,7 @@ SCNetworkConnectionCreateWithServiceID (CFAllocatorRef                     allocator,
                return NULL;
        }
 
                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;
 }
 
        return (SCNetworkConnectionRef)connectionPrivate;
 }
@@ -308,7 +424,7 @@ SCNetworkConnectionCreateWithServiceID (CFAllocatorRef                      allocator,
 ------------------------------------------------------------------------------------------- */
 
 CFStringRef
 ------------------------------------------------------------------------------------------- */
 
 CFStringRef
-SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyServiceID(SCNetworkConnectionRef connection)
 {
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
 {
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -322,67 +438,40 @@ SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection)
 ------------------------------------------------------------------------------------------- */
 
 CFDictionaryRef
 ------------------------------------------------------------------------------------------- */
 
 CFDictionaryRef
-SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyStatistics(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       void                            *data                   = NULL;
+       int                             datalen;
        int                             error                   = kSCStatusFailed;
        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;
        }
 
 
        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;
                goto fail;
+       }
 
 
-       /* create dictionaries */
-       if ((statsdict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0)
+       if (error != kSCStatusOK) {
                goto fail;
                goto fail;
+       }
 
 
-       if ((dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0)
+       if ((data == NULL) ||
+           !_SCUnserialize(&statistics, NULL, data, datalen) ||
+           !isA_CFDictionary(statistics)) {
                goto fail;
                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:
 
 
     fail:
 
-       if (stats)
-               CFAllocatorDeallocate(NULL, stats);
-       if (dict)
-               CFRelease(dict);
-       if (statsdict)
-               CFRelease(statsdict);
+       if (statistics) CFRelease(statistics);
        _SCErrorSet(error);
        return NULL;
 }
        _SCErrorSet(error);
        return NULL;
 }
@@ -391,59 +480,67 @@ SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection)
 ------------------------------------------------------------------------------------------- */
 
 SCNetworkConnectionStatus
 ------------------------------------------------------------------------------------------- */
 
 SCNetworkConnectionStatus
-SCNetworkConnectionGetStatus (SCNetworkConnectionRef connection)
+SCNetworkConnectionGetStatus(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)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);
 
        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
 CFDictionaryRef
-SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyExtendedStatus(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)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 (!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;
                goto fail;
+       }
 
 
-       if (!data
-           || !(status = PPPUnserialize(data, datalen))
-           || !isA_CFDictionary(status))
+       if (error != kSCStatusOK) {
                goto fail;
                goto fail;
+       }
 
 
-       CFAllocatorDeallocate(NULL, data);
-       return status;
+       if ((data == NULL) ||
+           !_SCUnserialize(&extstatus, NULL, data, datalen) ||
+           !isA_CFDictionary(extstatus)) {
+               goto fail;
+       }
+
+       return extstatus;
 
     fail:
 
 
     fail:
 
-       _SCErrorSet(kSCStatusFailed);
-       if (status)
-               CFRelease(status);
-       if (data)
-               CFAllocatorDeallocate(NULL, data);
+       if (extstatus)  CFRelease(extstatus);
+       _SCErrorSet(error);
        return NULL;
 }
 
        return NULL;
 }
 
@@ -451,37 +548,97 @@ SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection)
 ------------------------------------------------------------------------------------------- */
 
 Boolean
 ------------------------------------------------------------------------------------------- */
 
 Boolean
-SCNetworkConnectionStart (SCNetworkConnectionRef       connection,
-                         CFDictionaryRef               userOptions,
-                         Boolean                       linger)
+SCNetworkConnectionStart(SCNetworkConnectionRef        connection,
+                        CFDictionaryRef        userOptions,
+                        Boolean                linger)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
 {
        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);
 
        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;
                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;
                goto fail;
+       }
 
 
-       if (dataref)
+       if (dataref) {
                CFRelease(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:
 
 
        /* connection is now started */
        return TRUE;
 
     fail:
 
-       if (dataref)
-               CFRelease(dataref);
-       _SCErrorSet(kSCStatusFailed);   // XXX
+       if (dataref)    CFRelease(dataref);
+       _SCErrorSet(error);
        return FALSE;
 }
 
        return FALSE;
 }
 
@@ -489,280 +646,214 @@ SCNetworkConnectionStart (SCNetworkConnectionRef        connection,
 ------------------------------------------------------------------------------------------- */
 
 Boolean
 ------------------------------------------------------------------------------------------- */
 
 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 (!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;
        }
 
        /* connection is now disconnecting */
        return TRUE;
+
+    fail:
+
+       _SCErrorSet(error);
+       return FALSE;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 Boolean
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 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);
 
        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;
        }
 
        /* connection is now suspended */
        return TRUE;
+
+    fail:
+
+       _SCErrorSet(error);
+       return FALSE;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 Boolean
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 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);
 
        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;
        }
 
        /* connection is now resume */
        return TRUE;
+
+    fail:
+
+       _SCErrorSet(error);
+       return FALSE;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 CFDictionaryRef
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 CFDictionaryRef
-SCNetworkConnectionCopyUserOptions (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyUserOptions(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)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 (!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;
                goto fail;
+       }
+
+       if (error != kSCStatusOK) {
+               goto fail;
+       }
 
        // no data were used, return an empty dictionary
 
        // no data were used, return an empty dictionary
-       if (data == 0) {
+       if (data == NULL) {
                CFDictionaryRef dict;
 
                dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
                CFDictionaryRef dict;
 
                dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-               if (dict == 0)
+               if (dict == NULL) {
                        _SCErrorSet(kSCStatusFailed); // XXX
                        _SCErrorSet(kSCStatusFailed); // XXX
+               }
                return dict;
        }
 
                return dict;
        }
 
-       userOptions = PPPUnserialize(data, datalen);
-       if (!isA_CFDictionary(userOptions))
+       if (!_SCUnserialize(&userOptions, NULL, data, datalen) ||
+           !isA_CFDictionary(userOptions)) {
                goto fail;
                goto fail;
+       }
 
 
-       CFAllocatorDeallocate(NULL, data);
        return userOptions;
 
     fail:
 
        return userOptions;
 
     fail:
 
-       _SCErrorSet(kSCStatusFailed);
-       if (userOptions)
-               CFRelease(userOptions);
-       if (data)
-               CFAllocatorDeallocate(NULL, data);
+       if (userOptions)        CFRelease(userOptions);
+       _SCErrorSet(error);
        return NULL;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
        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)
 {
 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 (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
        }
 
-       if (connectionPrivate->rlsFunction == 0) {
+       if (connectionPrivate->rlsFunction == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
        }
 
                _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;
        }
 
                /* 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;
                }
 
                        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);
                connectionPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-               //CFRelease(ref);
        }
 
        CFRunLoopAddSource(runLoop, connectionPrivate->rls, runLoopMode);
        }
 
        CFRunLoopAddSource(runLoop, connectionPrivate->rls, runLoopMode);
-       __schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList);
+       _SC_schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList);
 
        return TRUE;
 }
 
        return TRUE;
 }
@@ -775,15 +866,17 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef           connection,
                                         CFRunLoopRef                   runLoop,
                                         CFStringRef                    runLoopMode)
 {
                                         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 (!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;
                /* if not currently scheduled */
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
@@ -796,11 +889,12 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef           connection,
                connectionPrivate->rls = NULL;
                CFRelease(connectionPrivate->rlList);
                connectionPrivate->rlList = NULL;
                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;
        }
 
        return TRUE;
@@ -810,6 +904,7 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef             connection,
 //************************* USER LEVEL DIAL API **********************************
 
 
 //************************* 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")
 
 #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 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
 
 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, &notify_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
 
 
        // 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);
                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;
 }
 
        return success;
 }
 
+
 //*******************************************************************************************
 // SCNetworkConnectionPrivateCopyDefaultServiceIDForDial
 // ----------------------------------------------------
 //*******************************************************************************************
 // SCNetworkConnectionPrivateCopyDefaultServiceIDForDial
 // ----------------------------------------------------
@@ -887,19 +1210,11 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
        Boolean                 foundService            = FALSE;
        CFPropertyListRef       lastServiceSelectedInIC = NULL;
 
        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
 
        // 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;
                        // 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);
                                                                          kSCEntNetInterface);
                        dict = SCDynamicStoreCopyValue(session, key);
                        CFRelease(key);
-                       if (dict) {
+                       if (dict != NULL) {
+                               CFRelease(dict);
                                *serviceID = CFRetain(lastServiceSelectedInIC);
                                foundService = TRUE;
                                *serviceID = CFRetain(lastServiceSelectedInIC);
                                foundService = TRUE;
-                               CFRelease(dict);
                        }
                }
                CFRelease(lastServiceSelectedInIC);
                        }
                }
                CFRelease(lastServiceSelectedInIC);
@@ -934,10 +1249,10 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
 static Boolean
 SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef session, CFStringRef *serviceID)
 {
 static Boolean
 SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef session, CFStringRef *serviceID)
 {
-       Boolean         success         = FALSE;
-       CFStringRef     key             = NULL;
        CFDictionaryRef dict            = NULL;
        CFDictionaryRef dict            = NULL;
+       CFStringRef     key             = NULL;
        CFArrayRef      serviceIDs      = NULL;
        CFArrayRef      serviceIDs      = NULL;
+       Boolean         success         = FALSE;
 
        *serviceID = NULL;
 
 
        *serviceID = NULL;
 
@@ -952,17 +1267,14 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                }
 
                dict = SCDynamicStoreCopyValue(session, key);
                }
 
                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
                        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;
                }
 
                        break;
                }
 
@@ -970,7 +1282,7 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                for (i = 0; i < count; i++) {
                        CFStringRef service = CFArrayGetValueAtIndex(serviceIDs, i);
 
                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;
                                *serviceID = CFRetain(service);
                                success = TRUE;
                                break;
@@ -978,11 +1290,8 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                }
        } while (FALSE);
 
                }
        } while (FALSE);
 
-       if (key != NULL)
-               CFRelease(key);
-
-       if (dict != NULL)
-               CFRelease(dict);
+       if (key != NULL)        CFRelease(key);
+       if (dict != NULL)       CFRelease(dict);
 
        return success;
 }
 
        return success;
 }
@@ -998,16 +1307,15 @@ SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptions
        CFIndex count   = CFArrayGetCount(userOptionsArray);
        int     i;
 
        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
        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
                        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
 //********************************************************************************
 static Boolean
-SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID)
+SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2)
 {
        CFStringRef     entityKey;
 {
        CFStringRef     entityKey;
-       Boolean         isPPPService    = FALSE;
-       Boolean         isModemOrPPPoE  = FALSE;
+       Boolean         isPPPService            = FALSE;
+       Boolean         isMatchingSubType       = FALSE;
+       CFDictionaryRef serviceDict;
 
        entityKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                                kSCDynamicStoreDomainSetup,
                                                                serviceID,
                                                                kSCEntNetInterface);
 
        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
 // --------------------------------------
 }
 
 //********************************************************************************
 // 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
 //********************************************************************************
 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);
        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;
        n = CFArrayGetCount(enumerator);
        if (n > 0) {
                void                    *data   = NULL;
@@ -1108,44 +1502,14 @@ addPasswordFromKeychain(CFDictionaryRef *userOptions)
                                                    NULL,               // attrList
                                                    &dataLen,           // length
                                                    (void *)&data);     // outData
                                                    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);
                }
        }
 
        CFRelease(enumerator);
-       return;
+
+       return password;
 }
 
 //********************************************************************************
 }
 
 //********************************************************************************
@@ -1156,7 +1520,7 @@ addPasswordFromKeychain(CFDictionaryRef *userOptions)
 static CFArrayRef
 copyKeychainEnumerator(CFStringRef uniqueIdentifier)
 {
 static CFArrayRef
 copyKeychainEnumerator(CFStringRef uniqueIdentifier)
 {
-       char                    *buf            = NULL;
+       char                    *buf;
        CFMutableArrayRef       itemArray       = NULL;
        OSStatus                result;
        SecKeychainSearchRef    search          = NULL;
        CFMutableArrayRef       itemArray       = NULL;
        OSStatus                result;
        SecKeychainSearchRef    search          = NULL;
index 74a70d1a498a6a35d8c8346b2b8904899f6570a7..148e3dd186ae269b3aebab81d2b85fa6717a9ae6 100644 (file)
 
 /*!
        @header SCNetworkConnection
 
 /*!
        @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
  */
 
 
 /*!
        @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
 
 
 /*!
        @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;
  */
 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);
        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.
                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 kSCNetworkConnectionInvalid
                The network connection refers to an invalid service.
-
        @constant kSCNetworkConnectionDisconnected
                The network connection is disconnected.
        @constant kSCNetworkConnectionDisconnected
                The network connection is disconnected.
-
        @constant kSCNetworkConnectionConnecting
                The network connection is connecting.
        @constant kSCNetworkConnectionConnecting
                The network connection is connecting.
-
        @constant kSCNetworkConnectionConnected
                The network connection is connected.
        @constant kSCNetworkConnectionConnected
                The network connection is connected.
-
        @constant kSCNetworkConnectionDisconnecting
                The network connection is disconnecting.
  */
        @constant kSCNetworkConnectionDisconnecting
                The network connection is disconnecting.
  */
@@ -96,57 +107,50 @@ enum {
        kSCNetworkConnectionConnected           =  2,
        kSCNetworkConnectionDisconnecting       =  3
 };
        kSCNetworkConnectionConnected           =  2,
        kSCNetworkConnectionDisconnecting       =  3
 };
-typedef int32_t SCNetworkConnectionStatus                              AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef int32_t SCNetworkConnectionStatus;
 
 
 /*!
        @enum SCNetworkConnectionPPPStatus
 
 
 /*!
        @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.
                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 kSCNetworkConnectionPPPDisconnected
                PPP is disconnected.
-
        @constant kSCNetworkConnectionPPPInitializing
                PPP is initializing.
        @constant kSCNetworkConnectionPPPInitializing
                PPP is initializing.
-
        @constant kSCNetworkConnectionPPPConnectingLink
        @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
        @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
        @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
        @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
        @constant kSCNetworkConnectionPPPWaitingForCallBack
-               PPP is waiting for server to call back.
-
+               PPP is waiting for the server to call back.
        @constant kSCNetworkConnectionPPPNegotiatingNetwork
        @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
        @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.
                Additional networking protocol might still be negotiating.
-
        @constant kSCNetworkConnectionPPPTerminating
                PPP networking and link protocols are terminating.
        @constant kSCNetworkConnectionPPPTerminating
                PPP networking and link protocols are terminating.
-
        @constant kSCNetworkConnectionPPPDisconnectingLink
        @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 kSCNetworkConnectionPPPHoldingLinkOff
                PPP is disconnected and maintaining the link temporarily off.
-
        @constant kSCNetworkConnectionPPPSuspended
        @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.
  */
        @constant kSCNetworkConnectionPPPWaitingForRedial
                PPP has found a busy server and is waiting for redial.
  */
@@ -166,7 +170,7 @@ enum {
        kSCNetworkConnectionPPPSuspended                =  12,
        kSCNetworkConnectionPPPWaitingForRedial         =  13
 };
        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.
                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
  */
 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
 
 /*!
 __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;
 
 
 /*!
  */
 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,
  */
 Boolean SCNetworkConnectionCopyUserPreferences (
                                                CFDictionaryRef                 selectionOptions,
@@ -228,22 +236,24 @@ Boolean SCNetworkConnectionCopyUserPreferences    (
 
 /*!
        @function SCNetworkConnectionCreateWithServiceID
 
 /*!
        @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
        @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
                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         (
  */
 SCNetworkConnectionRef
 SCNetworkConnectionCreateWithServiceID         (
@@ -257,8 +267,8 @@ SCNetworkConnectionCreateWithServiceID              (
 /*!
        @function SCNetworkConnectionCopyService
        @discussion Returns the service ID associated with the SCNetworkConnection.
 /*!
        @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               (
  */
 CFStringRef
 SCNetworkConnectionCopyServiceID               (
@@ -269,15 +279,19 @@ SCNetworkConnectionCopyServiceID          (
 /*!
        @function SCNetworkConnectionGetStatus
        @discussion Returns the status of the SCNetworkConnection.
 /*!
        @function SCNetworkConnectionGetStatus
        @discussion Returns the status of the SCNetworkConnection.
-               A status is one of the following values :
-                   kSCNetworkConnectionInvalid
-                   kSCNetworkConnectionDisconnected
-                   kSCNetworkConnectionConnecting
-                   kSCNetworkConnectionDisconnecting
-                   kSCNetworkConnectionConnected
-
+               A status is one of the following values:
+<pre>
+@textblock
+&#32
+       kSCNetworkConnectionInvalid
+       kSCNetworkConnectionDisconnected
+       kSCNetworkConnectionConnecting
+       kSCNetworkConnectionDisconnecting
+       kSCNetworkConnectionConnected
+@/textblock
+</pre>
        @param connection The SCNetworkConnection to obtain status from.
        @param connection The SCNetworkConnection to obtain status from.
-       @result The status value.
+       @result Returns the status value.
 */
 SCNetworkConnectionStatus
 SCNetworkConnectionGetStatus                   (
 */
 SCNetworkConnectionStatus
 SCNetworkConnectionGetStatus                   (
@@ -291,29 +305,34 @@ SCNetworkConnectionGetStatus                      (
                An extended status dictionary contains specific dictionaries
                describing the status for each subcomponent of the service.
 
                An extended status dictionary contains specific dictionaries
                describing the status for each subcomponent of the service.
 
-               For example, a status dictionary will contain the following dictionaries:
-
-               IPv4:
-                   IPaddress: IP address used.
-
-               PPP:
-                   Status: PPP specific status of type SCNetworkConnectionPPPStatus.
-                   LastCause: Available when status is Disconnected.
-                               Contains the last error of disconnection.
-                   ConnectTime: time when the connection happened
-                   MaxTime: maximum time for this connection
-
-               Modem:
-                   ConnectionSpeed:   Speed of the modem connection in bits/s
-
-               Other dictionaries could be present for PPPoE, PPTP and L2TP.
-
-               The status dictionary can be extended as needed in the future
-               to contain additional information.
-
+               For example, a status dictionary will contain the following
+               sub-dictionaries, keys, and values:
+<pre>
+@textblock
+&#32
+       IPv4  : Addresses      : the assigned IP address.
+&#32
+       PPP   : Status         : the PPP-specific status of type
+                                SCNetworkConnectionPPPStatus.
+&#32
+               LastCause      : Available when the status is "Disconnected"
+                                and contains the last error associated with
+                                connecting or disconnecting.
+&#32
+               ConnectTime    : the time when the connection was
+                                established.
+&#32
+       Modem : ConnectSpeed   : the speed of the modem connection
+                                in bits/second.
+@/textblock
+</pre>
+               Other dictionaries could be present for PPPoE, PPTP, and L2TP.
+
+               The status dictionary may be extended in the future to contain
+               additional information.
        @param connection The SCNetworkConnection to obtain status from.
        @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          (
  */
 CFDictionaryRef
 SCNetworkConnectionCopyExtendedStatus          (
@@ -325,23 +344,37 @@ SCNetworkConnectionCopyExtendedStatus             (
        @function SCNetworkConnectionCopyStatistics
        @discussion Returns the statistics of the SCNetworkConnection.
                A statistic dictionary contains specific dictionaries
        @function SCNetworkConnectionCopyStatistics
        @discussion Returns the statistics of the SCNetworkConnection.
                A statistic dictionary contains specific dictionaries
-               with statistics for each subcomponents of the service.
-
-               For example, a statistic dictionary will contain the following dictionaries:
-
-               PPP: {Bytes,Packets,Errors}{In,Out}:
-                   Statistics at the Network level.
-                   Contains the number of bytes, packets, and errors on the PPP interface.
-                   For example, BytesIn contains the number of bytes going up
-                   into the network stack, for any networking protocol,
-                   without the PPP headers and trailers.
-
-               The statistic dictionary can be extended as needed in the future
-               to contain additional information.
-
+               with statistics for each subcomponent of the service.
+
+               For example, a statistics dictionary will contain the following
+               sub-dictionaries, keys, and values:
+<pre>
+@textblock
+&#32
+       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.
+&#32
+       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.
+&#32
+       PPP : ErrorsIn   :
+       PPP : ErrorsOut  : Contains the number of errors going up into
+                          (or coming out of) the network stack for
+                          any networking protocol without the PPP
+                          headers and trailers.
+@/textblock
+</pre>
+               The statistics dictionary may be extended in the future to
+               contain additional information.
        @param connection The SCNetworkConnection to obtained statistics from.
        @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              (
  */
 CFDictionaryRef
 SCNetworkConnectionCopyStatistics              (
@@ -351,42 +384,47 @@ SCNetworkConnectionCopyStatistics         (
 
 /*!
        @function SCNetworkConnectionStart
 
 /*!
        @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
                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.
        @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                       (
  */
 Boolean
 SCNetworkConnectionStart                       (
@@ -398,21 +436,22 @@ SCNetworkConnectionStart                  (
 
 /*!
        @function SCNetworkConnectionStop
 
 /*!
        @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.
        @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                                (
  */
 Boolean
 SCNetworkConnectionStop                                (
@@ -423,13 +462,13 @@ SCNetworkConnectionStop                           (
 
 /*!
        @function SCNetworkConnectionCopyCurrentOptions
 
 /*!
        @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.
                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.
                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             (
  */
 CFDictionaryRef
 SCNetworkConnectionCopyUserOptions             (
@@ -439,12 +478,13 @@ SCNetworkConnectionCopyUserOptions                (
 
 /*!
        @function SCNetworkConnectionScheduleWithRunLoop
 
 /*!
        @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 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         (
  */
 Boolean
 SCNetworkConnectionScheduleWithRunLoop         (
@@ -456,12 +496,13 @@ SCNetworkConnectionScheduleWithRunLoop            (
 
 /*!
        @function SCNetworkConnectionUnscheduleFromRunLoop
 
 /*!
        @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 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       (
  */
 Boolean
 SCNetworkConnectionUnscheduleFromRunLoop       (
diff --git a/SystemConfiguration.fproj/SCNetworkInterface.c b/SystemConfiguration.fproj/SCNetworkInterface.c
new file mode 100644 (file)
index 0000000..bb4fd5a
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ *     which includes code originally authored by
+ *       Robert Ulrich         <rulrich@apple.com>
+ *       Elizaabeth Douglas    <elizabeth@apple.com>
+ *       Quinn                 <eskimo1@apple.com>
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+#include <SystemConfiguration/BondConfiguration.h>
+#include <SystemConfiguration/VLANConfiguration.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFBundle.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/network/IONetworkController.h>
+#include <IOKit/network/IONetworkInterface.h>
+#include <IOKit/network/IOEthernetInterface.h> // for kIOEthernetInterfaceClass
+#include <IOKit/serial/IOSerialKeys.h>
+#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
+#include "dy_framework.h"
+
+#ifndef        kIODeviceSupportsHoldKey
+#define        kIODeviceSupportsHoldKey        "V92Modem"
+#endif
+
+#include "SCNetworkConfiguration.h"
+#include "SCNetworkConfigurationInternal.h"
+
+#include <mach/mach.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <pthread.h>
+
+
+static CFStringRef     __SCNetworkInterfaceCopyDescription     (CFTypeRef cf);
+static void            __SCNetworkInterfaceDeallocate          (CFTypeRef cf);
+static Boolean         __SCNetworkInterfaceEqual               (CFTypeRef cf1, CFTypeRef cf2);
+
+
+enum {
+       kSortInternalModem,
+       kSortUSBModem,
+       kSortModem,
+       kSortBluetooth,
+       kSortIrDA,
+       kSortSerialPort,
+       kSortEthernet,
+       kSortFireWire,
+       kSortAirPort,
+       kSortOtherWireless,
+       kSortBond,
+       kSortVLAN,
+       kSortUnknown
+};
+
+
+const CFStringRef kSCNetworkInterfaceType6to4          = CFSTR("6to4");
+const CFStringRef kSCNetworkInterfaceTypeBluetooth     = CFSTR("Bluetooth");
+const CFStringRef kSCNetworkInterfaceTypeBond          = CFSTR("Bond");
+const CFStringRef kSCNetworkInterfaceTypeEthernet      = CFSTR("Ethernet");
+const CFStringRef kSCNetworkInterfaceTypeFireWire      = CFSTR("FireWire");
+const CFStringRef kSCNetworkInterfaceTypeIEEE80211     = CFSTR("IEEE80211");   // IEEE 802.11, AirPort
+const CFStringRef kSCNetworkInterfaceTypeIrDA          = CFSTR("IrDA");
+const CFStringRef kSCNetworkInterfaceTypeL2TP          = CFSTR("L2TP");
+const CFStringRef kSCNetworkInterfaceTypeModem         = CFSTR("Modem");
+const CFStringRef kSCNetworkInterfaceTypePPP           = CFSTR("PPP");
+const CFStringRef kSCNetworkInterfaceTypePPTP          = CFSTR("PPTP");
+const CFStringRef kSCNetworkInterfaceTypeSerial                = CFSTR("Serial");
+const CFStringRef kSCNetworkInterfaceTypeVLAN          = CFSTR("VLAN");
+
+const CFStringRef kSCNetworkInterfaceTypeIPv4          = CFSTR("IPv4");
+
+static SCNetworkInterfacePrivate __kSCNetworkInterfaceIPv4      = {
+       INIT_CFRUNTIME_BASE(NULL, 0, 0x0080),   // cfBase
+       NULL,                                   // interface type
+       NULL,                                   // localized name
+       NULL,                                   // localization key
+       NULL,                                   // localization arg1
+       NULL,                                   // localization arg2
+       NULL,                                   // [layered] interface
+       NULL,                                   // service
+       NULL,                                   // unsaved
+       NULL,                                   // entity_device
+       NULL,                                   // entity_hardware
+       NULL,                                   // entity_type
+       NULL,                                   // entity_subtype
+       NULL,                                   // supported_interface_types
+       NULL,                                   // supported_protocol_types
+       NULL,                                   // address
+       FALSE,                                  // builtin
+       NULL,                                   // location
+       NULL,                                   // path
+       FALSE,                                  // supportsDeviceOnHold
+       FALSE,                                  // supportsBond
+       FALSE,                                  // supportsVLAN
+       kSortUnknown                            // sort_order
+};
+
+const SCNetworkInterfaceRef kSCNetworkInterfaceIPv4     = (SCNetworkInterfaceRef)&__kSCNetworkInterfaceIPv4;
+
+#define doNone         0
+
+#define do6to4         1<<0
+#define doL2TP         1<<1
+#define doPPP          1<<2
+#define doPPTP         1<<3
+
+#define doAppleTalk     1<<0
+#define doDNS          1<<1
+#define doIPv4         1<<2
+#define doIPv6         1<<3
+#define doProxies       1<<4
+
+static const struct {
+       const CFStringRef       *interface_type;
+       Boolean                 per_interface_config;
+       uint32_t                supported_interfaces;
+       const CFStringRef       *ppp_subtype;
+       uint32_t                supported_protocols;
+} configurations[] = {
+       // interface type                         if config?    interface types         PPP sub-type                            interface protocols
+       // =====================================  ==========    ======================= ======================================= =========================================
+       { &kSCNetworkInterfaceType6to4          , FALSE,        doNone,                 NULL,                                   doIPv6                                          },
+       { &kSCNetworkInterfaceTypeBluetooth     , FALSE,        doPPP,                  &kSCValNetInterfaceSubTypePPPSerial,    doNone                                          },
+       { &kSCNetworkInterfaceTypeBond          , TRUE,         doNone,                 NULL,                                   doAppleTalk|doDNS|doIPv4|doIPv6|doProxies       },
+       { &kSCNetworkInterfaceTypeEthernet      , TRUE,         doPPP,                  &kSCValNetInterfaceSubTypePPPoE,        doAppleTalk|doDNS|doIPv4|doIPv6|doProxies       },
+       { &kSCNetworkInterfaceTypeFireWire      , TRUE,         doNone,                 NULL,                                   doDNS|doIPv4|doIPv6|doProxies                   },
+       { &kSCNetworkInterfaceTypeIEEE80211     , TRUE,         doPPP,                  &kSCValNetInterfaceSubTypePPPoE,        doAppleTalk|doDNS|doIPv4|doIPv6|doProxies       },
+       { &kSCNetworkInterfaceTypeIrDA          , FALSE,        doPPP,                  &kSCValNetInterfaceSubTypePPPSerial,    doNone                                          },
+       { &kSCNetworkInterfaceTypeL2TP          , FALSE,        doPPP,                  &kSCValNetInterfaceSubTypeL2TP,         doNone                                          },
+       { &kSCNetworkInterfaceTypeModem         , FALSE,        doPPP,                  &kSCValNetInterfaceSubTypePPPSerial,    doNone                                          },
+       { &kSCNetworkInterfaceTypePPP           , FALSE,        doNone,                 NULL,                                   doDNS|doIPv4|doIPv6|doProxies                   },
+       { &kSCNetworkInterfaceTypePPTP          , FALSE,        doPPP,                  &kSCValNetInterfaceSubTypePPTP,         doNone                                          },
+       { &kSCNetworkInterfaceTypeSerial        , FALSE,        doPPP,                  &kSCValNetInterfaceSubTypePPPSerial,    doNone                                          },
+       { &kSCNetworkInterfaceTypeVLAN          , TRUE,         doNone,                 NULL,                                   doAppleTalk|doDNS|doIPv4|doIPv6|doProxies       },
+       // =====================================  ==========    ======================= ======================================= =========================================
+       { &kSCNetworkInterfaceTypeIPv4          , FALSE,        do6to4|doPPTP|doL2TP,   NULL,                                   doNone                                          }
+};
+
+
+#define        SYSTEMCONFIGURATION_BUNDLE_ID   CFSTR("com.apple.SystemConfiguration")
+#define        NETWORKINTERFACE_LOCALIZATIONS  CFSTR("NetworkInterface")
+static CFBundleRef bundle                      = NULL;
+
+
+static CFTypeID __kSCNetworkInterfaceTypeID    = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkInterfaceClass = {
+       0,                                      // version
+       "SCNetworkInterface",                   // className
+       NULL,                                   // init
+       NULL,                                   // copy
+       __SCNetworkInterfaceDeallocate,         // dealloc
+       __SCNetworkInterfaceEqual,              // equal
+       NULL,                                   // hash
+       NULL,                                   // copyFormattingDesc
+       __SCNetworkInterfaceCopyDescription     // copyDebugDesc
+};
+
+
+static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkInterface(CFTypeRef obj)
+{
+       return (isA_CFType(obj, SCNetworkInterfaceGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkInterfaceCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef                  allocator               = CFGetAllocator(cf);
+       CFMutableStringRef              result;
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)cf;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkInterface %p [%p]> { "), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("type = %@"), interfacePrivate->interface_type);
+       CFStringAppendFormat(result, NULL, CFSTR(", entity = %@ / %@ / %@"),
+                            interfacePrivate->entity_device,
+                            interfacePrivate->entity_hardware,
+                            interfacePrivate->entity_type);
+       if (interfacePrivate->entity_subtype != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(" / %@"), interfacePrivate->entity_subtype);
+       }
+       if (interfacePrivate->localized_name != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), interfacePrivate->localized_name);
+       } else {
+               if (interfacePrivate->localized_key != NULL) {
+                       CFStringAppendFormat(result, NULL, CFSTR(", name = \"%@\""), interfacePrivate->localized_key);
+                       if (interfacePrivate->localized_arg1 != NULL) {
+                               CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg1);
+                       }
+                       if (interfacePrivate->localized_arg2 != NULL) {
+                               CFStringAppendFormat(result, NULL, CFSTR("+\"%@\""), interfacePrivate->localized_arg2);
+                       }
+               }
+       }
+       if (interfacePrivate->address != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", address = %@"), interfacePrivate->address);
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(", builtin = %s"), interfacePrivate->builtin ? "TRUE" : "FALSE");
+       if (interfacePrivate->location != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", location = %@"), interfacePrivate->location);
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(", path = %@"), interfacePrivate->path);
+       CFStringAppendFormat(result, NULL, CFSTR(", order = %d"), interfacePrivate->sort_order);
+
+       if (interfacePrivate->service != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", service=%@"), interfacePrivate->service);
+       }
+
+       if (interfacePrivate->interface != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", interface=%@"), interfacePrivate->interface);
+       }
+
+       if (interfacePrivate->unsaved != NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR(", unsaved=%@"), interfacePrivate->unsaved);
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__SCNetworkInterfaceDeallocate(CFTypeRef cf)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)cf;
+
+       /* release resources */
+
+       if (interfacePrivate->interface != NULL)
+               CFRelease(interfacePrivate->interface);
+
+       if (interfacePrivate->localized_name != NULL)
+               CFRelease(interfacePrivate->localized_name);
+
+       if (interfacePrivate->localized_arg1 != NULL)
+               CFRelease(interfacePrivate->localized_arg1);
+
+       if (interfacePrivate->localized_arg2 != NULL)
+               CFRelease(interfacePrivate->localized_arg2);
+
+       if (interfacePrivate->unsaved != NULL)
+               CFRelease(interfacePrivate->unsaved);
+
+       if (interfacePrivate->entity_device != NULL)
+               CFRelease(interfacePrivate->entity_device);
+
+       if (interfacePrivate->supported_interface_types != NULL)
+               CFRelease(interfacePrivate->supported_interface_types);
+
+       if (interfacePrivate->supported_protocol_types != NULL)
+               CFRelease(interfacePrivate->supported_protocol_types);
+
+       if (interfacePrivate->address != NULL)
+               CFRelease(interfacePrivate->address);
+
+       if (interfacePrivate->location != NULL)
+               CFRelease(interfacePrivate->location);
+
+       if (interfacePrivate->path != NULL)
+               CFRelease(interfacePrivate->path);
+
+       return;
+}
+
+
+static Boolean
+__SCNetworkInterfaceEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+       SCNetworkInterfacePrivateRef    if1     = (SCNetworkInterfacePrivateRef)cf1;
+       SCNetworkInterfacePrivateRef    if2     = (SCNetworkInterfacePrivateRef)cf2;
+
+       if (if1 == if2)
+               return TRUE;
+
+       if (!CFEqual(if1->interface_type, if2->interface_type)) {
+               return FALSE;   // if not the same interface type
+       }
+
+       if (if1->entity_device != if2->entity_device) {
+               if ((if1->entity_device != NULL) && (if2->entity_device != NULL)) {
+                       if (!CFEqual(if1->entity_device, if2->entity_device)) {
+                               return FALSE;   // if not the same device
+                       }
+               } else {
+                       return FALSE;   // if only one interface has a device
+               }
+       }
+
+       return TRUE;
+}
+
+
+static void
+__SCNetworkInterfaceInitialize(void)
+{
+       // register w/CF
+       __kSCNetworkInterfaceTypeID = _CFRuntimeRegisterClass(&__SCNetworkInterfaceClass);
+
+       // initialize __kSCNetworkInterfaceIPv4
+       _CFRuntimeSetInstanceTypeID(&__kSCNetworkInterfaceIPv4, __kSCNetworkInterfaceTypeID);
+       __kSCNetworkInterfaceIPv4.interface_type = kSCNetworkInterfaceTypeIPv4;
+       __kSCNetworkInterfaceIPv4.localized_key  = CFSTR("ipv4");
+
+       // get CFBundleRef for SystemConfiguration.framework
+       bundle = CFBundleGetBundleWithIdentifier(SYSTEMCONFIGURATION_BUNDLE_ID);
+       if (bundle == NULL) {
+               // try a bit harder
+               CFURLRef        url;
+
+               url = CFURLCreateWithFileSystemPath(NULL,
+                                                   CFSTR("/System/Library/Frameworks/SystemConfiguration.framework"),
+                                                   kCFURLPOSIXPathStyle,
+                                                   TRUE);
+               bundle = CFBundleCreate(NULL, url);
+               CFRelease(url);
+       }
+
+       return;
+}
+
+
+__private_extern__ SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreatePrivate(CFAllocatorRef       allocator,
+                                 SCNetworkInterfaceRef interface,
+                                 SCNetworkServiceRef   service,
+                                 io_string_t           path)
+{
+       SCNetworkInterfacePrivateRef            interfacePrivate;
+       uint32_t                                size;
+
+       /* initialize runtime */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       /* allocate target */
+       size             = sizeof(SCNetworkInterfacePrivate) - sizeof(CFRuntimeBase);
+       interfacePrivate = (SCNetworkInterfacePrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                                 __kSCNetworkInterfaceTypeID,
+                                                                                 size,
+                                                                                 NULL);
+       if (interfacePrivate == NULL) {
+               return NULL;
+       }
+
+       interfacePrivate->interface_type                = NULL;
+       interfacePrivate->localized_name                = NULL;
+       interfacePrivate->localized_key                 = NULL;
+       interfacePrivate->localized_arg1                = NULL;
+       interfacePrivate->localized_arg2                = NULL;
+       interfacePrivate->interface                     = (interface != NULL) ? CFRetain(interface) : NULL;
+       interfacePrivate->service                       = service;
+       interfacePrivate->unsaved                       = NULL;
+       interfacePrivate->entity_device                 = NULL;
+       interfacePrivate->entity_hardware               = NULL;
+       interfacePrivate->entity_type                   = NULL;
+       interfacePrivate->entity_subtype                = NULL;
+       interfacePrivate->supported_interface_types     = NULL;
+       interfacePrivate->supported_protocol_types      = NULL;
+       interfacePrivate->address                       = NULL;
+       interfacePrivate->builtin                       = FALSE;
+       interfacePrivate->path                          = (path != NULL) ? CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8)
+                                                                        : NULL;
+       interfacePrivate->location                      = NULL;
+       interfacePrivate->supportsDeviceOnHold          = FALSE;
+       interfacePrivate->supportsBond                  = FALSE;
+       interfacePrivate->supportsVLAN                  = FALSE;
+       interfacePrivate->sort_order                    = kSortUnknown;
+
+       return interfacePrivate;
+}
+
+
+/* ---------- ordering ---------- */
+
+
+static CFArrayRef
+split_path(CFStringRef path)
+{
+       CFArrayRef              components;
+       CFMutableStringRef      nPath;
+
+       // turn '@'s into '/'s
+       nPath = CFStringCreateMutableCopy(NULL, 0, path);
+       (void) CFStringFindAndReplace(nPath,
+                                     CFSTR("@"),
+                                     CFSTR("/"),
+                                     CFRangeMake(0, CFStringGetLength(nPath)),
+                                     0);
+
+       // split path into components to be compared
+       components = CFStringCreateArrayBySeparatingStrings(NULL, nPath, CFSTR("/"));
+       CFRelease(nPath);
+
+       return components;
+}
+
+
+static CFComparisonResult
+compare_interfaces(const void *val1, const void *val2, void *context)
+{
+       SCNetworkInterfacePrivateRef    dev1            = (SCNetworkInterfacePrivateRef)val1;
+       SCNetworkInterfacePrivateRef    dev2            = (SCNetworkInterfacePrivateRef)val2;
+       CFComparisonResult              res             = kCFCompareEqualTo;
+
+       /* sort by interface type */
+       if (dev1->sort_order != dev2->sort_order) {
+               if (dev1->sort_order < dev2->sort_order) {
+                       res = kCFCompareLessThan;
+               } else {
+                       res = kCFCompareGreaterThan;
+               }
+               return (res);
+       }
+
+       /* built-in interfaces sort first */
+       if (dev1->builtin != dev2->builtin) {
+               if (dev1->builtin) {
+                       res = kCFCompareLessThan;
+               } else {
+                       res = kCFCompareGreaterThan;
+               }
+               return (res);
+       }
+
+       /* ... and then, sort built-in interfaces by "location" */
+       if (dev1->builtin) {
+               if (dev1->location != dev2->location) {
+                       if (isA_CFString(dev1->location)) {
+                               if (isA_CFString(dev2->location)) {
+                                       res = CFStringCompare(dev1->location, dev2->location, 0);
+                               } else {
+                                       res = kCFCompareLessThan;
+                               }
+                       } else {
+                               res = kCFCompareGreaterThan;
+                       }
+
+                       if (res != kCFCompareEqualTo) {
+                               return (res);
+                       }
+               }
+       }
+
+       /* ... and, then sort by IOPathMatch */
+       if ((dev1->path != NULL) && (dev2->path != NULL)) {
+               CFArrayRef      elements1;
+               CFArrayRef      elements2;
+               CFIndex         i;
+               CFIndex         n;
+               CFIndex         n1;
+               CFIndex         n2;
+
+               elements1 = split_path(dev1->path);
+               n1 = CFArrayGetCount(elements1);
+
+               elements2 = split_path(dev2->path);
+               n2 = CFArrayGetCount(elements2);
+
+               n = (n1 <= n2) ? n1 : n2;
+               for (i = 0; i < n; i++) {
+                       CFStringRef     e1;
+                       CFStringRef     e2;
+                       char            *end;
+                       quad_t          q1;
+                       quad_t          q2;
+                       char            *str;
+                       Boolean         isNum;
+
+                       e1 = CFArrayGetValueAtIndex(elements1, i);
+                       e2 = CFArrayGetValueAtIndex(elements2, i);
+
+                       str = _SC_cfstring_to_cstring(e1, NULL, 0, kCFStringEncodingUTF8);
+                       errno = 0;
+                       q1 = strtoq(str, &end, 16);
+                       isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+                       CFAllocatorDeallocate(NULL, str);
+
+                       if (isNum) {
+                               // if e1 is a valid numeric string
+                               str = _SC_cfstring_to_cstring(e2, NULL, 0, kCFStringEncodingUTF8);
+                               errno = 0;
+                               q2 = strtoq(str, &end, 16);
+                               isNum = ((*str != '\0') && (*end == '\0') && (errno == 0));
+                               CFAllocatorDeallocate(NULL, str);
+
+                               if (isNum) {
+                                       // if e2 is also a valid numeric string
+
+                                       if (q1 == q2) {
+                                               res = kCFCompareEqualTo;
+                                               continue;
+                                       } else if (q1 < q2) {
+                                               res = kCFCompareLessThan;
+                                       } else {
+                                               res = kCFCompareGreaterThan;
+                                       }
+                                       break;
+                               }
+                       }
+
+                       res = CFStringCompare(e1, e2, 0);
+                       if (res != kCFCompareEqualTo) {
+                               break;
+                       }
+               }
+
+               if (res == kCFCompareEqualTo) {
+                       if (n1 < n2) {
+                               res = kCFCompareLessThan;
+                       } else if (n1 < n2) {
+                               res = kCFCompareGreaterThan;
+                       }
+               }
+
+               CFRelease(elements1);
+               CFRelease(elements2);
+
+               if (res != kCFCompareEqualTo) {
+                       return (res);
+               }
+       }
+
+       /* ... and lastly, sort by BSD interface name */
+       if ((dev1->entity_device != NULL) && (dev2->entity_device != NULL)) {
+               res = CFStringCompare(dev1->entity_device, dev2->entity_device, 0);
+       }
+
+       return res;
+}
+
+
+static void
+sort_interfaces(CFMutableArrayRef all_interfaces)
+{
+       int     n       = CFArrayGetCount(all_interfaces);
+
+       if (n < 2) {
+               return;
+       }
+
+       CFArraySortValues(all_interfaces, CFRangeMake(0, n), compare_interfaces, NULL);
+       return;
+}
+
+
+/* ---------- interface details ---------- */
+
+
+static CFStringRef
+IOCopyCFStringValue(CFTypeRef ioVal)
+{
+       if (isA_CFString(ioVal)) {
+               return CFStringCreateCopy(NULL, ioVal);
+       }
+
+       if (isA_CFData(ioVal)) {
+               return CFStringCreateWithCString(NULL, CFDataGetBytePtr(ioVal), kCFStringEncodingUTF8);
+       }
+
+       return NULL;
+}
+
+
+static CFStringRef
+IODictionaryCopyCFStringValue(CFDictionaryRef io_dict, CFStringRef io_key)
+{
+       CFTypeRef       ioVal;
+
+       ioVal = CFDictionaryGetValue(io_dict, io_key);
+       return IOCopyCFStringValue(ioVal);
+}
+
+
+static Boolean
+IOStringValueHasPrefix(CFTypeRef ioVal, CFStringRef prefix)
+{
+       Boolean         match           = FALSE;
+       CFIndex         prefixLen       = CFStringGetLength(prefix);
+       CFStringRef     str             = ioVal;
+
+       if (!isA_CFString(ioVal)) {
+               if (isA_CFData(ioVal)) {
+                       str = CFStringCreateWithCStringNoCopy(NULL,
+                                                             (const char *)CFDataGetBytePtr(ioVal),
+                                                             kCFStringEncodingUTF8,
+                                                             kCFAllocatorNull);
+               } else {
+                       return FALSE;
+               }
+       }
+
+       if ((str != NULL) &&
+           (CFStringGetLength(str) >= prefixLen) &&
+           (CFStringCompareWithOptions(str,
+                                       prefix,
+                                       CFRangeMake(0, prefixLen),
+                                       kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
+               match = TRUE;
+       }
+
+       if (str != ioVal)       CFRelease(str);
+       return match;
+}
+
+
+static CFStringRef
+copyMACAddress(CFDictionaryRef controller_dict)
+{
+       CFStringRef     address = NULL;
+       uint8_t         *bp;
+       char            *cp;
+       CFDataRef       data;
+       CFIndex         n;
+       char            mac[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
+       char            *mac_p  = mac;
+
+       data = CFDictionaryGetValue(controller_dict, CFSTR(kIOMACAddress));
+       if (data == NULL) {
+               return NULL;
+       }
+
+       bp = (uint8_t *)CFDataGetBytePtr(data);
+       n  = CFDataGetLength(data) * 3;
+
+       if (n > sizeof(mac)) {
+               mac_p = CFAllocatorAllocate(NULL, 0, n);
+       }
+
+       for (cp = mac_p; n > 0; n -= 3) {
+               cp += snprintf(cp, n, "%2.2x:", *bp++);
+       }
+
+       address = CFStringCreateWithCString(NULL, mac_p, kCFStringEncodingUTF8);
+       if (mac_p != mac)       CFAllocatorDeallocate(NULL, mac_p);
+       return address;
+}
+
+
+static const struct {
+       const CFStringRef       name;
+       const CFStringRef       slot;
+} slot_mappings[] = {
+       // Beige G3
+       { CFSTR("A1") , CFSTR("1") },
+       { CFSTR("B1") , CFSTR("2") },
+       { CFSTR("C1") , CFSTR("3") },
+
+       // Blue&White G3, Yikes G4
+       { CFSTR("J12"), CFSTR("1") },
+       { CFSTR("J11"), CFSTR("2") },
+       { CFSTR("J10"), CFSTR("3") },
+       { CFSTR("J9"),  CFSTR("4") },
+
+       // AGP G4
+       { CFSTR("A")  , CFSTR("1") },
+       { CFSTR("B")  , CFSTR("2") },
+       { CFSTR("C")  , CFSTR("3") },
+       { CFSTR("D") ,  CFSTR("4") },
+
+       // Digital Audio G4 (and later models)
+       { CFSTR("1")  , CFSTR("1") },
+       { CFSTR("2")  , CFSTR("2") },
+       { CFSTR("3")  , CFSTR("3") },
+       { CFSTR("4") ,  CFSTR("4") },
+       { CFSTR("5") ,  CFSTR("5") }
+};
+
+
+static CFStringRef
+pci_slot(io_registry_entry_t interface, CFTypeRef *pci_slot_name)
+{
+       kern_return_t           kr;
+       io_registry_entry_t     slot    = interface;
+
+       if (pci_slot_name != NULL) *pci_slot_name = NULL;
+
+       while (slot != MACH_PORT_NULL) {
+               io_registry_entry_t     parent;
+               CFTypeRef               slot_name;
+
+               slot_name = IORegistryEntryCreateCFProperty(slot, CFSTR("AAPL,slot-name"), NULL, 0);
+               if (slot_name != NULL) {
+                       Boolean         found;
+
+                       found = IOStringValueHasPrefix(slot_name, CFSTR("slot"));
+                       if (found) {
+                               CFIndex                 i;
+                               CFMutableStringRef      name;
+
+                               // if we found a slot #
+                               name = CFStringCreateMutable(NULL, 0);
+                               if (isA_CFString(slot_name)) {
+                                       if (pci_slot_name != NULL) *pci_slot_name = CFStringCreateCopy(NULL, slot_name);
+                                       CFStringAppend(name, slot_name);
+                               } else if (isA_CFData(slot_name)) {
+                                       if (pci_slot_name != NULL) *pci_slot_name = CFDataCreateCopy(NULL, slot_name);
+                                       CFStringAppendCString(name, CFDataGetBytePtr(slot_name), kCFStringEncodingUTF8);
+                               }
+
+                               (void) CFStringFindAndReplace(name,
+                                                             CFSTR("slot-"),
+                                                             CFSTR(""),
+                                                             CFRangeMake(0, 5),
+                                                             kCFCompareCaseInsensitive|kCFCompareAnchored);
+                               for (i = 0; i < sizeof(slot_mappings)/sizeof(slot_mappings[0]); i++) {
+                                       if (CFStringCompareWithOptions(name,
+                                                                      slot_mappings[i].name,
+                                                                      CFRangeMake(0, CFStringGetLength(slot_mappings[i].name)),
+                                                                      kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                                               CFRelease(name);
+                                               name = (CFMutableStringRef)CFRetain(slot_mappings[i].slot);
+                                               break;
+                                       }
+                               }
+
+                               CFRelease(slot_name);
+                               if (slot != interface) IOObjectRelease(slot);
+                               return name;
+                       }
+
+                       CFRelease(slot_name);
+               }
+
+               kr = IORegistryEntryGetParentEntry(slot, kIOServicePlane, &parent);
+               if (slot != interface) IOObjectRelease(slot);
+               switch (kr) {
+                       case kIOReturnSuccess :
+                               slot = parent;
+                               break;
+                       case kIOReturnNoDevice :
+                               // if we have hit the root node without finding a slot #
+                               goto done;
+                       default :
+                               SCLog(TRUE, LOG_INFO, CFSTR("pci_slot IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+                               goto done;
+               }
+       }
+
+    done :
+
+       return NULL;
+}
+
+
+static CFComparisonResult
+compare_bsdNames(const void *val1, const void *val2, void *context)
+{
+       CFStringRef     bsd1    = (CFStringRef)val1;
+       CFStringRef     bsd2    = (CFStringRef)val2;
+
+       return CFStringCompare(bsd1, bsd2, 0);
+}
+
+
+static CFStringRef
+pci_port(mach_port_t masterPort, CFTypeRef slot_name, CFStringRef bsdName)
+{
+       CFIndex                 n;
+       CFStringRef             port_name       = NULL;
+       CFMutableArrayRef       port_names;
+
+       kern_return_t           kr;
+       CFStringRef             match_keys[2];
+       CFTypeRef               match_vals[2];
+       CFDictionaryRef         match_dict;
+       CFDictionaryRef         matching;
+       io_registry_entry_t     slot;
+       io_iterator_t           slot_iterator   = MACH_PORT_NULL;
+
+       match_keys[0] = CFSTR("AAPL,slot-name");
+       match_vals[0] = slot_name;
+
+       match_dict = CFDictionaryCreate(NULL,
+                                       (const void **)match_keys,
+                                       (const void **)match_vals,
+                                       1,
+                                       &kCFTypeDictionaryKeyCallBacks,
+                                       &kCFTypeDictionaryValueCallBacks);
+
+       match_keys[0] = CFSTR(kIOProviderClassKey);
+       match_vals[0] = CFSTR("IOPCIDevice");
+
+       match_keys[1] = CFSTR(kIOPropertyMatchKey);
+       match_vals[1] = match_dict;
+
+       // note: the "matching" dictionary will be consumed by the following
+       matching = CFDictionaryCreate(NULL,
+                                     (const void **)match_keys,
+                                     (const void **)match_vals,
+                                     sizeof(match_keys)/sizeof(match_keys[0]),
+                                     &kCFTypeDictionaryKeyCallBacks,
+                                     &kCFTypeDictionaryValueCallBacks);
+       CFRelease(match_dict);
+
+       kr = IOServiceGetMatchingServices(masterPort, matching, &slot_iterator);
+       if (kr != kIOReturnSuccess) {
+               SCPrint(TRUE, stderr, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr);
+               return MACH_PORT_NULL;
+       }
+
+       port_names = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       while ((slot = IOIteratorNext(slot_iterator)) != MACH_PORT_NULL) {
+               io_registry_entry_t     child;
+               io_iterator_t           child_iterator  = MACH_PORT_NULL;
+
+               kr = IORegistryEntryCreateIterator(slot,
+                                                  kIOServicePlane,
+                                                  kIORegistryIterateRecursively,
+                                                  &child_iterator);
+               if (kr != kIOReturnSuccess) {
+                       SCPrint(TRUE, stderr, CFSTR("IORegistryEntryCreateIterator() failed, kr = 0x%x\n"), kr);
+                       return MACH_PORT_NULL;
+               }
+
+               while ((child = IOIteratorNext(child_iterator)) != MACH_PORT_NULL) {
+                       if (IOObjectConformsTo(child, kIONetworkInterfaceClass)) {
+                               CFStringRef     if_bsdName;
+
+                               if_bsdName = IORegistryEntryCreateCFProperty(child,
+                                                                            CFSTR(kIOBSDNameKey),
+                                                                            NULL,
+                                                                            0);
+                               if (if_bsdName != NULL) {
+                                       CFArrayAppendValue(port_names, if_bsdName);
+                                       CFRelease(if_bsdName);
+                               }
+                       }
+                       IOObjectRelease(child);
+               }
+               IOObjectRelease(child_iterator);
+               IOObjectRelease(slot);
+       }
+       IOObjectRelease(slot_iterator);
+
+       n = CFArrayGetCount(port_names);
+       if (n > 1) {
+               CFArraySortValues(port_names, CFRangeMake(0, n), compare_bsdNames, NULL);
+               n = CFArrayGetFirstIndexOfValue(port_names, CFRangeMake(0, n), bsdName);
+               if (n != kCFNotFound) {
+                       port_name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), n + 1);
+               }
+       }
+
+       CFRelease(port_names);
+       return port_name;
+}
+
+
+static Boolean
+pci_slot_info(mach_port_t masterPort, io_registry_entry_t interface, CFStringRef *slot_name, CFStringRef *port_name)
+{
+       CFStringRef     bsd_name;
+       Boolean         ok              = FALSE;
+       CFTypeRef       pci_slot_name;
+
+       *slot_name = NULL;
+       *port_name = NULL;
+
+       bsd_name = IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, 0);
+       if (bsd_name == NULL) {
+               return FALSE;
+       }
+
+       *slot_name = pci_slot(interface, &pci_slot_name);
+       if (*slot_name != NULL) {
+               if (pci_slot_name != NULL) {
+                       *port_name = pci_port(masterPort, pci_slot_name, bsd_name);
+                       CFRelease(pci_slot_name);
+               }
+               ok = TRUE;
+       }
+
+       CFRelease(bsd_name);
+       return ok;
+}
+
+
+static Boolean
+isBuiltIn(io_registry_entry_t interface)
+{
+       kern_return_t           kr;
+       io_registry_entry_t     slot    = interface;
+
+       while (slot != MACH_PORT_NULL) {
+               io_registry_entry_t     parent;
+               CFTypeRef               slot_name;
+
+               slot_name = IORegistryEntryCreateCFProperty(slot, CFSTR("AAPL,slot-name"), NULL, 0);
+               if (slot_name != NULL) {
+                       Boolean         found;
+
+                       found = IOStringValueHasPrefix(slot_name, CFSTR("slot"));
+                       CFRelease(slot_name);
+
+                       if (found) {
+                               // if we found a slot # then this is not a built-in interface
+                               if (slot != interface) IOObjectRelease(slot);
+                               return FALSE;
+                       }
+               }
+
+               kr = IORegistryEntryGetParentEntry(slot, kIOServicePlane, &parent);
+               if (slot != interface) IOObjectRelease(slot);
+               switch (kr) {
+                       case kIOReturnSuccess :
+                               slot = parent;
+                               break;
+                       case kIOReturnNoDevice :
+                               // if we have hit the root node without finding a slot #
+                               return TRUE;
+                       default :
+                               SCLog(TRUE, LOG_INFO, CFSTR("isBuiltIn IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+                               return FALSE;
+               }
+       }
+
+       return FALSE;
+}
+
+
+/* ---------- interface enumeration ---------- */
+
+
+typedef Boolean (*processInterface)(mach_port_t                                masterPort,
+                                   SCNetworkInterfacePrivateRef        interfacePrivate,
+                                   io_registry_entry_t                 interface,
+                                   CFDictionaryRef                     interface_dict,
+                                   io_registry_entry_t                 controller,
+                                   CFDictionaryRef                     controller_dict,
+                                   io_registry_entry_t                 bus,
+                                   CFDictionaryRef                     bus_dict);
+
+
+static Boolean
+processNetworkInterface(mach_port_t                    masterPort,
+                       SCNetworkInterfacePrivateRef    interfacePrivate,
+                       io_registry_entry_t             interface,
+                       CFDictionaryRef                 interface_dict,
+                       io_registry_entry_t             controller,
+                       CFDictionaryRef                 controller_dict,
+                       io_registry_entry_t             bus,
+                       CFDictionaryRef                 bus_dict)
+{
+       CFBooleanRef    bVal;
+       io_name_t       c_IOClass;
+       io_name_t       c_IOName;
+       io_name_t       i_IOClass;
+       int             ift     = -1;
+       int             iVal;
+       CFNumberRef     num;
+       CFStringRef     str;
+
+       // get the interface type
+
+       num = CFDictionaryGetValue(interface_dict, CFSTR(kIOInterfaceType));
+       if (!isA_CFNumber(num) ||
+           !CFNumberGetValue(num, kCFNumberIntType, &ift)) {
+               SCPrint(TRUE, stderr, CFSTR("Could not get interface type\n"));
+               return FALSE;
+       }
+
+       switch (ift) {
+               case IFT_ETHER :
+                       // Type, Hardware
+
+                       if (IOObjectGetClass(interface, i_IOClass) != KERN_SUCCESS) {
+                               i_IOClass[0] = '\0';
+                       }
+                       if (IOObjectGetClass(controller, c_IOClass) != KERN_SUCCESS) {
+                               c_IOClass[0] = '\0';
+                       }
+                       if (IORegistryEntryGetName(controller, c_IOName) != KERN_SUCCESS) {
+                               c_IOName[0] = '\0';
+                       }
+
+                       if ((strcmp(i_IOClass, "IO80211Interface"  ) == 0) ||
+                           (strcmp(c_IOClass, "AirPortPCI"        ) == 0) ||
+                           (strcmp(c_IOClass, "AirPortDriver"     ) == 0) ||
+                           (strcmp(c_IOName , "AppleWireless80211") == 0)) {
+                               interfacePrivate->interface_type        = kSCNetworkInterfaceTypeIEEE80211;
+                               interfacePrivate->entity_type           = kSCEntNetEthernet;
+                               interfacePrivate->entity_hardware       = kSCEntNetAirPort;
+                               interfacePrivate->sort_order            = kSortAirPort;
+                       } else {
+                               str = IODictionaryCopyCFStringValue(bus_dict, CFSTR("name"));
+                               if ((str != NULL) && CFEqual(str, CFSTR("radio"))) {
+                                       interfacePrivate->interface_type        = kSCNetworkInterfaceTypeEthernet;      // ??
+                                       interfacePrivate->entity_type           = kSCEntNetEthernet;
+                                       interfacePrivate->entity_hardware       = kSCEntNetEthernet;                    // ??
+                                       interfacePrivate->sort_order            = kSortOtherWireless;
+                               } else {
+                                       interfacePrivate->interface_type        = kSCNetworkInterfaceTypeEthernet;
+                                       interfacePrivate->entity_type           = kSCEntNetEthernet;
+                                       interfacePrivate->entity_hardware       = kSCEntNetEthernet;
+                                       interfacePrivate->sort_order            = kSortEthernet;
+
+                                       // BOND support only enabled for ethernet devices
+                                       interfacePrivate->supportsBond = TRUE;
+                               }
+
+                               if (str != NULL) CFRelease(str);
+                       }
+
+                       // built-in
+                       bVal = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOBuiltin)));
+                       if ((bVal == NULL) || !CFBooleanGetValue(bVal)) {
+                               bVal = isA_CFBoolean(CFDictionaryGetValue(interface_dict, CFSTR(kIOPrimaryInterface)));
+                       }
+                       if (bVal != NULL) {
+                               interfacePrivate->builtin = CFBooleanGetValue(bVal);
+                       } else {
+                               interfacePrivate->builtin = isBuiltIn(interface);
+                       }
+
+                       // location
+                       interfacePrivate->location = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOLocation));
+
+                       // VLAN support
+                       num = CFDictionaryGetValue(controller_dict, CFSTR(kIOFeatures));
+                       if (isA_CFNumber(num) &&
+                           CFNumberGetValue(num, kCFNumberIntType, & iVal)) {
+                               if (iVal & (kIONetworkFeatureHardwareVlan | kIONetworkFeatureSoftwareVlan)) {
+                                       interfacePrivate->supportsVLAN = TRUE;
+                               }
+                       }
+
+                       // localized name
+                       if (interfacePrivate->builtin) {
+                               if ((interfacePrivate->location == NULL) ||
+                                   (CFStringGetLength(interfacePrivate->location) == 0)) {
+                                       interfacePrivate->localized_key = CFSTR("ether");
+                               } else {
+                                       interfacePrivate->localized_key  = CFSTR("multiether");
+                                       interfacePrivate->localized_arg1 = CFRetain(interfacePrivate->location);
+                               }
+                       } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIEEE80211)) {
+                               interfacePrivate->localized_key = CFSTR("airport");
+                       } else  if (interfacePrivate->sort_order == kSortOtherWireless) {
+                               interfacePrivate->localized_key  = CFSTR("wireless");
+                               interfacePrivate->localized_arg1 = CFRetain(CFSTR(""));         // ??
+                       } else {
+                               CFStringRef     provider;
+
+                               // check provider class
+                               provider = IORegistryEntrySearchCFProperty(interface,
+                                                                          kIOServicePlane,
+                                                                          CFSTR(kIOProviderClassKey),
+                                                                          NULL,
+                                                                          kIORegistryIterateRecursively | kIORegistryIterateParents);
+                               if (provider != NULL) {
+                                       if (CFEqual(provider, CFSTR("IOPCIDevice"))) {
+                                               CFStringRef             port_name;
+                                               CFStringRef             slot_name;
+
+                                               if (pci_slot_info(masterPort, interface, &slot_name, &port_name)) {
+                                                       if (port_name == NULL) {
+                                                               interfacePrivate->localized_key  = CFSTR("pci-ether");
+                                                               interfacePrivate->localized_arg1 = slot_name;
+                                                       } else {
+                                                               interfacePrivate->localized_key  = CFSTR("pci-multiether");
+                                                               interfacePrivate->localized_arg1 = slot_name;
+                                                               interfacePrivate->localized_arg2 = port_name;
+                                                       }
+                                               }
+                                       }
+                                       CFRelease(provider);
+                               }
+
+                               if (interfacePrivate->localized_key == NULL) {
+                                       // if no provider, not a PCI device, or no slot information
+                                       interfacePrivate->localized_key  = CFSTR("generic-ether");
+                                       interfacePrivate->localized_arg1 = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+                               }
+                       }
+
+                       break;
+               case IFT_IEEE1394 :
+                       // Type
+                       interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
+
+                       // Entity
+                       interfacePrivate->entity_type     = kSCEntNetFireWire;
+                       interfacePrivate->entity_hardware = kSCEntNetFireWire;
+
+                       // built-in
+                       interfacePrivate->builtin = isBuiltIn(interface);
+
+                       // sort order
+                       interfacePrivate->sort_order = kSortFireWire;
+
+                       // localized name
+                       if (interfacePrivate->builtin) {
+                               interfacePrivate->localized_key = CFSTR("firewire");
+                       } else {
+                               CFStringRef     slot_name;
+
+                               slot_name = pci_slot(interface, NULL);
+                               if (slot_name != NULL) {
+                                       interfacePrivate->localized_key  = CFSTR("pci-firewire");
+                                       interfacePrivate->localized_arg1 = slot_name;
+                               }
+                       }
+
+                       break;
+               default :
+                       SCPrint(TRUE, stderr, CFSTR("Unknown interface type = %d\n"), ift);
+                       return FALSE;
+       }
+
+       // Device
+       interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOBSDNameKey));
+
+       // Hardware (MAC) address
+       interfacePrivate->address = copyMACAddress(controller_dict);
+
+       return TRUE;
+}
+
+
+static Boolean
+processSerialInterface(mach_port_t                     masterPort,
+                      SCNetworkInterfacePrivateRef     interfacePrivate,
+                      io_registry_entry_t              interface,
+                      CFDictionaryRef                  interface_dict,
+                      io_registry_entry_t              controller,
+                      CFDictionaryRef                  controller_dict,
+                      io_registry_entry_t              bus,
+                      CFDictionaryRef                  bus_dict)
+{
+       CFStringRef             ift;
+       Boolean                 isModem = FALSE;
+       CFStringRef             str;
+       CFTypeRef               val;
+
+       // check if hidden
+       val = IORegistryEntrySearchCFProperty(interface,
+                                             kIOServicePlane,
+                                             CFSTR("HiddenPort"),
+                                             NULL,
+                                             kIORegistryIterateRecursively | kIORegistryIterateParents);
+       if (val != NULL) {
+               CFRelease(val);
+               return FALSE;   // if this interface should not be exposed
+       }
+
+       // Type
+       str = CFDictionaryGetValue(interface_dict, CFSTR(kIOTTYBaseNameKey));
+       if (str == NULL) {
+               return FALSE;
+       }
+
+       /*
+        * From MoreSCF:
+        *
+        * Exclude ports named "irda" because otherwise the IrDA ports on the
+        * original iMac (rev's A through D) show up as serial ports.  Given
+        * that only the rev A actually had an IrDA port, and Mac OS X doesn't
+        * even support it, these ports definitely shouldn't be listed.
+        */
+       if (CFStringCompare(str,
+                           CFSTR("irda"),
+                           kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+               return FALSE;
+       }
+
+       if (IOStringValueHasPrefix(str, CFSTR("irda-ircomm"))) {
+               // IrDA
+               interfacePrivate->interface_type        = kSCNetworkInterfaceTypeIrDA;
+               interfacePrivate->sort_order            = kSortIrDA;
+       } else if (IOStringValueHasPrefix(str, CFSTR("bluetooth"))) {
+               // Bluetooth
+               interfacePrivate->interface_type        = kSCNetworkInterfaceTypeBluetooth;
+               interfacePrivate->sort_order            = kSortBluetooth;
+       } else {
+               // Modem
+               interfacePrivate->interface_type        = kSCNetworkInterfaceTypeModem;
+
+               // DeviceOnHold support
+               val = IORegistryEntrySearchCFProperty(interface,
+                                                     kIOServicePlane,
+                                                     CFSTR(kIODeviceSupportsHoldKey),
+                                                     NULL,
+                                                     kIORegistryIterateRecursively | kIORegistryIterateParents);
+               if (val != NULL) {
+                       uint32_t        supportsHold;
+
+                       if (isA_CFNumber(val) &&
+                           CFNumberGetValue(val, kCFNumberSInt32Type, &supportsHold)) {
+                               interfacePrivate->supportsDeviceOnHold = (supportsHold == 1);
+                       }
+                       CFRelease(val);
+               }
+       }
+
+       // Entity (Type)
+       interfacePrivate->entity_type = kSCEntNetModem;
+
+       // Entity (Hardware)
+       ift = CFDictionaryGetValue(interface_dict, CFSTR(kIOSerialBSDTypeKey));
+       if (!isA_CFString(ift)) {
+               return FALSE;
+       }
+
+       if (CFEqual(ift, CFSTR(kIOSerialBSDModemType))) {
+               // if modem
+               isModem = TRUE;
+               interfacePrivate->entity_hardware = kSCEntNetModem;
+
+               if (CFEqual(str, CFSTR("modem"))) {
+                       interfacePrivate->builtin = TRUE;
+                       interfacePrivate->sort_order = kSortInternalModem;
+               } else if (CFEqual(str, CFSTR("usbmodem"))) {
+                       interfacePrivate->sort_order = kSortUSBModem;
+               } else {
+                       interfacePrivate->sort_order = kSortModem;
+               }
+       } else if (CFEqual(ift, CFSTR(kIOSerialBSDRS232Type))) {
+               // if serial port
+               interfacePrivate->entity_hardware = kSCEntNetModem;
+               interfacePrivate->sort_order = kSortSerialPort;
+       } else {
+               return FALSE;
+       }
+
+       // Entity (Device)
+       interfacePrivate->entity_device = IODictionaryCopyCFStringValue(interface_dict, CFSTR(kIOTTYDeviceKey));
+
+       // localized name
+       if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeIrDA)) {
+               interfacePrivate->localized_key = CFSTR("irda");
+       } else if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeBluetooth)) {
+               interfacePrivate->localized_key = CFSTR("bluetooth");
+       } else {
+               CFStringRef             localized;
+               CFMutableStringRef      port;
+
+               port = CFStringCreateMutableCopy(NULL, 0, str);
+               CFStringLowercase(port, NULL);
+
+               if (!isModem) {
+                       CFStringAppend(port, CFSTR("-port"));
+               }
+
+               localized = CFBundleCopyLocalizedString(bundle,
+                                                       port,
+                                                       port,
+                                                       NETWORKINTERFACE_LOCALIZATIONS);
+               if (localized != NULL) {
+                       if (!CFEqual(port, localized)) {
+                               // if localization available
+                               interfacePrivate->localized_name = localized;
+                       } else {
+                               // if no localization available, use TTY base name
+                               CFRelease(localized);
+                               interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
+                       }
+               } else {
+                       interfacePrivate->localized_name = CFStringCreateCopy(NULL, str);
+               }
+
+               if (!isModem || !CFEqual(str, CFSTR("modem"))) {
+                       CFStringRef     productName;
+
+                       // check if a "Product Name" has been provided
+                       val = IORegistryEntrySearchCFProperty(interface,
+                                                             kIOServicePlane,
+                                                             CFSTR(kIOPropertyProductNameKey),
+                                                             NULL,
+                                                             kIORegistryIterateRecursively | kIORegistryIterateParents);
+                       if (val != NULL) {
+                               productName = IOCopyCFStringValue(val);
+                               CFRelease(val);
+
+                               if (productName != NULL) {
+                                       if (CFStringGetLength(productName) > 0) {
+                                               // if we have a [somewhat reasonable?] product name
+                                               CFRelease(interfacePrivate->localized_name);
+                                               interfacePrivate->localized_name = CFRetain(productName);
+                                       }
+                                       CFRelease(productName);
+                               }
+                       }
+               }
+
+               CFRelease(port);
+       }
+
+       return TRUE;
+}
+
+
+static CFArrayRef
+findMatchingInterfaces(mach_port_t masterPort, CFDictionaryRef matching, processInterface func)
+{
+       CFMutableArrayRef       interfaces;
+       io_registry_entry_t     interface;
+       kern_return_t           kr;
+       io_iterator_t           iterator        = MACH_PORT_NULL;
+
+       kr = IOServiceGetMatchingServices(masterPort, matching, &iterator);
+       if (kr != kIOReturnSuccess) {
+               SCPrint(TRUE, stderr, CFSTR("IOServiceGetMatchingServices() failed, kr = 0x%x\n"), kr);
+               return NULL;
+       }
+
+       interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       while ((interface = IOIteratorNext(iterator)) != MACH_PORT_NULL) {
+               io_registry_entry_t             bus                     = MACH_PORT_NULL;
+               CFMutableDictionaryRef          bus_dict                = NULL;
+               io_registry_entry_t             controller              = MACH_PORT_NULL;
+               CFMutableDictionaryRef          controller_dict         = NULL;
+               SCNetworkInterfacePrivateRef    interfacePrivate        = NULL;
+               CFMutableDictionaryRef          interface_dict          = NULL;
+               io_string_t                     path;
+
+               kr = IORegistryEntryGetPath(interface, kIOServicePlane, path);
+               if (kr != kIOReturnSuccess) {
+                       SCPrint(TRUE, stderr, CFSTR("IORegistryEntryGetPath() failed, kr = 0x%x"), kr);
+                       goto done;
+               }
+
+               kr = IORegistryEntryCreateCFProperties(interface, &interface_dict, NULL, kNilOptions);
+               if (kr != kIOReturnSuccess) {
+                       SCPrint(TRUE, stderr, CFSTR("IORegistryEntryCreateCFProperties() failed, kr = 0x%x\n"), kr);
+                       goto done;
+               }
+
+               /* get the controller node */
+               kr = IORegistryEntryGetParentEntry(interface, kIOServicePlane, &controller);
+               if (kr != KERN_SUCCESS) {
+                       SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+                       goto done;
+               }
+
+               /* get the dictionary associated with the node */
+               kr = IORegistryEntryCreateCFProperties(controller, &controller_dict, NULL, kNilOptions);
+               if (kr != KERN_SUCCESS) {
+                       SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
+                       goto done;
+               }
+
+               /* get the bus node */
+               kr = IORegistryEntryGetParentEntry(controller, kIOServicePlane, &bus);
+               if (kr != KERN_SUCCESS) {
+                       SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryGetParentEntry() failed, kr = 0x%x"), kr);
+                       goto done;
+               }
+
+               /* get the dictionary associated with the node */
+               kr = IORegistryEntryCreateCFProperties(bus, &bus_dict, NULL, kNilOptions);
+               if (kr != KERN_SUCCESS) {
+                       SCLog(TRUE, LOG_INFO, CFSTR("findMatchingInterfaces IORegistryEntryCreateCFProperties() failed, kr = 0x%x"), kr);
+                       goto done;
+               }
+
+               interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, path);
+
+               if ((*func)(masterPort, interfacePrivate, interface, interface_dict, controller, controller_dict, bus, bus_dict)) {
+                       CFArrayAppendValue(interfaces, (SCNetworkInterfaceRef)interfacePrivate);
+               }
+
+               CFRelease(interfacePrivate);
+
+           done:
+
+               if (interface != MACH_PORT_NULL)        IOObjectRelease(interface);
+               if (interface_dict != NULL)             CFRelease(interface_dict);
+
+               if (controller != MACH_PORT_NULL)       IOObjectRelease(controller);
+               if (controller_dict != NULL)            CFRelease(controller_dict);
+
+               if (bus != MACH_PORT_NULL)              IOObjectRelease(bus);
+               if (bus_dict != NULL)                   CFRelease(bus_dict);
+       }
+
+       IOObjectRelease(iterator);
+
+       return interfaces;
+}
+
+
+/* ---------- Bond configuration ---------- */
+
+Boolean
+SCNetworkInterfaceSupportsBonding(SCNetworkInterfaceRef interface)
+{
+       return ((SCNetworkInterfacePrivateRef)interface)->supportsBond;
+}
+
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithBond(BondInterfaceRef bond)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate;
+       CFStringRef                     bond_if;
+
+       bond_if = BondInterfaceGetInterface(bond);
+       if (bond_if == NULL) {
+               return NULL;
+       }
+
+       interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+       if (interfacePrivate == NULL) {
+               return NULL;
+       }
+
+       interfacePrivate->interface_type        = kSCNetworkInterfaceTypeBond;
+       interfacePrivate->entity_type           = kSCEntNetEthernet;
+       interfacePrivate->entity_hardware       = kSCEntNetEthernet;
+       interfacePrivate->entity_device         = CFStringCreateCopy(NULL, bond_if);
+       interfacePrivate->builtin               = TRUE;
+       interfacePrivate->sort_order            = kSortBond;
+
+       interfacePrivate->localized_key         = CFSTR("bond");
+       interfacePrivate->localized_arg1        = CFRetain(interfacePrivate->entity_device);
+
+       return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+static CFArrayRef
+findBondInterfaces(CFStringRef match)
+{
+       CFMutableArrayRef       interfaces      = NULL;
+       CFIndex                 i;
+       CFIndex                 n;
+       BondPreferencesRef      prefs;
+       CFArrayRef              bonds           = NULL;
+
+       prefs = BondPreferencesCreate(NULL);
+       if (prefs == NULL) {
+               // if no bonds
+               return NULL;
+       }
+
+       bonds = BondPreferencesCopyInterfaces(prefs);
+       if (bonds == NULL) {
+               // if no bonds
+               goto done;
+       }
+
+       n = CFArrayGetCount(bonds);
+       if (n == 0) {
+               // if no bonds
+               goto done;
+       }
+
+       interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef   interface;
+               BondInterfaceRef        bond            = CFArrayGetValueAtIndex(bonds, i);
+               CFStringRef             bond_if;
+
+               bond_if = BondInterfaceGetInterface(bond);
+               if (bond_if == NULL) {
+                       continue;
+               }
+
+               if ((match != NULL) && !CFEqual(bond_if, match)) {
+                       continue;
+               }
+
+               interface = SCNetworkInterfaceCreateWithBond(bond);
+               CFArrayAppendValue(interfaces, interface);
+               CFRelease(interface);
+       }
+
+    done :
+
+       if (bonds != NULL)      CFRelease(bonds);
+       CFRelease(prefs);
+       return interfaces;
+}
+
+
+/* ---------- VLAN configuration ---------- */
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithVLAN(VLANInterfaceRef vlan)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate;
+       CFStringRef                     vlan_if;
+
+       vlan_if = VLANInterfaceGetInterface(vlan);
+       if (vlan_if == NULL) {
+               return NULL;
+       }
+
+       interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+       if (interfacePrivate == NULL) {
+               return NULL;
+       }
+
+       interfacePrivate->interface_type        = kSCNetworkInterfaceTypeVLAN;
+       interfacePrivate->entity_type           = kSCEntNetEthernet;
+       interfacePrivate->entity_hardware       = kSCEntNetEthernet;
+       interfacePrivate->entity_device         = CFStringCreateCopy(NULL, vlan_if);
+       interfacePrivate->builtin               = TRUE;
+       interfacePrivate->sort_order            = kSortVLAN;
+
+       interfacePrivate->localized_key         = CFSTR("vlan");
+       interfacePrivate->localized_arg1        = CFRetain(interfacePrivate->entity_device);
+
+       return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+static CFArrayRef
+findVLANInterfaces(CFStringRef match)
+{
+       CFMutableArrayRef       interfaces      = NULL;
+       CFIndex                 i;
+       CFIndex                 n;
+       VLANPreferencesRef      prefs;
+       CFArrayRef              vlans           = NULL;
+
+       prefs = VLANPreferencesCreate(NULL);
+       if (prefs == NULL) {
+               // if no VLANs
+               return NULL;
+       }
+
+       vlans = VLANPreferencesCopyInterfaces(prefs);
+       if (vlans == NULL) {
+               // if no VLANs
+               goto done;
+       }
+
+       n = CFArrayGetCount(vlans);
+       if (n == 0) {
+               // if no VLANs
+               goto done;
+       }
+
+       interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef   interface;
+               VLANInterfaceRef        vlan            = CFArrayGetValueAtIndex(vlans, i);
+               CFStringRef             vlan_if;
+
+               vlan_if = VLANInterfaceGetInterface(vlan);
+               if (vlan_if == NULL) {
+                       continue;
+               }
+
+               if ((match != NULL) && !CFEqual(vlan_if, match)) {
+                       continue;
+               }
+
+               interface = SCNetworkInterfaceCreateWithVLAN(vlan);
+               CFArrayAppendValue(interfaces, interface);
+               CFRelease(interface);
+       }
+
+    done :
+
+       if (vlans != NULL)      CFRelease(vlans);
+       CFRelease(prefs);
+       return interfaces;
+}
+
+
+/* ---------- interface from preferences ---------- */
+
+
+__private_extern__ SCNetworkInterfaceRef
+__SCNetworkInterfaceCreateWithEntity(CFAllocatorRef            allocator,
+                                    CFDictionaryRef            interface_entity,
+                                    SCNetworkServiceRef        service)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = NULL;
+       CFStringRef                     ifDevice;
+       CFStringRef                     ifSubType;
+       CFStringRef                     ifType;
+       static mach_port_t              masterPort              = MACH_PORT_NULL;
+       CFArrayRef                      matching_interfaces     = NULL;
+
+       if (masterPort == MACH_PORT_NULL) {
+               kern_return_t   kr;
+
+               kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+               if (kr != KERN_SUCCESS) {
+                       return NULL;
+               }
+       }
+
+       ifType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceType);
+       if (!isA_CFString(ifType)) {
+               return NULL;
+       }
+
+       ifSubType = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceSubType);
+       if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+               if (!isA_CFString(ifSubType)) {
+                       return NULL;
+               }
+       }
+
+       ifDevice = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceDeviceName);
+
+       if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet) ||
+           CFEqual(ifType, kSCValNetInterfaceTypeFireWire) ||
+           (CFEqual(ifType, kSCValNetInterfaceTypePPP) && CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE))) {
+               char                    bsdName[IFNAMSIZ + 1];
+               CFMutableDictionaryRef  matching;
+
+               if (!isA_CFString(ifDevice)) {
+                       return NULL;
+               }
+
+               if (_SC_cfstring_to_cstring(ifDevice, bsdName, sizeof(bsdName), kCFStringEncodingASCII) == NULL) {
+                       goto done;
+               }
+
+               matching = IOBSDNameMatching(masterPort, 0, bsdName);
+               if (matching == NULL) {
+                       goto done;
+               }
+
+               // note: the "matching" dictionary will be consumed by the following
+               matching_interfaces = findMatchingInterfaces(masterPort, matching, processNetworkInterface);
+
+       } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+               if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
+                       CFDictionaryRef matching;
+                       CFStringRef     match_keys[2];
+                       CFStringRef     match_vals[2];
+
+                       if (!isA_CFString(ifDevice)) {
+                               return NULL;
+                       }
+
+                       match_keys[0] = CFSTR(kIOProviderClassKey);
+                       match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
+
+                       match_keys[1] = CFSTR(kIOTTYDeviceKey);
+                       match_vals[1] = ifDevice;
+
+                       matching = CFDictionaryCreate(NULL,
+                                                     (const void **)match_keys,
+                                                     (const void **)match_vals,
+                                                     sizeof(match_keys)/sizeof(match_keys[0]),
+                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                     &kCFTypeDictionaryValueCallBacks);
+
+                       // note: the "matching" dictionary will be consumed by the following
+                       matching_interfaces = findMatchingInterfaces(masterPort, matching, processSerialInterface);
+
+               } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypeL2TP)) {
+                       interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+                                                                                                              kSCNetworkInterfaceTypeL2TP);
+               } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPTP)) {
+                       interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+                                                                                                              kSCNetworkInterfaceTypePPTP);
+               } else {
+                       // XXX do we allow non-Apple variants of PPP??? XXX
+                       interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+                                                                                                              ifSubType);
+               }
+       } else if (CFEqual(ifType, kSCValNetInterfaceType6to4)) {
+               if (!isA_CFString(ifDevice)) {
+                       return NULL;
+               }
+
+               interfacePrivate = (SCNetworkInterfacePrivateRef)SCNetworkInterfaceCreateWithInterface(kSCNetworkInterfaceIPv4,
+                                                                                                      kSCNetworkInterfaceType6to4);
+       }
+
+       if (matching_interfaces != NULL) {
+               CFIndex n;
+
+               n = CFArrayGetCount(matching_interfaces);
+               switch (n) {
+                       case 0 :
+                               if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
+                                       CFArrayRef      bonds;
+                                       CFArrayRef      vlans;
+
+                                       bonds = findBondInterfaces(ifDevice);
+                                       if (bonds != NULL) {
+                                               if (CFArrayGetCount(bonds) == 1) {
+                                                       interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(bonds, 0);
+                                                       CFRetain(interfacePrivate);
+                                               }
+                                               CFRelease(bonds);
+                                               break;
+                                       }
+
+                                       vlans = findVLANInterfaces(ifDevice);
+                                       if (vlans != NULL) {
+                                               if (CFArrayGetCount(vlans) == 1) {
+                                                       interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(vlans, 0);
+                                                       CFRetain(interfacePrivate);
+                                               }
+                                               CFRelease(vlans);
+                                               break;
+                                       }
+                               }
+                               break;
+                       case 1 :
+                               interfacePrivate = (SCNetworkInterfacePrivateRef)CFArrayGetValueAtIndex(matching_interfaces, 0);
+                               CFRetain(interfacePrivate);
+                               break;
+                       default :
+                               SCPrint(TRUE, stderr, CFSTR("more than one interface matches %@\n"), ifDevice);
+                               if (matching_interfaces != NULL) CFRelease(matching_interfaces);
+                               _SCErrorSet(kSCStatusFailed);
+                               return NULL;
+               }
+               CFRelease(matching_interfaces);
+       }
+
+    done :
+
+       if (interfacePrivate == NULL) {
+               /*
+                * if device not present on this system
+                */
+               interfacePrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+               interfacePrivate->entity_type     = ifType;
+               interfacePrivate->entity_subtype  = ifSubType;
+               interfacePrivate->entity_device   = (ifDevice != NULL) ? CFStringCreateCopy(NULL, ifDevice) : NULL;
+               interfacePrivate->entity_hardware = CFDictionaryGetValue(interface_entity, kSCPropNetInterfaceHardware);
+
+               if (CFEqual(ifType, kSCValNetInterfaceTypeEthernet)) {
+                       if ((interfacePrivate->entity_hardware != NULL) &&
+                           CFEqual(interfacePrivate->entity_hardware, kSCEntNetAirPort)) {
+                               interfacePrivate->interface_type = kSCNetworkInterfaceTypeIEEE80211;
+                       } else {
+                               interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
+                       }
+               } else if (CFEqual(ifType, kSCValNetInterfaceTypeFireWire)) {
+                       interfacePrivate->interface_type = kSCNetworkInterfaceTypeFireWire;
+               } else if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+                       if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPoE)) {
+                               interfacePrivate->interface_type = kSCNetworkInterfaceTypeEthernet;
+                       } else if (CFEqual(ifSubType, kSCValNetInterfaceSubTypePPPSerial)) {
+                               if        (CFStringHasPrefix(ifDevice, CFSTR("irda"))) {
+                                       interfacePrivate->interface_type = kSCNetworkInterfaceTypeIrDA;
+                               } else if (CFStringHasPrefix(ifDevice, CFSTR("Bluetooth"))) {
+                                       interfacePrivate->interface_type = kSCNetworkInterfaceTypeBluetooth;
+                               } else {
+                                       interfacePrivate->interface_type = kSCNetworkInterfaceTypeModem;
+                               }
+                       } else {
+                               // PPTP, L2TP, ...
+                               CFRelease(interfacePrivate);
+                               interfacePrivate = (SCNetworkInterfacePrivateRef)kSCNetworkInterfaceIPv4;
+                               CFRetain(interfacePrivate);
+                       }
+               } else {
+                       // unknown interface type
+                       CFRelease(interfacePrivate);
+                       interfacePrivate = NULL;
+               }
+       }
+
+       if ((interfacePrivate != NULL) && (service != NULL)) {
+               interfacePrivate->service = service;
+       }
+
+       if (CFEqual(ifType, kSCValNetInterfaceTypePPP)) {
+               SCNetworkInterfaceRef   parent;
+
+               parent = SCNetworkInterfaceCreateWithInterface((SCNetworkInterfaceRef)interfacePrivate,
+                                                              kSCNetworkInterfaceTypePPP);
+               CFRelease(interfacePrivate);
+               interfacePrivate = (SCNetworkInterfacePrivateRef)parent;
+       }
+
+       return (SCNetworkInterfaceRef)interfacePrivate;
+}
+
+
+/* ---------- helper functions ---------- */
+
+
+static CFIndex
+findConfiguration(CFStringRef interface_type)
+{
+       CFIndex i;
+
+       for (i = 0; i < sizeof(configurations)/sizeof(configurations[0]); i++) {
+               if (CFEqual(interface_type, *configurations[i].interface_type)) {
+                       return i;
+               }
+       }
+
+       return kCFNotFound;
+}
+
+
+static CFArrayRef
+copyConfigurationPaths(SCNetworkInterfacePrivateRef interfacePrivate)
+{
+       CFMutableArrayRef               array           = NULL;
+       CFIndex                         interfaceIndex;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate;
+
+       interfaceIndex = findConfiguration(interfacePrivate->interface_type);
+       if (interfaceIndex == kCFNotFound) {
+               // if unknown interface type
+               return NULL;
+       }
+
+       servicePrivate = (SCNetworkServicePrivateRef)interfacePrivate->service;
+       if (servicePrivate == NULL) {
+               // if not associated with a service (yet)
+               return NULL;
+       }
+
+       array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       if (configurations[interfaceIndex].per_interface_config) {
+               CFIndex         i;
+               CFIndex         n;
+               CFArrayRef      sets;
+
+               /*
+                * per-interface configuration preferences
+                *
+                * 1. look for all sets which contain the associated service
+                * 2. add a per-set path for the interface configuration for
+                *    each set.
+                */
+
+               sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+               n = (sets != NULL) ? CFArrayGetCount(sets) : 0;
+
+               for (i = 0; i < n; i++) {
+                       CFArrayRef      services;
+                       SCNetworkSetRef set;
+
+                       set = CFArrayGetValueAtIndex(sets, i);
+                       services = SCNetworkSetCopyServices(set);
+                       if (CFArrayContainsValue(services,
+                                                CFRangeMake(0, CFArrayGetCount(services)),
+                                                interfacePrivate->service)) {
+                               path = SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(NULL,                                // allocator
+                                                                                          SCNetworkSetGetSetID(set),           // set
+                                                                                          interfacePrivate->entity_device,     // service
+                                                                                          interfacePrivate->entity_type);      // entity
+                               CFArrayAppendValue(array, path);
+                               CFRelease(path);
+                       }
+                       CFRelease(services);
+               }
+
+               if (CFArrayGetCount(array) == 0) {
+                       CFRelease(array);
+                       array = NULL;
+               }
+
+               CFRelease(sets);
+       } else {
+               // per-service configuration preferences
+               path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                                     // allocator
+                                                                     servicePrivate->serviceID,                // service
+                                                                     interfacePrivate->entity_type);           // entity
+               CFArrayAppendValue(array, path);
+               CFRelease(path);
+       }
+
+       return array;
+}
+
+
+/* ---------- SCNetworkInterface APIs ---------- */
+
+
+CFArrayRef /* of SCNetworkInterfaceRef's */
+SCNetworkInterfaceCopyAll()
+{
+       CFMutableArrayRef       all_interfaces;
+       static mach_port_t      masterPort      = MACH_PORT_NULL;
+       CFDictionaryRef         matching;
+       CFStringRef             match_keys[2];
+       CFStringRef             match_vals[2];
+       CFArrayRef              new_interfaces;
+
+       if (masterPort == MACH_PORT_NULL) {
+               kern_return_t   kr;
+
+               kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+               if (kr != KERN_SUCCESS) {
+                       return NULL;
+               }
+       }
+
+       all_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       // get Ethernet, Firewire, and AirPort interfaces
+
+       matching = IOServiceMatching(kIONetworkInterfaceClass);
+       new_interfaces = findMatchingInterfaces(masterPort, matching, processNetworkInterface);
+       if (new_interfaces != NULL) {
+               CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+               CFRelease(new_interfaces);
+       }
+
+       // get Modem interfaces
+
+       match_keys[0] = CFSTR(kIOProviderClassKey);
+       match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
+
+       match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
+       match_vals[1] = CFSTR(kIOSerialBSDModemType);
+
+       matching = CFDictionaryCreate(NULL,
+                                     (const void **)match_keys,
+                                     (const void **)match_vals,
+                                     sizeof(match_keys)/sizeof(match_keys[0]),
+                                     &kCFTypeDictionaryKeyCallBacks,
+                                     &kCFTypeDictionaryValueCallBacks);
+       new_interfaces = findMatchingInterfaces(masterPort, matching, processSerialInterface);
+       if (new_interfaces != NULL) {
+               CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+               CFRelease(new_interfaces);
+       }
+
+       // get serial (RS232) interfaces
+
+       match_keys[0] = CFSTR(kIOProviderClassKey);
+       match_vals[0] = CFSTR(kIOSerialBSDServiceValue);
+
+       match_keys[1] = CFSTR(kIOSerialBSDTypeKey);
+       match_vals[1] = CFSTR(kIOSerialBSDRS232Type);
+
+       matching = CFDictionaryCreate(NULL,
+                                     (const void **)match_keys,
+                                     (const void **)match_vals,
+                                     sizeof(match_keys)/sizeof(match_keys[0]),
+                                     &kCFTypeDictionaryKeyCallBacks,
+                                     &kCFTypeDictionaryValueCallBacks);
+       new_interfaces = findMatchingInterfaces(masterPort, matching, processSerialInterface);
+       if (new_interfaces != NULL) {
+               CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+               CFRelease(new_interfaces);
+       }
+
+       new_interfaces = findBondInterfaces(NULL);
+       if (new_interfaces != NULL) {
+               CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+               CFRelease(new_interfaces);
+       }
+
+       new_interfaces = findVLANInterfaces(NULL);
+       if (new_interfaces != NULL) {
+               CFArrayAppendArray(all_interfaces, new_interfaces, CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+               CFRelease(new_interfaces);
+       }
+
+       sort_interfaces(all_interfaces);
+
+       return all_interfaces;
+}
+
+
+CFArrayRef /* of kSCNetworkInterfaceTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedInterfaceTypes(SCNetworkInterfaceRef interface)
+{
+       CFIndex                         i;
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       if (interfacePrivate->supported_interface_types != NULL) {
+               goto done;
+       }
+
+       /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       i = findConfiguration(interfacePrivate->interface_type);
+       if (i != kCFNotFound) {
+               if (configurations[i].supported_interfaces != doNone) {
+                       interfacePrivate->supported_interface_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                       if (configurations[i].supported_interfaces & do6to4) {
+                               CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceType6to4);
+                       }
+                       if (configurations[i].supported_interfaces & doL2TP) {
+                               CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypeL2TP);
+                       }
+                       if (configurations[i].supported_interfaces & doPPP) {
+                               CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPP);
+                       }
+                       if (configurations[i].supported_interfaces & doPPTP) {
+                               CFArrayAppendValue(interfacePrivate->supported_interface_types, kSCNetworkInterfaceTypePPTP);
+                       }
+               }
+       }
+
+    done :
+
+       return interfacePrivate->supported_interface_types;
+}
+
+
+CFArrayRef /* of kSCNetworkProtocolTypeXXX CFStringRef's */
+SCNetworkInterfaceGetSupportedProtocolTypes(SCNetworkInterfaceRef interface)
+{
+       CFIndex                         i;
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       if (interfacePrivate->supported_protocol_types != NULL) {
+               goto done;
+       }
+
+       /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       i = findConfiguration(interfacePrivate->interface_type);
+       if (i != kCFNotFound) {
+               if (configurations[i].supported_protocols != doNone) {
+                       interfacePrivate->supported_protocol_types = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                       if (configurations[i].supported_protocols & doAppleTalk) {
+                               CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeAppleTalk);
+                       }
+                       if (configurations[i].supported_protocols & doDNS) {
+                               CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeDNS);
+                       }
+                       if (configurations[i].supported_protocols & doIPv4) {
+                               CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv4);
+                       }
+                       if (configurations[i].supported_protocols & doIPv6) {
+                               CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeIPv6);
+                       }
+                       if (configurations[i].supported_protocols & doProxies) {
+                               CFArrayAppendValue(interfacePrivate->supported_protocol_types, kSCNetworkProtocolTypeProxies);
+                       }
+               }
+       }
+
+    done :
+
+       return interfacePrivate->supported_protocol_types;
+}
+
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceCreateWithInterface(SCNetworkInterfaceRef child, CFStringRef interfaceType)
+{
+       SCNetworkInterfacePrivateRef    childPrivate    = (SCNetworkInterfacePrivateRef)child;
+       CFIndex                         childIndex;
+       SCNetworkInterfacePrivateRef    parentPrivate;
+
+       /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       childIndex = findConfiguration(childPrivate->interface_type);
+
+       parentPrivate = __SCNetworkInterfaceCreatePrivate(NULL, child, childPrivate->service, NULL);
+       if (parentPrivate == NULL) {
+               _SCErrorSet(kSCStatusFailed);
+               return NULL;
+       }
+
+       if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
+               parentPrivate->interface_type = kSCNetworkInterfaceTypePPP;
+               parentPrivate->entity_type    = kSCEntNetPPP;
+
+               // entity subtype
+               if (childIndex != kCFNotFound) {
+                       if (configurations[childIndex].ppp_subtype != NULL) {
+                               parentPrivate->entity_subtype = *configurations[childIndex].ppp_subtype;
+                       } else {
+                               // sorry, the child interface does not support PPP
+                               goto fail;
+                       }
+               } else {
+                       // if the child's interface type not known, use the child entities "Type"
+                       parentPrivate->entity_subtype = childPrivate->entity_type;
+               }
+
+               if (childPrivate->entity_device != NULL) {
+                       parentPrivate->entity_device = CFStringCreateCopy(NULL, childPrivate->entity_device);
+               }
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) {
+               if ((childIndex == kCFNotFound) ||
+                   ((configurations[childIndex].supported_interfaces & doL2TP) != doL2TP)) {
+                       // if the child interface does not support L2TP
+                       goto fail;
+               }
+               parentPrivate->interface_type = kSCNetworkInterfaceTypeL2TP;
+               parentPrivate->entity_type    = kSCValNetInterfaceSubTypeL2TP;  // interface config goes into "L2TP"
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) {
+               if ((childIndex == kCFNotFound) ||
+                   ((configurations[childIndex].supported_interfaces & doPPTP) != doPPTP)) {
+                       // if the child interface does not support PPTP
+                       goto fail;
+               }
+               parentPrivate->interface_type = kSCNetworkInterfaceTypePPTP;
+               parentPrivate->entity_type    = kSCValNetInterfaceSubTypePPTP;  // interface config goes into "PPTP"
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceType6to4)) {
+               if ((childIndex == kCFNotFound) ||
+                   ((configurations[childIndex].supported_interfaces & do6to4) != do6to4)) {
+                       // if the child interface does not support 6to4
+                       goto fail;
+               }
+
+               parentPrivate->interface_type = kSCNetworkInterfaceType6to4;
+               parentPrivate->entity_type    = kSCEntNet6to4;
+               parentPrivate->entity_device  = CFRetain(CFSTR("stf0"));
+               CFRetain(parentPrivate->entity_device);
+       } else {
+               // unknown interface type
+               goto fail;
+       }
+
+       parentPrivate->entity_hardware = childPrivate->entity_hardware;
+       parentPrivate->sort_order = childPrivate->sort_order;
+
+       return (SCNetworkInterfaceRef)parentPrivate;
+
+    fail :
+
+       CFRelease(parentPrivate);
+       _SCErrorSet(kSCStatusInvalidArgument);
+       return NULL;
+}
+
+
+static CFDictionaryRef
+__SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface, Boolean okToHold)
+{
+       CFDictionaryRef                 config                  = NULL;
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+       CFArrayRef                      paths;
+
+       /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       paths = copyConfigurationPaths(interfacePrivate);
+       if (paths != NULL) {
+               CFStringRef                     path;
+               SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)interfacePrivate->service;
+
+               path = CFArrayGetValueAtIndex(paths, 0);
+               config = __getPrefsConfiguration(servicePrivate->prefs, path);
+
+               CFRelease(paths);
+       } else if (okToHold) {
+               config = interfacePrivate->unsaved;
+       }
+
+       return config;
+}
+
+
+CFDictionaryRef
+SCNetworkInterfaceGetConfiguration(SCNetworkInterfaceRef interface)
+{
+       return __SCNetworkInterfaceGetConfiguration(interface, FALSE);
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetBSDName(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       if (interfacePrivate->interface != NULL) {
+               return NULL;
+       }
+
+       return interfacePrivate->entity_device;
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetHardwareAddressString(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       return interfacePrivate->address;
+}
+
+SCNetworkInterfaceRef
+SCNetworkInterfaceGetInterface(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       return interfacePrivate->interface;
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetInterfaceType(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       return interfacePrivate->interface_type;
+}
+
+
+CFStringRef
+SCNetworkInterfaceGetLocalizedDisplayName(SCNetworkInterfaceRef interface)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+
+       if (interfacePrivate->localized_name == NULL) {
+               CFStringRef             child   = NULL;
+               CFMutableStringRef      local   = NULL;
+
+               pthread_once(&initialized, __SCNetworkInterfaceInitialize);     /* initialize runtime */
+
+               if (interfacePrivate->interface != NULL) {
+                       child = SCNetworkInterfaceGetLocalizedDisplayName(interfacePrivate->interface);
+               }
+
+               if (interfacePrivate->localized_key != NULL) {
+                       CFStringRef     fmt;
+
+                       fmt = CFBundleCopyLocalizedString(bundle,
+                                                         interfacePrivate->localized_key,
+                                                         interfacePrivate->localized_key,
+                                                         NETWORKINTERFACE_LOCALIZATIONS);
+                       if (fmt != NULL) {
+                               local = CFStringCreateMutable(NULL, 0);
+                               CFStringAppendFormat(local,
+                                                    NULL,
+                                                    fmt,
+                                                    interfacePrivate->localized_arg1,
+                                                    interfacePrivate->localized_arg2);
+                               CFRelease(fmt);
+                       }
+               }
+
+               if (local == NULL) {
+                       // create (non-)localized name based on the interface type
+                       local = CFStringCreateMutableCopy(NULL, 0, interfacePrivate->interface_type);
+
+                       // ... and, if this is a leaf node, the interface device
+                       if ((interfacePrivate->entity_device != NULL) && (child == NULL)) {
+                               CFStringAppendFormat(local, NULL, CFSTR(" (%@)"), interfacePrivate->entity_device);
+                       }
+               }
+
+               if (child == NULL) {
+                       // no child, show just this interfaces localized name
+                       interfacePrivate->localized_name = CFStringCreateCopy(NULL, local);
+               } else {
+                       // show localized interface name layered over child
+                       interfacePrivate->localized_name = CFStringCreateWithFormat(NULL,
+                                                                                   NULL,
+                                                                                   CFSTR("%@ --> %@"),
+                                                                                   local,
+                                                                                   child);
+               }
+               CFRelease(local);
+       }
+
+       return interfacePrivate->localized_name;
+}
+
+
+CFTypeID
+SCNetworkInterfaceGetTypeID(void)
+{
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);     /* initialize runtime */
+       return __kSCNetworkInterfaceTypeID;
+}
+
+
+__private_extern__ Boolean
+__SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config, Boolean okToHold)
+{
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+       Boolean                         ok                      = FALSE;
+       CFArrayRef                      paths;
+
+       /* initialize runtime (and kSCNetworkInterfaceIPv4) */
+       pthread_once(&initialized, __SCNetworkInterfaceInitialize);
+
+       paths = copyConfigurationPaths(interfacePrivate);
+       if (paths != NULL) {
+               CFIndex                         i;
+               CFIndex                         n;
+               SCPreferencesRef                prefs;
+               SCNetworkServicePrivateRef      servicePrivate;
+
+               servicePrivate  = (SCNetworkServicePrivateRef)interfacePrivate->service;
+               prefs = servicePrivate->prefs;
+
+               n = CFArrayGetCount(paths);
+               for (i = 0; i < n; i++) {
+                       CFStringRef     path;
+
+                       path = CFArrayGetValueAtIndex(paths, i);
+                       ok = __setPrefsConfiguration(prefs, path, config, FALSE);
+                       if (!ok) {
+                               break;
+                       }
+               }
+
+               CFRelease(paths);
+       } else if (okToHold) {
+               interfacePrivate->unsaved = config;
+               ok = TRUE;
+       } else {
+               _SCErrorSet(kSCStatusNoKey);
+       }
+
+       return ok;
+}
+
+
+Boolean
+SCNetworkInterfaceSetConfiguration(SCNetworkInterfaceRef interface, CFDictionaryRef config)
+{
+       return __SCNetworkInterfaceSetConfiguration(interface, config, FALSE);
+}
+
+
+/* ---------- SCNetworkInterface internal SPIs ---------- */
+
+
+__private_extern__ SCNetworkInterfacePrivateRef
+__SCNetworkInterfaceCreateCopy(CFAllocatorRef          allocator,
+                              SCNetworkInterfaceRef    interface,
+                              SCNetworkServiceRef      service)
+{
+       SCNetworkInterfacePrivateRef            oldPrivate      = (SCNetworkInterfacePrivateRef)interface;
+       SCNetworkInterfacePrivateRef            newPrivate;
+
+       newPrivate = __SCNetworkInterfaceCreatePrivate(NULL, NULL, NULL, NULL);
+       newPrivate->interface_type              = CFRetain(oldPrivate->interface_type);
+       if (oldPrivate->interface != NULL) {
+               newPrivate->interface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL,                     // allocator
+                                                                                             oldPrivate->interface,    // interface
+                                                                                             service);                 // [new] service
+       }
+       newPrivate->localized_name              = (oldPrivate->localized_name != NULL) ? CFRetain(oldPrivate->localized_name) : NULL;
+       newPrivate->service                     = service;
+       newPrivate->unsaved                     = (oldPrivate->unsaved != NULL) ? CFRetain(oldPrivate->unsaved) : NULL;
+       newPrivate->entity_device               = (oldPrivate->entity_device != NULL) ? CFRetain(oldPrivate->entity_device) : NULL;
+       newPrivate->entity_hardware             = CFRetain(oldPrivate->entity_hardware);
+       newPrivate->entity_type                 = oldPrivate->entity_type;
+       newPrivate->entity_subtype              = oldPrivate->entity_subtype;
+       if (oldPrivate->supported_interface_types != NULL) {
+               newPrivate->supported_interface_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_interface_types);
+       }
+       if (oldPrivate->supported_protocol_types != NULL) {
+               newPrivate->supported_protocol_types = CFArrayCreateMutableCopy(NULL, 0, oldPrivate->supported_protocol_types);
+       }
+       newPrivate->address                     = (oldPrivate->address != NULL) ? CFRetain(oldPrivate->address) : NULL;
+       newPrivate->builtin                     = oldPrivate->builtin;
+       newPrivate->path                        = (oldPrivate->path != NULL) ? CFRetain(oldPrivate->path) : NULL;
+       newPrivate->location                    = (oldPrivate->location != NULL) ? CFRetain(oldPrivate->location) : NULL;
+       newPrivate->supportsDeviceOnHold        = oldPrivate->supportsDeviceOnHold;
+       newPrivate->supportsBond                = oldPrivate->supportsBond;
+       newPrivate->supportsVLAN                = oldPrivate->supportsVLAN;
+       newPrivate->sort_order                  = oldPrivate->sort_order;
+
+       return newPrivate;
+}
+
+
+__private_extern__ CFArrayRef
+__SCNetworkInterfaceCopyDeepConfiguration(SCNetworkInterfaceRef interface)
+{
+       CFDictionaryRef         config;
+       CFMutableArrayRef       configs;
+
+       configs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       while (interface != NULL) {
+               config = __SCNetworkInterfaceGetConfiguration(interface, TRUE);
+               CFArrayAppendValue(configs,
+                                  (config != NULL) ? config : (CFDictionaryRef)kCFNull);
+               interface = SCNetworkInterfaceGetInterface(interface);
+       }
+
+       return configs;
+}
+
+
+__private_extern__ void
+__SCNetworkInterfaceSetDeepConfiguration(SCNetworkInterfaceRef interface, CFArrayRef configs)
+{
+       CFIndex         i;
+
+       for (i = 0; interface != NULL; i++) {
+               CFDictionaryRef config;
+
+               config = (configs != NULL) ? CFArrayGetValueAtIndex(configs, i) : NULL;
+               if (!isA_CFDictionary(config) || (CFDictionaryGetCount(config) == 0)) {
+                       config = NULL;
+               }
+
+               (void) __SCNetworkInterfaceSetConfiguration(interface, config, TRUE);
+               interface = SCNetworkInterfaceGetInterface(interface);
+       }
+
+       return;
+}
diff --git a/SystemConfiguration.fproj/SCNetworkProtocol.c b/SystemConfiguration.fproj/SCNetworkProtocol.c
new file mode 100644 (file)
index 0000000..1c6c73a
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "SCNetworkConfiguration.h"
+#include "SCNetworkConfigurationInternal.h"
+
+#include <pthread.h>
+
+
+static CFStringRef     __SCNetworkProtocolCopyDescription      (CFTypeRef cf);
+static void            __SCNetworkProtocolDeallocate           (CFTypeRef cf);
+static Boolean         __SCNetworkProtocolEqual                (CFTypeRef cf1, CFTypeRef cf2);
+
+
+const CFStringRef kSCNetworkProtocolTypeAppleTalk       = CFSTR("AppleTalk");
+const CFStringRef kSCNetworkProtocolTypeDNS            = CFSTR("DNS");
+const CFStringRef kSCNetworkProtocolTypeIPv4           = CFSTR("IPv4");
+const CFStringRef kSCNetworkProtocolTypeIPv6           = CFSTR("IPv6");
+const CFStringRef kSCNetworkProtocolTypeProxies                = CFSTR("Proxies");
+
+
+static CFTypeID __kSCNetworkProtocolTypeID     = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkProtocolClass = {
+       0,                                      // version
+       "SCNetworkProtocol",                    // className
+       NULL,                                   // init
+       NULL,                                   // copy
+       __SCNetworkProtocolDeallocate,          // dealloc
+       __SCNetworkProtocolEqual,               // equal
+       NULL,                                   // hash
+       NULL,                                   // copyFormattingDesc
+       __SCNetworkProtocolCopyDescription      // copyDebugDesc
+};
+
+
+static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkProtocol(CFTypeRef obj)
+{
+       return (isA_CFType(obj, SCNetworkProtocolGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkProtocolCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef                  allocator       = CFGetAllocator(cf);
+       CFMutableStringRef              result;
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkProtocol %p [%p]> { "), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("id=%@"), protocolPrivate->entityID);
+       CFStringAppendFormat(result, NULL, CFSTR(", service=%@"), protocolPrivate->service);
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__SCNetworkProtocolDeallocate(CFTypeRef cf)
+{
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
+
+       /* release resources */
+       CFRelease(protocolPrivate->entityID);
+
+       return;
+}
+
+
+static Boolean
+__SCNetworkProtocolEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+       SCNetworkProtocolPrivateRef     p1      = (SCNetworkProtocolPrivateRef)cf1;
+       SCNetworkProtocolPrivateRef     p2      = (SCNetworkProtocolPrivateRef)cf2;
+
+       if (p1 == p2)
+               return TRUE;
+
+       if (!CFEqual(p1->entityID, p2->entityID))
+               return FALSE;   // if not the same protocol type
+
+       if (p1->service == p2->service)
+               return TRUE;    // if both point to the same service
+
+       if ((p1->service != NULL) && (p2->service != NULL) && CFEqual(p1->service, p2->service))
+               return TRUE;    // if both effectively point to the same service
+
+       return FALSE;
+}
+
+
+static void
+__SCNetworkProtocolInitialize(void)
+{
+       __kSCNetworkProtocolTypeID = _CFRuntimeRegisterClass(&__SCNetworkProtocolClass);
+       return;
+}
+
+
+__private_extern__ SCNetworkProtocolPrivateRef
+__SCNetworkProtocolCreatePrivate(CFAllocatorRef                allocator,
+                                CFStringRef            entityID,
+                                SCNetworkServiceRef    service)
+{
+       SCNetworkProtocolPrivateRef             protocolPrivate;
+       uint32_t                                size;
+
+       /* initialize runtime */
+       pthread_once(&initialized, __SCNetworkProtocolInitialize);
+
+       /* allocate target */
+       size           = sizeof(SCNetworkProtocolPrivate) - sizeof(CFRuntimeBase);
+       protocolPrivate = (SCNetworkProtocolPrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                             __kSCNetworkProtocolTypeID,
+                                                                             size,
+                                                                             NULL);
+       if (protocolPrivate == NULL) {
+               return NULL;
+       }
+
+       protocolPrivate->entityID       = CFStringCreateCopy(NULL, entityID);
+       protocolPrivate->service        = service;
+
+       return protocolPrivate;
+}
+
+
+__private_extern__ Boolean
+__SCNetworkProtocolIsValidType(CFStringRef protocolType)
+{
+       int                             i;
+       static const CFStringRef        *valid_types[]   = {
+               &kSCNetworkProtocolTypeAppleTalk,
+               &kSCNetworkProtocolTypeDNS,
+               &kSCNetworkProtocolTypeIPv4,
+               &kSCNetworkProtocolTypeIPv6,
+               &kSCNetworkProtocolTypeProxies
+       };
+
+       for (i = 0; i < sizeof(valid_types)/sizeof(valid_types[0]); i++) {
+               if (CFEqual(protocolType, *valid_types[i])) {
+                       // if known/valid protocol type
+                       return TRUE;
+               }
+       }
+
+       if (CFStringFindWithOptions(protocolType,
+                                   CFSTR("."),
+                                   CFRangeMake(0, CFStringGetLength(protocolType)),
+                                   0,
+                                   NULL)) {
+               // if user-defined protocol type (e.g. com.apple.myProtocol)
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+static CFStringRef
+copyProtocolConfigurationPath(SCNetworkProtocolPrivateRef protocolPrivate)
+{
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate;
+
+       servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             protocolPrivate->entityID);       // entity
+       return path;
+}
+
+
+/* ---------- SCNetworkProtocol APIs ---------- */
+
+
+CFTypeID
+SCNetworkProtocolGetTypeID()
+{
+       pthread_once(&initialized, __SCNetworkProtocolInitialize);      /* initialize runtime */
+       return __kSCNetworkProtocolTypeID;
+}
+
+
+CFDictionaryRef
+SCNetworkProtocolGetConfiguration(SCNetworkProtocolRef protocol)
+{
+       CFDictionaryRef                 config;
+       CFStringRef                     path;
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+       path = copyProtocolConfigurationPath(protocolPrivate);
+       config = __getPrefsConfiguration(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       return config;
+}
+
+
+Boolean
+SCNetworkProtocolGetEnabled(SCNetworkProtocolRef protocol)
+{
+       Boolean                         enabled;
+       CFStringRef                     path;
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+       path = copyProtocolConfigurationPath(protocolPrivate);
+       enabled = __getPrefsEnabled(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       return enabled;
+}
+
+
+CFStringRef
+SCNetworkProtocolGetProtocolType(SCNetworkProtocolRef protocol)
+{
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+
+       return protocolPrivate->entityID;
+}
+
+
+Boolean
+SCNetworkProtocolSetConfiguration(SCNetworkProtocolRef protocol, CFDictionaryRef config)
+{
+       Boolean                         ok;
+       CFStringRef                     path;
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+       path = copyProtocolConfigurationPath(protocolPrivate);
+       ok = __setPrefsConfiguration(servicePrivate->prefs, path, config, TRUE);
+       CFRelease(path);
+
+       return ok;
+}
+
+
+Boolean
+SCNetworkProtocolSetEnabled(SCNetworkProtocolRef protocol, Boolean enabled)
+{
+       Boolean                         ok;
+       CFStringRef                     path;
+       SCNetworkProtocolPrivateRef     protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)protocolPrivate->service;
+
+       path = copyProtocolConfigurationPath(protocolPrivate);
+       ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
+       CFRelease(path);
+
+       return ok;
+}
index c838bc71167ae4c313a3070ddef62e6f877c5946..a0d0a5408976a732242ff18a384f89a72a781ce5 100644 (file)
@@ -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@
  *
  * @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.
  * 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,
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 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
  *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
  * Modification History
  *
+ * March 31, 2004              Allan Nathanson <ajn@apple.com>
+ * - use [SC] DNS configuration information
+ *
  * January 19, 2003            Allan Nathanson <ajn@apple.com>
  * - add advanced reachability APIs
  */
  * January 19, 2003            Allan Nathanson <ajn@apple.com>
  * - add advanced reachability APIs
  */
 #include <CoreFoundation/CFRuntime.h>
 #include <pthread.h>
 
 #include <CoreFoundation/CFRuntime.h>
 #include <pthread.h>
 
+#include <notify.h>
+#include <dnsinfo.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <arpa/nameser.h>
 #include <netdb.h>
 #include <netdb_async.h>
 #include <resolv.h>
 #include <netdb.h>
 #include <netdb_async.h>
 #include <resolv.h>
@@ -54,7 +58,7 @@
 #define s6_addr16 __u6_addr.__u6_addr16
 #endif
 
 #define s6_addr16 __u6_addr.__u6_addr16
 #endif
 
-#include "ppp.h"
+#include <ppp/ppp_msg.h>
 
 
 #define kSCNetworkFlagsFirstResolvePending     (1<<31)
 
 
 #define kSCNetworkFlagsFirstResolvePending     (1<<31)
@@ -104,9 +108,11 @@ typedef struct {
        SCNetworkReachabilityContext    rlsContext;
        CFMutableArrayRef               rlList;
 
        SCNetworkReachabilityContext    rlsContext;
        CFMutableArrayRef               rlList;
 
-       /* async DNS query info */
+       /* [async] DNS query info */
+       Boolean                         haveDNS;
        CFMachPortRef                   dnsPort;
        CFRunLoopSourceRef              dnsRLS;
        CFMachPortRef                   dnsPort;
        CFRunLoopSourceRef              dnsRLS;
+       struct timeval                  dnsQueryStart;
 
 } SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef;
 
 
 } SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef;
 
@@ -128,10 +134,12 @@ static const CFRuntimeClass __SCNetworkReachabilityClass = {
 
 
 static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
 
 
 static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
-static Boolean                 needDNS         = TRUE;
 
 
 
 
-/* host "something has changed" notifications */
+/*
+ * host "something has changed" notifications
+ */
+
 static pthread_mutex_t         hn_lock         = PTHREAD_MUTEX_INITIALIZER;
 static SCDynamicStoreRef       hn_store        = NULL;
 static CFRunLoopSourceRef      hn_storeRLS     = NULL;
 static 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 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
 
 
 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;
        }
 
                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;
        }
 
                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;
 }
 
        return;
 }
 
@@ -312,7 +211,7 @@ updatePPPStatus(SCDynamicStoreRef           *storeP,
        CFIndex                 n;
        CFStringRef             ppp_if;
        int                     sc_status       = kSCStatusReachabilityUnknown;
        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;
 
        const void *            values_q[N_QUICK];
        const void **           values  = values_q;
 
@@ -327,10 +226,10 @@ updatePPPStatus(SCDynamicStoreRef         *storeP,
                        goto done;
        }
 
                        goto done;
        }
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, 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;
                }
        }
                        goto done;
                }
        }
@@ -364,7 +263,7 @@ updatePPPStatus(SCDynamicStoreRef           *storeP,
                dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
                CFRelease(patterns);
        }
                dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
                CFRelease(patterns);
        }
-       if (!dict) {
+       if (dict == NULL) {
                /* if we could not access the dynamic store */
                goto done;
        }
                /* if we could not access the dynamic store */
                goto done;
        }
@@ -502,16 +401,16 @@ updatePPPStatus(SCDynamicStoreRef         *storeP,
 
     done :
 
 
     done :
 
-       if (dict)       CFRelease(dict);
-       if (storeP)     *storeP = store;
+       if (dict != NULL)       CFRelease(dict);
+       if (storeP != NULL)     *storeP = store;
        return sc_status;
 }
 
 
 static int
 updatePPPAvailable(SCDynamicStoreRef           *storeP,
        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;
 {
        CFDictionaryRef         dict            = NULL;
        CFStringRef             entity;
@@ -520,25 +419,29 @@ updatePPPAvailable(SCDynamicStoreRef              *storeP,
        const void **           keys            = keys_q;
        CFIndex                 n;
        int                     sc_status       = kSCStatusReachabilityUnknown;
        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;
 
        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);
                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;
                }
        }
                        goto done;
                }
        }
@@ -566,7 +469,7 @@ updatePPPAvailable(SCDynamicStoreRef                *storeP,
                dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
                CFRelease(patterns);
        }
                dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
                CFRelease(patterns);
        }
-       if (!dict) {
+       if (dict == NULL) {
                /* if we could not access the dynamic store */
                goto done;
        }
                /* if we could not access the dynamic store */
                goto done;
        }
@@ -667,8 +570,8 @@ updatePPPAvailable(SCDynamicStoreRef                *storeP,
 
     done :
 
 
     done :
 
-       if (dict)       CFRelease(dict);
-       if (storeP)     *storeP = store;
+       if (dict != NULL)       CFRelease(dict);
+       if (storeP != NULL)     *storeP = store;
        return sc_status;
 }
 
        return sc_status;
 }
 
@@ -717,7 +620,7 @@ checkAddress(SCDynamicStoreRef              *storeP,
        int                     sc_status       = kSCStatusReachabilityUnknown;
        struct sockaddr_dl      *sdl;
        int                     seq             = (int)pthread_self();
        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)
        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
 
        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) {
        }
 
        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;
                                SCLog(TRUE, LOG_INFO, CFSTR("checkAddress(%s)"), buf);
                        }
                        break;
@@ -749,16 +657,6 @@ checkAddress(SCDynamicStoreRef             *storeP,
                        goto done;
        }
 
                        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;
        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) {
 
        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);
                }
        }
                        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 */
        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 */
        }
 
        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 */
        }
 
        /* 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);
                                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;
                                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;
        }
 
                *flags |= kSCNetworkFlagsIsDirect;
        }
 
@@ -973,7 +882,7 @@ checkAddress(SCDynamicStoreRef              *storeP,
              if_name,
              (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ);
 
              if_name,
              (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ);
 
-       if (if_index) {
+       if (if_index != NULL) {
                *if_index = sdl->sdl_index;
        }
 
                *if_index = sdl->sdl_index;
        }
 
@@ -1012,7 +921,7 @@ checkAddress(SCDynamicStoreRef             *storeP,
                SCLog(_sc_debug, LOG_INFO, CFSTR("  cannot be reached"));
        }
 
                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;
        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)
 {
 static CFStringRef
 __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
 {
@@ -1077,14 +945,14 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                case reachabilityTypeAddressPair : {
                        char            buf[64];
 
                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);
                        }
 
                                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 " : "",
                                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)) {
                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);
                                        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);
 
                                                        address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
                                                        sa      = (struct sockaddr *)CFDataGetBytePtr(address);
-                                                       sockaddr_to_string(sa, buf, sizeof(buf));
+                                                       _SC_sockaddr_to_string(sa, buf, sizeof(buf));
                                                        CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
                                                                             i > 0 ? ", " : "",
                                                                             buf);
                                                        CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
                                                                             i > 0 ? ", " : "",
                                                                             buf);
@@ -1118,13 +986,8 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                                                CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)"));
                                        }
                                } else {
                                                CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)"));
                                        }
                                } else {
-#ifdef CHECK_IPV6_REACHABILITY
                                        CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
                                                             gai_strerror(targetPrivate->resolvedAddressError));
                                        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)"));
                                }
                        } else if (targetPrivate->dnsPort) {
                                CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)"));
@@ -1132,7 +995,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                        break;
                }
        }
                        break;
                }
        }
-       if (targetPrivate->rls) {
+       if (targetPrivate->rls != NULL) {
                CFStringAppendFormat(result,
                                     NULL,
                                     CFSTR(", flags=%8.8x, if_index=%hu"),
                CFStringAppendFormat(result,
                                     NULL,
                                     CFSTR(", flags=%8.8x, if_index=%hu"),
@@ -1150,26 +1013,24 @@ __SCNetworkReachabilityDeallocate(CFTypeRef cf)
 {
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)cf;
 
 {
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityDeallocate:"));
-
        /* release resources */
 
        pthread_mutex_destroy(&targetPrivate->lock);
 
        /* release resources */
 
        pthread_mutex_destroy(&targetPrivate->lock);
 
-       if (targetPrivate->name)
+       if (targetPrivate->name != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->name);
 
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->name);
 
-       if (targetPrivate->resolvedAddress)
+       if (targetPrivate->resolvedAddress != NULL)
                CFRelease(targetPrivate->resolvedAddress);
 
                CFRelease(targetPrivate->resolvedAddress);
 
-       if (targetPrivate->localAddress)
+       if (targetPrivate->localAddress != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->localAddress);
 
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->localAddress);
 
-       if (targetPrivate->remoteAddress)
+       if (targetPrivate->remoteAddress != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->remoteAddress);
 
                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;
        }
 
        return;
@@ -1193,15 +1054,13 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef     allocator)
        /* initialize runtime */
        pthread_once(&initialized, __SCNetworkReachabilityInitialize);
 
        /* 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);
        /* allocate target */
        size          = sizeof(SCNetworkReachabilityPrivate) - sizeof(CFRuntimeBase);
        targetPrivate = (SCNetworkReachabilityPrivateRef)_CFRuntimeCreateInstance(allocator,
                                                                                  __kSCNetworkReachabilityTypeID,
                                                                                  size,
                                                                                  NULL);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
                return NULL;
        }
 
@@ -1226,6 +1085,7 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef       allocator)
        targetPrivate->rlsContext.copyDescription       = NULL;
        targetPrivate->rlList                           = NULL;
 
        targetPrivate->rlsContext.copyDescription       = NULL;
        targetPrivate->rlList                           = NULL;
 
+       targetPrivate->haveDNS                          = FALSE;
        targetPrivate->dnsPort                          = NULL;
        targetPrivate->dnsRLS                           = NULL;
 
        targetPrivate->dnsPort                          = NULL;
        targetPrivate->dnsRLS                           = NULL;
 
@@ -1239,7 +1099,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef             allocator,
 {
        SCNetworkReachabilityPrivateRef targetPrivate;
 
 {
        SCNetworkReachabilityPrivateRef targetPrivate;
 
-       if (!address ||
+       if ((address == NULL) ||
            (address->sa_len == 0) ||
            (address->sa_len > sizeof(struct sockaddr_storage))) {
                _SCErrorSet(kSCStatusInvalidArgument);
            (address->sa_len == 0) ||
            (address->sa_len > sizeof(struct sockaddr_storage))) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -1247,7 +1107,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef             allocator,
        }
 
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
        }
 
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
                return NULL;
        }
 
@@ -1271,7 +1131,7 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef         allocator,
                return NULL;
        }
 
                return NULL;
        }
 
-       if (localAddress) {
+       if (localAddress != NULL) {
                if ((localAddress->sa_len == 0) ||
                    (localAddress->sa_len > sizeof(struct sockaddr_storage))) {
                            _SCErrorSet(kSCStatusInvalidArgument);
                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);
                if ((remoteAddress->sa_len == 0) ||
                    (remoteAddress->sa_len > sizeof(struct sockaddr_storage))) {
                            _SCErrorSet(kSCStatusInvalidArgument);
@@ -1288,18 +1148,18 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef               allocator,
        }
 
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
        }
 
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
        targetPrivate->type = reachabilityTypeAddressPair;
 
                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);
        }
 
                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);
        }
                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)
 {
 SCNetworkReachabilityCreateWithName(CFAllocatorRef     allocator,
                                    const char          *nodename)
 {
+       struct sockaddr_in              sin;
+       struct sockaddr_in6             sin6;
        SCNetworkReachabilityPrivateRef targetPrivate;
 
        SCNetworkReachabilityPrivateRef targetPrivate;
 
-       if (!nodename) {
+       if (nodename == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return 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);
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
                return NULL;
        }
 
@@ -1364,7 +1251,7 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef target,
        }
 
        if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
        }
 
        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 */
                        return CFRetain(targetPrivate->resolvedAddress);
                } else {
                        /* if status is known but no resolved addresses to return */
@@ -1379,37 +1266,20 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef       target,
 
 
 static void
 
 
 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;
        struct addrinfo                         *resP;
-       SCNetworkReachabilityRef                target          = (SCNetworkReachabilityRef)context;
        SCNetworkReachabilityPrivateRef         targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        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);
                CFMutableArrayRef       addresses;
 
                addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
@@ -1423,94 +1293,41 @@ __SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinf
                }
 
                /* save the resolved address[es] */
                }
 
                /* 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 */
        } 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 (res)        freeaddrinfo(res);
 
-       if (targetPrivate->rls) {
+       if (targetPrivate->rls != NULL) {
                SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed"));
                CFRunLoopSourceSignal(targetPrivate->rls);
                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;
 }
        }
 
        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;
 }
        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)
 {
 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) {
        getaddrinfo_async_handle_reply(msg);
 
        if (port == targetPrivate->dnsPort) {
+               CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
                CFRelease(targetPrivate->dnsRLS);
                targetPrivate->dnsRLS = NULL;
                CFRelease(targetPrivate->dnsPort);
                CFRelease(targetPrivate->dnsRLS);
                targetPrivate->dnsRLS = NULL;
                CFRelease(targetPrivate->dnsPort);
@@ -1552,38 +1369,255 @@ getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi
 
        return;
 }
 
        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;
 }
        return;
 }
-#endif /* CHECK_IPV6_REACHABILITY */
 
 
 static Boolean
 
 
 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
 
        /*
         * We first assume that all of the configured DNS servers
@@ -1596,41 +1630,105 @@ checkResolverReachability(SCDynamicStoreRef            *storeP,
        *flags   = kSCNetworkFlagsReachable;
        *haveDNS = FALSE;
 
        *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;
        }
 
        return ok;
@@ -1641,17 +1739,19 @@ static Boolean
 startAsyncDNSQuery(SCNetworkReachabilityRef target) {
        CFMachPortContext               context         = { 0, (void *)target, CFRetain, CFRelease, CFCopyDescription };
        int                             error;
 startAsyncDNSQuery(SCNetworkReachabilityRef target) {
        CFMachPortContext               context         = { 0, (void *)target, CFRetain, CFRelease, CFCopyDescription };
        int                             error;
-#ifdef CHECK_IPV6_REACHABILITY
        struct addrinfo                 hints;
        struct addrinfo                 hints;
-#endif /* CHECK_IPV6_REACHABILITY */
        CFIndex                         i;
        CFIndex                         n;
        mach_port_t                     port;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
        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;
        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,
 
        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 */
                                        (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;
        }
 
                return FALSE;
        }
 
@@ -1670,26 +1770,6 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) {
                                                          getaddrinfo_async_handleCFReply,
                                                          &context,
                                                          NULL);
                                                          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);
        targetPrivate->dnsRLS = CFMachPortCreateRunLoopSource(NULL, targetPrivate->dnsPort, 0);
 
        n = CFArrayGetCount(targetPrivate->rlList);
@@ -1718,7 +1798,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef         *storeP,
        Boolean                         ok              = TRUE;
 
        *flags = 0;
        Boolean                         ok              = TRUE;
 
        *flags = 0;
-       if (if_index) {
+       if (if_index != NULL) {
                *if_index = 0;
        }
 
                *if_index = 0;
        }
 
@@ -1733,14 +1813,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef                *storeP,
                        /*
                         * Check "local" address
                         */
                        /*
                         * 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
                                 */
                                /*
                                 * Check "local" address
                                 */
@@ -1754,12 +1827,10 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                                }
                        }
 
                                }
                        }
 
-                   checkRemote :
-
                        /*
                         * Check "remote" address
                         */
                        /*
                         * 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.
                                /*
                                 * 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;
 
                                my_flags = 0;
                                my_index = 0;
 
-                               /*
-                                * Check if 0.0.0.0
-                                */
-                               if (isAddressZero(targetPrivate->remoteAddress, &my_flags)) {
-                                       break;
-                               }
-
                                /*
                                 * Check "remote" address
                                 */
                                /*
                                 * Check "remote" address
                                 */
@@ -1788,27 +1852,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                }
 
                case reachabilityTypeName : {
                }
 
                case reachabilityTypeName : {
+                       struct timeval                  dnsQueryStart;
                        int                             error;
                        int                             error;
-#ifndef        CHECK_IPV6_REACHABILITY
-                       struct hostent                  *h;
-#endif /* CHECK_IPV6_REACHABILITY */
-                       Boolean                         haveDNS         = FALSE;
-#ifdef CHECK_IPV6_REACHABILITY
                        struct addrinfo                 hints;
                        struct addrinfo                 hints;
-#endif /* CHECK_IPV6_REACHABILITY */
                        SCNetworkConnectionFlags        ns_flags;
                        SCNetworkConnectionFlags        ns_flags;
-#ifdef CHECK_IPV6_REACHABILITY
                        struct addrinfo                 *res;
                        struct addrinfo                 *res;
-#endif /* CHECK_IPV6_REACHABILITY */
 
                        addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
 
                        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 */
                                /* 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;
                        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.
                                 */
                                 * 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;
                                }
 
                                        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.
                                         */
                                         * and schedule notification.
                                         */
-#ifdef CHECK_IPV6_REACHABILITY
                                        __SCNetworkReachabilityCallbackSetResolvedAddress(EAI_NODATA,
                                                                                          NULL,
                                                                                          (void *)target);
                                        __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);
                                        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;
                        }
                                }
                                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.
                         */
                         * 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;
                        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);
 
                        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);
 
 
                        addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
 
@@ -1911,6 +1971,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef         *storeP,
                                        struct sockaddr                 *sa;
 
                                        sa = (struct sockaddr *)CFDataGetBytePtr(CFArrayGetValueAtIndex(addresses, i));
                                        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 */
                                        ok = checkAddress(storeP, sa, &ns_flags, &ns_if_index);
                                        if (!ok) {
                                                goto error;     /* not today */
@@ -1927,13 +1988,13 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                                        }
                                }
                        } else {
                                        }
                                }
                        } 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.
                                         */
                                        /*
                                         * 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 */
                                        }
                                        if (!ok) {
                                                goto error;     /* not today */
                                        }
@@ -1958,13 +2019,13 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
        }
 
        *flags = my_flags;
        }
 
        *flags = my_flags;
-       if (if_index) {
+       if (if_index != NULL) {
                *if_index = my_index;
        }
 
     error :
 
                *if_index = my_index;
        }
 
     error :
 
-       if (addresses)  CFRelease(addresses);
+       if (addresses != NULL)  CFRelease(addresses);
        return ok;
 }
 
        return ok;
 }
 
@@ -1982,15 +2043,15 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef  target,
                return FALSE;
        }
 
                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;
                *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;
 }
 
        return ok;
 }
 
@@ -1998,6 +2059,7 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef    target,
 static void
 __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef  store)
 {
 static void
 __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef  store)
 {
+       CFStringRef                     dns_key;
        CFStringRef                     key;
        CFMutableArrayRef               keys;
        CFStringRef                     pattern;
        CFStringRef                     key;
        CFMutableArrayRef               keys;
        CFStringRef                     pattern;
@@ -2006,34 +2068,30 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef   store)
        keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 
        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);
 
        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);
 
        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);
 
        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,
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -2041,7 +2099,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* Setup: per-service Interface info */
+       // Setup: per-service Interface info
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -2049,7 +2107,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* Setup: per-service PPP info */
+       // Setup: per-service PPP info (for kSCPropNetPPPDialOnDemand)
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -2057,15 +2115,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef    store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
        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,
        pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                                kSCDynamicStoreDomainState,
                                                                kSCCompAnyRegex,
@@ -2073,7 +2123,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* State: per-interface IPv6 info */
+       // State: per-interface IPv6 info
        pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                                kSCDynamicStoreDomainState,
                                                                kSCCompAnyRegex,
        pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                                kSCDynamicStoreDomainState,
                                                                kSCCompAnyRegex,
@@ -2094,12 +2144,13 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef      store,
                                                 CFArrayRef             changedKeys,
                                                 void                   *info)
 {
                                                 CFArrayRef             changedKeys,
                                                 void                   *info)
 {
-       Boolean         dnsChanged      = FALSE;
+       Boolean         dnsConfigChanged        = FALSE;
+       CFStringRef     dnsKey;
        CFIndex         i;
        CFStringRef     key;
        CFIndex         nTargets;
        const void *    targets_q[N_QUICK];
        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);
 
 
        pthread_mutex_lock(&hn_lock);
 
@@ -2116,35 +2167,20 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef      store,
 
        SCLog(_sc_debug, LOG_INFO, CFSTR("process configuration change"));
 
 
        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)) {
        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);
 
        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);
 
 
                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);
                }
 
                CFRunLoopSourceSignal(targetPrivate->rls);
-               __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+               _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
 
                pthread_mutex_unlock(&targetPrivate->lock);
        }
 
                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)
 {
 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);
 
        /* update reachability, notify if status changed */
        ok = __SCNetworkReachabilityGetFlags(&store, target, &flags, &if_index, TRUE);
-       if (store) CFRelease(store);
+       if (store != NULL) CFRelease(store);
        if (!ok) {
                /* if reachability status not available */
                flags    = 0;
        if (!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);
        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;
                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 */
        }
 
        /* update flags / interface */
@@ -2298,8 +2294,8 @@ rlsPerform(void *info)
 
        /* callout */
        rlsFunction = targetPrivate->rlsFunction;
 
        /* 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;
                context_release = targetPrivate->rlsContext.release;
        } else {
                context_info    = targetPrivate->rlsContext.info;
@@ -2308,13 +2304,12 @@ rlsPerform(void *info)
 
        pthread_mutex_unlock(&targetPrivate->lock);
 
 
        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);
        }
 
                (*rlsFunction)(target, flags, context_info);
        }
 
-       if (context_release) {
-               context_release(context_info);
+       if (context_release != NULL) {
+               (*context_release)(context_info);
        }
 
        return;
        }
 
        return;
@@ -2330,9 +2325,9 @@ SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target,
 
        pthread_mutex_lock(&targetPrivate->lock);
 
 
        pthread_mutex_lock(&targetPrivate->lock);
 
-       if (targetPrivate->rlsContext.release) {
+       if (targetPrivate->rlsContext.release != NULL) {
                /* let go of the current context */
                /* let go of the current context */
-               targetPrivate->rlsContext.release(targetPrivate->rlsContext.info);
+               (*targetPrivate->rlsContext.release)(targetPrivate->rlsContext.info);
        }
 
        targetPrivate->rlsFunction                      = callout;
        }
 
        targetPrivate->rlsFunction                      = callout;
@@ -2342,8 +2337,8 @@ SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target,
        targetPrivate->rlsContext.copyDescription       = NULL;
        if (context) {
                bcopy(context, &targetPrivate->rlsContext, sizeof(SCNetworkReachabilityContext));
        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);
 
        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);
                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;
                }
                        SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
                        goto done;
                }
@@ -2392,7 +2393,7 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target,
                hn_targets  = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
        }
 
                hn_targets  = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
        }
 
-       if (!targetPrivate->rls) {
+       if (targetPrivate->rls == NULL) {
                CFRunLoopSourceContext  context = { 0                   // version
                                                  , (void *)target      // info
                                                  , CFRetain            // retain
                CFRunLoopSourceContext  context = { 0                   // version
                                                  , (void *)target      // info
                                                  , CFRetain            // retain
@@ -2410,24 +2411,24 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
                init = TRUE;
        }
 
                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 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);
                }
        }
 
                        /* 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 */
 
 
        /* 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
                /*
                 * 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);
        }
 
                CFRunLoopAddSource(runLoop, hn_storeRLS, runLoopMode);
        }
 
-       __schedule(target, runLoop, runLoopMode, hn_rlList);
+       _SC_schedule(target, runLoop, runLoopMode, hn_rlList);
        CFSetAddValue(hn_targets, target);
 
        if (init) {
        CFSetAddValue(hn_targets, target);
 
        if (init) {
@@ -2456,13 +2457,13 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
                        targetPrivate->flags    = flags;
                        targetPrivate->if_index = if_index;
                        CFRunLoopSourceSignal(targetPrivate->rls);
                        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;
                }
                } 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;
        }
 
        ok = TRUE;
@@ -2492,24 +2493,24 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
        pthread_mutex_lock(&hn_lock);
        pthread_mutex_lock(&targetPrivate->lock);
 
        pthread_mutex_lock(&hn_lock);
        pthread_mutex_lock(&targetPrivate->lock);
 
-       if (!targetPrivate->rls) {
+       if (targetPrivate->rls == NULL) {
                /* if not currently scheduled */
                goto done;
        }
 
                /* 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 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 this host is no longer scheduled for this runLoop / runLoopMode
                 */
                CFRunLoopRemoveSource(runLoop, targetPrivate->rls, runLoopMode);
 
-               if (targetPrivate->dnsRLS) {
+               if (targetPrivate->dnsRLS != NULL) {
                        /* if we have an active async DNS query too */
                        CFRunLoopRemoveSource(runLoop, targetPrivate->dnsRLS, runLoopMode);
                }
                        /* if 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
                         */
                        /*
                         * 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;
                        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 */
 
                        if (targetPrivate->dnsPort) {
                                /* if we have an active async DNS query too */
-#ifdef CHECK_IPV6_REACHABILITY
                                lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
                                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);
                                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);
 
        n = CFArrayGetCount(hn_rlList);
-       if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
+       if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
                /*
                 * if we no longer have any addresses scheduled for
                 * this runLoop / runLoopMode
                /*
                 * if we 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);
                         * if we are no longer monitoring any addresses
                         */
                        CFRelease(hn_targets);
+                       hn_targets = NULL;
                        CFRelease(hn_rlList);
                        CFRelease(hn_rlList);
+                       hn_rlList = NULL;
+                       CFRunLoopSourceInvalidate(hn_storeRLS);
                        CFRelease(hn_storeRLS);
                        CFRelease(hn_storeRLS);
+                       hn_storeRLS = NULL;
                        CFRelease(hn_store);
                        hn_store = NULL;
 
                        /*
                         * until we start monitoring again, ensure that
                        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();
                }
        }
 
                }
        }
 
index 8efa2d3f6a2ac9fa7c4a6aaa3aa8ecbddc3e07fb..33ffd57788b4f245593cc1985996910d07c6e794 100644 (file)
 
 /*!
        @header SCNetworkReachability
 
 /*!
        @header SCNetworkReachability
-       The SCNetworkReachabilityXXX() APIs allow an application to determine the status
-       of a system's current network configuration and the reachability
-       of a target host.  In addition, the reachability can be monitored
-       with a notification being provided when/if the status has changed.
-
-       The term "reachable" reflects whether a data packet, sent by
-       an application into the network stack, can be sent to the
-       the target host/address.  Please note that there is no
-       guarantee that the data packet will actually be received by
-       the host.
+       @discussion The SCNetworkReachability API allows an application to
+               determine the status of a system's current network
+               configuration and the reachability of a target host.
+               In addition, reachability can be monitored with notifications
+               that are sent when the status has changed.
+
+               "Reachability" reflects whether a data packet, sent by
+               an application into the network stack, can leave the local
+               computer.
+               Note that reachability does <i>not</i> guarantee that the data
+               packet will actually be received by the host.
  */
 
 /*!
        @typedef SCNetworkReachabilityRef
  */
 
 /*!
        @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
 
 
 /*!
        @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;
  */
 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);
        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
 
 /*!
        @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 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
  */
 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
 
 __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.
        @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.
  */
 
                 You must release the returned value.
  */
@@ -99,13 +115,13 @@ SCNetworkReachabilityCreateWithAddress             (
 /*!
        @function SCNetworkReachabilityCreateWithAddressPair
        @discussion Creates a reference to the specified network
 /*!
        @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.
        @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.
  */
 
                 You must release the returned value.
  */
@@ -118,12 +134,13 @@ SCNetworkReachabilityCreateWithAddressPair        (
 
 /*!
        @function SCNetworkReachabilityCreateWithName
 
 /*!
        @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.
                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.
  */
 
                You must release the returned value.
  */
@@ -135,7 +152,8 @@ SCNetworkReachabilityCreateWithName         (
 
 /*!
        @function SCNetworkReachabilityGetTypeID
 
 /*!
        @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;
  */
 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.
        @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.
                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                  (
  */
 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.
        @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
                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               (
  */
 Boolean
 SCNetworkReachabilitySetCallback               (
@@ -181,10 +199,15 @@ SCNetworkReachabilitySetCallback          (
 
 /*!
        @function SCNetworkReachabilityScheduleWithRunLoop
 
 /*!
        @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       (
  */
 Boolean
 SCNetworkReachabilityScheduleWithRunLoop       (
@@ -195,10 +218,16 @@ SCNetworkReachabilityScheduleWithRunLoop  (
 
 /*!
        @function SCNetworkReachabilityUnscheduleFromRunLoop
 
 /*!
        @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     (
  */
 Boolean
 SCNetworkReachabilityUnscheduleFromRunLoop     (
diff --git a/SystemConfiguration.fproj/SCNetworkService.c b/SystemConfiguration.fproj/SCNetworkService.c
new file mode 100644 (file)
index 0000000..db30ae7
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include <pthread.h>
+
+
+static CFStringRef     __SCNetworkServiceCopyDescription       (CFTypeRef cf);
+static void            __SCNetworkServiceDeallocate            (CFTypeRef cf);
+static Boolean         __SCNetworkServiceEqual                 (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static CFTypeID __kSCNetworkServiceTypeID      = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkServiceClass = {
+       0,                                      // version
+       "SCNetworkService",                     // className
+       NULL,                                   // init
+       NULL,                                   // copy
+       __SCNetworkServiceDeallocate,           // dealloc
+       __SCNetworkServiceEqual,                // equal
+       NULL,                                   // hash
+       NULL,                                   // copyFormattingDesc
+       __SCNetworkServiceCopyDescription       // copyDebugDesc
+};
+
+
+static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkService(CFTypeRef obj)
+{
+       return (isA_CFType(obj, SCNetworkServiceGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkServiceCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef                  allocator       = CFGetAllocator(cf);
+       CFMutableStringRef              result;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)cf;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkService %p [%p]> { "), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("id=%@"), servicePrivate->serviceID);
+//     CFStringAppendFormat(result, NULL, CFSTR(", prefs=%@"), servicePrivate->prefs);
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__SCNetworkServiceDeallocate(CFTypeRef cf)
+{
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)cf;
+
+       /* release resources */
+
+       CFRelease(servicePrivate->serviceID);
+       if (servicePrivate->interface != NULL)  CFRelease(servicePrivate->interface);
+       CFRelease(servicePrivate->prefs);
+
+       return;
+}
+
+
+static Boolean
+__SCNetworkServiceEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+       SCNetworkServicePrivateRef      s1      = (SCNetworkServicePrivateRef)cf1;
+       SCNetworkServicePrivateRef      s2      = (SCNetworkServicePrivateRef)cf2;
+
+       if (s1 == s2)
+               return TRUE;
+
+       if (s1->prefs != s2->prefs)
+               return FALSE;   // if not the same prefs
+
+       if (!CFEqual(s1->serviceID, s2->serviceID))
+               return FALSE;   // if not the same service identifier
+
+       return TRUE;
+}
+
+
+static void
+__SCNetworkServiceInitialize(void)
+{
+       __kSCNetworkServiceTypeID = _CFRuntimeRegisterClass(&__SCNetworkServiceClass);
+       return;
+}
+
+
+__private_extern__ SCNetworkServicePrivateRef
+__SCNetworkServiceCreatePrivate(CFAllocatorRef         allocator,
+                               CFStringRef             serviceID,
+                               SCNetworkInterfaceRef   interface,
+                               SCPreferencesRef        prefs)
+{
+       SCNetworkServicePrivateRef              servicePrivate;
+       uint32_t                                size;
+
+       /* initialize runtime */
+       pthread_once(&initialized, __SCNetworkServiceInitialize);
+
+       /* allocate target */
+       size           = sizeof(SCNetworkServicePrivate) - sizeof(CFRuntimeBase);
+       servicePrivate = (SCNetworkServicePrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                             __kSCNetworkServiceTypeID,
+                                                                             size,
+                                                                             NULL);
+       if (servicePrivate == NULL) {
+               return NULL;
+       }
+
+       servicePrivate->prefs           = CFRetain(prefs);
+       servicePrivate->serviceID       = CFStringCreateCopy(NULL, serviceID);
+       servicePrivate->interface       = (interface != NULL) ? CFRetain(interface) : NULL;
+
+       return servicePrivate;
+}
+
+
+/* ---------- SCNetworkService APIs ---------- */
+
+
+#define        N_QUICK 64
+
+
+Boolean
+SCNetworkServiceAddProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
+{
+       CFDictionaryRef                 entity;
+       CFDictionaryRef                 newEntity       = NULL;
+       Boolean                         ok              = FALSE;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       if (!__SCNetworkProtocolIsValidType(protocolType)) {
+               _SCErrorSet(kSCStatusInvalidArgument);
+               return FALSE;
+       }
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             protocolType);                    // entity
+
+       entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+       if (entity != NULL) {
+               // if "protocol" already exists
+               _SCErrorSet(kSCStatusKeyExists);
+               goto done;
+       }
+
+       if (servicePrivate->interface != NULL) {
+               SCNetworkInterfaceRef   childInterface;
+               CFStringRef             childInterfaceType      = NULL;
+               CFStringRef             interfaceType;
+
+               interfaceType = SCNetworkInterfaceGetInterfaceType(servicePrivate->interface);
+               childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
+               if (childInterface != NULL) {
+                       childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
+               }
+
+               newEntity = __copyProtocolTemplate(interfaceType, childInterfaceType, protocolType);
+       }
+
+       if (newEntity == NULL) {
+               newEntity = CFDictionaryCreate(NULL,
+                                              NULL,
+                                              NULL,
+                                              0,
+                                              &kCFTypeDictionaryKeyCallBacks,
+                                              &kCFTypeDictionaryValueCallBacks);
+       }
+
+       ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
+       CFRelease(newEntity);
+
+    done :
+
+       CFRelease(path);
+       return ok;
+}
+
+
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkServiceCopyAll(SCPreferencesRef prefs)
+{
+       CFMutableArrayRef       array;
+       CFIndex                 n;
+       CFStringRef             path;
+       CFDictionaryRef         services;
+
+       path = SCPreferencesPathKeyCreateNetworkServices(NULL);
+       services = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
+
+       if ((services != NULL) && !isA_CFDictionary(services)) {
+               return NULL;
+       }
+
+       array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       n = (services != NULL) ? CFDictionaryGetCount(services) : 0;
+       if (n > 0) {
+               CFIndex         i;
+               const void *    keys_q[N_QUICK];
+               const void **   keys    = keys_q;
+               const void *    vals_q[N_QUICK];
+               const void **   vals    = vals_q;
+
+               if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+                       keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+                       vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
+               }
+               CFDictionaryGetKeysAndValues(services, keys, vals);
+               for (i = 0; i < n; i++) {
+                       CFDictionaryRef                 entity;
+                       SCNetworkServicePrivateRef      servicePrivate;
+
+                       if (!isA_CFDictionary(vals[i])) {
+                               SCLog(TRUE,
+                                     LOG_INFO,
+                                     CFSTR("SCNetworkServiceCopyAll(): error w/service \"%@\"\n"),
+                                     keys[i]);
+                               continue;
+                       }
+
+                       entity = CFDictionaryGetValue(vals[i], kSCEntNetInterface);
+                       if (!isA_CFDictionary(entity)) {
+                               // if no "interface"
+                               SCLog(TRUE,
+                                     LOG_INFO,
+                                     CFSTR("SCNetworkServiceCopyAll(): no \"%@\" entity for service \"%@\"\n"),
+                                     kSCEntNetInterface,
+                                     keys[i]);
+                               continue;
+                       }
+
+                       servicePrivate = __SCNetworkServiceCreatePrivate(NULL, keys[i], NULL, prefs);
+                       CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
+                       CFRelease(servicePrivate);
+               }
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(NULL, keys);
+                       CFAllocatorDeallocate(NULL, vals);
+               }
+       }
+
+       return array;
+}
+
+
+/*
+ * build a list of all of a servives entity types that are associated
+ * with the services interface.  The list will include :
+ *
+ * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...)
+ * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...)
+ * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...)
+ */
+static CFSetRef
+_copyInterfaceEntityTypes(CFDictionaryRef protocols)
+{
+       CFDictionaryRef interface;
+       CFMutableSetRef interface_entity_types;
+
+       interface_entity_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
+
+       interface = CFDictionaryGetValue(protocols, kSCEntNetInterface);
+       if (isA_CFDictionary(interface)) {
+               CFStringRef     entities[]      = { kSCPropNetInterfaceType,
+                                                   kSCPropNetInterfaceSubType,
+                                                   kSCPropNetInterfaceHardware };
+               int             i;
+
+               // include the "Interface" entity itself
+               CFSetAddValue(interface_entity_types, kSCEntNetInterface);
+
+               // include the entities associated with the interface
+               for (i = 0; i < sizeof(entities)/sizeof(entities[0]); i++) {
+                       CFStringRef     entity;
+
+                       entity = CFDictionaryGetValue(interface, entities[i]);
+                       if (isA_CFString(entity)) {
+                               CFSetAddValue(interface_entity_types, entity);
+                       }
+               }
+
+               /*
+                * and, because we've found some misguided network preference code
+                * developers leaving [PPP] entity dictionaries around even though
+                * they are unused and/or unneeded...
+                */
+               CFSetAddValue(interface_entity_types, kSCEntNetPPP);
+       }
+
+       return interface_entity_types;
+}
+
+
+SCNetworkServiceRef
+SCNetworkServiceCopy(SCPreferencesRef prefs, CFStringRef serviceID)
+{
+       CFDictionaryRef                 entity;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                     // allocator
+                                                             serviceID,                // service
+                                                             kSCEntNetInterface);      // entity
+       entity = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
+
+       if (!isA_CFDictionary(entity)) {
+               // a "service" must have an "interface"
+               _SCErrorSet(kSCStatusNoKey);
+               return NULL;
+       }
+
+       servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
+       return (SCNetworkServiceRef)servicePrivate;
+}
+
+
+SCNetworkProtocolRef
+SCNetworkServiceCopyProtocol(SCNetworkServiceRef service, CFStringRef protocolType)
+{
+       CFSetRef                        non_protocol_entities;
+       CFStringRef                     path;
+       CFDictionaryRef                 protocols;
+       SCNetworkProtocolPrivateRef     protocolPrivate = NULL;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       if ((protocols != NULL) && !isA_CFDictionary(protocols)) {
+               // if corrupt prefs
+               _SCErrorSet(kSCStatusFailed);
+               return NULL;
+       }
+
+       non_protocol_entities = _copyInterfaceEntityTypes(protocols);
+       if (CFSetContainsValue(non_protocol_entities, protocolType)) {
+               // if the "protocolType" matches an interface entity type
+               _SCErrorSet(kSCStatusInvalidArgument);
+               goto done;
+       }
+
+       if (!CFDictionaryContainsKey(protocols, protocolType)) {
+               // if the "protocolType" entity does not exist
+               _SCErrorSet(kSCStatusNoKey);
+               goto done;
+       }
+
+       protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, protocolType, service);
+
+    done :
+
+       CFRelease(non_protocol_entities);
+
+       return (SCNetworkProtocolRef)protocolPrivate;
+}
+
+
+CFArrayRef /* of SCNetworkProtocolRef's */
+SCNetworkServiceCopyProtocols(SCNetworkServiceRef service)
+{
+       CFMutableArrayRef               array;
+       CFIndex                         n;
+       CFSetRef                        non_protocol_entities;
+       CFStringRef                     path;
+       CFDictionaryRef                 protocols;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       if (!isA_CFDictionary(protocols)) {
+               return NULL;
+       }
+
+       non_protocol_entities = _copyInterfaceEntityTypes(protocols);
+
+       array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       n = CFDictionaryGetCount(protocols);
+       if (n > 0) {
+               CFIndex                         i;
+               const void *                    keys_q[N_QUICK];
+               const void **                   keys            = keys_q;
+               const void *                    vals_q[N_QUICK];
+               const void **                   vals            = vals_q;
+
+               if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+                       keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+                       vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
+               }
+               CFDictionaryGetKeysAndValues(protocols, keys, vals);
+               for (i = 0; i < n; i++) {
+                       SCNetworkProtocolPrivateRef     protocolPrivate;
+
+                       if (!isA_CFDictionary(vals[i])) {
+                               // if it's not a dictionary then it can't be a protocol entity
+                               continue;
+                       }
+
+                       if (CFSetContainsValue(non_protocol_entities, keys[i])) {
+                               // skip any non-protocol (interface) entities
+                               continue;
+                       }
+
+                       protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, keys[i], service);
+                       CFArrayAppendValue(array, (SCNetworkProtocolRef)protocolPrivate);
+
+                       CFRelease(protocolPrivate);
+               }
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(NULL, keys);
+                       CFAllocatorDeallocate(NULL, vals);
+               }
+       }
+
+       CFRelease(non_protocol_entities);
+
+       return array;
+}
+
+
+static Boolean
+__SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef     service,
+                                    SCNetworkInterfaceRef   interface)
+{
+       CFMutableDictionaryRef          entity;
+       SCNetworkInterfacePrivateRef    interfacePrivate        = (SCNetworkInterfacePrivateRef)interface;
+       Boolean                         ok;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate          = (SCNetworkServicePrivateRef)service;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             kSCEntNetInterface);              // entity
+       entity = CFDictionaryCreateMutable(NULL,
+                                          0,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+       if (interfacePrivate->entity_type != NULL) {
+               CFDictionarySetValue(entity,
+                                    kSCPropNetInterfaceType,
+                                    interfacePrivate->entity_type);
+       }
+       if (interfacePrivate->entity_subtype != NULL) {
+               CFDictionarySetValue(entity,
+                                    kSCPropNetInterfaceSubType,
+                                    interfacePrivate->entity_subtype);
+       }
+       if (interfacePrivate->entity_device != NULL) {
+               CFDictionarySetValue(entity,
+                                    kSCPropNetInterfaceDeviceName,
+                                    interfacePrivate->entity_device);
+       }
+       if (interfacePrivate->entity_hardware != NULL) {
+               CFDictionarySetValue(entity,
+                                    kSCPropNetInterfaceHardware,
+                                    interfacePrivate->entity_hardware);
+       }
+       if (CFEqual(interfacePrivate->interface_type, kSCNetworkInterfaceTypeModem) &&
+           interfacePrivate->supportsDeviceOnHold) {
+               int             one     = 1;
+               CFNumberRef     num;
+
+               num = CFNumberCreate(NULL, kCFNumberIntType, &one);
+               CFDictionarySetValue(entity,
+                                    kSCPropNetInterfaceSupportsModemOnHold,
+                                    num);
+               CFRelease(num);
+       }
+       ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity);
+       CFRelease(entity);
+       CFRelease(path);
+
+       return ok;
+}
+
+
+SCNetworkServiceRef
+SCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface)
+{
+       CFArrayRef                      components;
+       CFArrayRef                      interface_config;
+       SCNetworkInterfaceRef           newInterface;
+       CFStringRef                     path;
+       CFStringRef                     prefix;
+       CFStringRef                     serviceID;
+       SCNetworkServicePrivateRef      servicePrivate;
+
+       // establish the service
+       prefix = SCPreferencesPathKeyCreateNetworkServices(NULL);
+       path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
+       CFRelease(prefix);
+       if (path == NULL) {
+               return NULL;
+       }
+
+       components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
+       CFRelease(path);
+
+       serviceID = CFArrayGetValueAtIndex(components, 2);
+       servicePrivate = __SCNetworkServiceCreatePrivate(NULL, serviceID, NULL, prefs);
+       CFRelease(components);
+
+       // duplicate the interface and associate the copy with the new service
+       newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL,
+                                                                            interface,
+                                                                            (SCNetworkServiceRef)servicePrivate);
+       servicePrivate->interface = newInterface;
+
+       // establish "default" configuration(s) for the interface
+       for (interface = newInterface;
+            interface != NULL;
+            interface = SCNetworkInterfaceGetInterface(interface)) {
+               SCNetworkInterfaceRef   childInterface;
+               CFStringRef             childInterfaceType      = NULL;
+               CFDictionaryRef         config;
+               CFStringRef             interfaceType;
+
+               interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+               childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface);
+               if (childInterface != NULL) {
+                       childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
+               }
+
+               config = __copyInterfaceTemplate(interfaceType, childInterfaceType);
+               if (config != NULL) {
+                       (void) __SCNetworkInterfaceSetConfiguration(interface, config, TRUE);
+                       CFRelease(config);
+               }
+       }
+
+       // add the interface [entity] to the service
+       (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef)servicePrivate,
+                                                   servicePrivate->interface);
+
+       // push the [deep] interface configuration into into the service.
+       interface_config = __SCNetworkInterfaceCopyDeepConfiguration(servicePrivate->interface);
+       __SCNetworkInterfaceSetDeepConfiguration(servicePrivate->interface, interface_config);
+
+       return (SCNetworkServiceRef)servicePrivate;
+}
+
+
+Boolean
+SCNetworkServiceGetEnabled(SCNetworkServiceRef service)
+{
+       Boolean                         enabled;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       enabled = __getPrefsEnabled(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       return enabled;
+}
+
+
+SCNetworkInterfaceRef
+SCNetworkServiceGetInterface(SCNetworkServiceRef service)
+{
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       if (servicePrivate->interface == NULL) {
+               CFDictionaryRef entity;
+               CFStringRef     path;
+
+               path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                                     servicePrivate->serviceID,        // service
+                                                                     kSCEntNetInterface);              // entity
+               entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+               CFRelease(path);
+
+               if (isA_CFDictionary(entity)) {
+                       servicePrivate->interface = __SCNetworkInterfaceCreateWithEntity(NULL, entity, service);
+               }
+       }
+
+       return servicePrivate->interface;
+}
+
+
+CFStringRef
+SCNetworkServiceGetName(SCNetworkServiceRef service)
+{
+       CFDictionaryRef                 entity;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+       CFStringRef                     name            = NULL;
+       CFStringRef                     path;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       if (isA_CFDictionary(entity)) {
+               name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
+       }
+
+       return isA_CFString(name) ? name : NULL;
+}
+
+
+CFStringRef
+SCNetworkServiceGetServiceID(SCNetworkServiceRef service)
+{
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       return servicePrivate->serviceID;
+}
+
+
+CFTypeID
+SCNetworkServiceGetTypeID(void)
+{
+       pthread_once(&initialized, __SCNetworkServiceInitialize);       /* initialize runtime */
+       return __kSCNetworkServiceTypeID;
+}
+
+
+Boolean
+SCNetworkServiceRemove(SCNetworkServiceRef service)
+{
+       Boolean                         ok              = FALSE;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+       CFArrayRef                      sets;
+       CFStringRef                     path;
+
+       // remove service from all sets
+
+       sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+       if (sets != NULL) {
+               CFIndex i;
+               CFIndex n;
+
+               n = CFArrayGetCount(sets);
+               for (i = 0; i < n; i++) {
+                       SCNetworkSetRef set;
+
+                       set = CFArrayGetValueAtIndex(sets, i);
+                       ok = SCNetworkSetRemoveService(set, service);
+                       if (!ok && (SCError() != kSCStatusNoKey)) {
+                               break;
+                       }
+               }
+               CFRelease(sets);
+       }
+
+       // remove service
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
+       CFRelease(path);
+
+       return ok;
+}
+
+
+Boolean
+SCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service, CFStringRef protocolType)
+{
+       CFDictionaryRef                 entity;
+       Boolean                         ok              = FALSE;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             protocolType);                    // entity
+
+       entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+       if (entity == NULL) {
+               // if "protocol" does not exist
+               _SCErrorSet(kSCStatusNoKey);
+               goto done;
+       }
+
+       ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
+
+    done :
+
+       CFRelease(path);
+       return ok;
+}
+
+
+Boolean
+SCNetworkServiceSetEnabled(SCNetworkServiceRef service, Boolean enabled)
+{
+       Boolean                         ok;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
+       CFRelease(path);
+
+       return ok;
+}
+
+
+Boolean
+SCNetworkServiceSetName(SCNetworkServiceRef service, CFStringRef name)
+{
+       CFDictionaryRef                 entity;
+       Boolean                         ok              = FALSE;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate  = (SCNetworkServicePrivateRef)service;
+
+#define PREVENT_DUPLICATE_SERVICE_NAMES
+#ifdef  PREVENT_DUPLICATE_SERVICE_NAMES
+       if (isA_CFString(name)) {
+               CFArrayRef      sets;
+
+               // ensure that each service is uniquely named within its sets
+
+               sets = SCNetworkSetCopyAll(servicePrivate->prefs);
+               if (sets != NULL) {
+                       CFIndex         set_index;
+                       CFIndex         set_count;
+
+                       set_count = CFArrayGetCount(sets);
+                       for (set_index = 0; set_index < set_count; set_index++) {
+                               CFIndex         service_index;
+                               Boolean         isDup           = FALSE;
+                               Boolean         isMember        = FALSE;
+                               CFIndex         service_count;
+                               CFArrayRef      services;
+                               SCNetworkSetRef set             = CFArrayGetValueAtIndex(sets, set_index);
+
+                               services = SCNetworkSetCopyServices(set);
+
+                               service_count = CFArrayGetCount(services);
+                               for (service_index = 0; service_index < service_count; service_index++) {
+                                       CFStringRef             otherID;
+                                       CFStringRef             otherName;
+                                       SCNetworkServiceRef     otherService;
+
+                                       otherService = CFArrayGetValueAtIndex(services, service_index);
+
+                                       otherID = SCNetworkServiceGetServiceID(otherService);
+                                       if (CFEqual(servicePrivate->serviceID, otherID)) {
+                                               // if the service is a member of this set
+                                               isMember = TRUE;
+                                               continue;
+                                       }
+
+                                       otherName = SCNetworkServiceGetName(otherService);
+                                       if ((otherName != NULL) && CFEqual(name, otherName)) {
+                                               isDup = TRUE;
+                                               continue;
+                                       }
+                               }
+
+                               CFRelease(services);
+
+                               if (isMember && isDup) {
+                                       /*
+                                        * if this service is a member of the set and
+                                        * the "name" is not unique.
+                                        */
+                                       CFRelease(sets);
+                                       _SCErrorSet(kSCStatusKeyExists);
+                                       return FALSE;
+                               }
+                       }
+
+                       CFRelease(sets);
+               }
+       }
+#endif  /* PREVENT_DUPLICATE_SERVICE_NAMES */
+
+       path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       entity = SCPreferencesPathGetValue(servicePrivate->prefs, path);
+       if ((entity == NULL) && (name != NULL)) {
+               entity = CFDictionaryCreate(NULL,
+                                           NULL,
+                                           NULL,
+                                           0,
+                                           &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+       }
+       if (isA_CFDictionary(entity)) {
+               CFMutableDictionaryRef  newEntity;
+
+               newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+               if (isA_CFString(name)) {
+                       CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
+               } else {
+                       CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
+               }
+               ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity);
+               CFRelease(newEntity);
+       }
+       CFRelease(path);
+
+       return ok;
+}
diff --git a/SystemConfiguration.fproj/SCNetworkSet.c b/SystemConfiguration.fproj/SCNetworkSet.c
new file mode 100644 (file)
index 0000000..72653fa
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFRuntime.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
+#include <SystemConfiguration/SCValidation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "SCNetworkConfiguration.h"
+#include "SCNetworkConfigurationInternal.h"
+
+#include <pthread.h>
+
+
+static CFStringRef     __SCNetworkSetCopyDescription           (CFTypeRef cf);
+static void            __SCNetworkSetDeallocate                (CFTypeRef cf);
+static Boolean         __SCNetworkSetEqual                     (CFTypeRef cf1, CFTypeRef cf2);
+
+
+static CFTypeID __kSCNetworkSetTypeID  = _kCFRuntimeNotATypeID;
+
+
+static const CFRuntimeClass __SCNetworkSetClass = {
+       0,                              // version
+       "SCNetworkSet",                 // className
+       NULL,                           // init
+       NULL,                           // copy
+       __SCNetworkSetDeallocate,       // dealloc
+       __SCNetworkSetEqual,            // equal
+       NULL,                           // hash
+       NULL,                           // copyFormattingDesc
+       __SCNetworkSetCopyDescription   // copyDebugDesc
+};
+
+
+static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
+
+
+static __inline__ CFTypeRef
+isA_SCNetworkSet(CFTypeRef obj)
+{
+       return (isA_CFType(obj, SCNetworkSetGetTypeID()));
+}
+
+
+static CFStringRef
+__SCNetworkSetCopyDescription(CFTypeRef cf)
+{
+       CFAllocatorRef          allocator       = CFGetAllocator(cf);
+       CFMutableStringRef      result;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)cf;
+
+       result = CFStringCreateMutable(allocator, 0);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkSet %p [%p]> { "), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("id=%@"), setPrivate->setID);
+//     CFStringAppendFormat(result, NULL, CFSTR(", prefs=%@"), setPrivate->prefs);
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
+
+       return result;
+}
+
+
+static void
+__SCNetworkSetDeallocate(CFTypeRef cf)
+{
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)cf;
+
+       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkSetDeallocate:"));
+
+       /* release resources */
+
+       CFRelease(setPrivate->setID);
+       CFRelease(setPrivate->prefs);
+
+       return;
+}
+
+
+static Boolean
+__SCNetworkSetEqual(CFTypeRef cf1, CFTypeRef cf2)
+{
+       SCNetworkSetPrivateRef  s1      = (SCNetworkSetPrivateRef)cf1;
+       SCNetworkSetPrivateRef  s2      = (SCNetworkSetPrivateRef)cf2;
+
+       if (s1 == s2)
+               return TRUE;
+
+       if (s1->prefs != s2->prefs)
+               return FALSE;   // if not the same prefs
+
+       if (!CFEqual(s1->setID, s2->setID))
+               return FALSE;   // if not the same set identifier
+
+       return TRUE;
+}
+
+
+static void
+__SCNetworkSetInitialize(void)
+{
+       __kSCNetworkSetTypeID = _CFRuntimeRegisterClass(&__SCNetworkSetClass);
+       return;
+}
+
+
+static SCNetworkSetPrivateRef
+__SCNetworkSetCreatePrivate(CFAllocatorRef      allocator,
+                           SCPreferencesRef    prefs,
+                           CFStringRef         setID)
+{
+       SCNetworkSetPrivateRef  setPrivate;
+       uint32_t                size;
+
+       /* initialize runtime */
+       pthread_once(&initialized, __SCNetworkSetInitialize);
+
+       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkSetCreatePrivate:"));
+
+       /* allocate target */
+       size            = sizeof(SCNetworkSetPrivate) - sizeof(CFRuntimeBase);
+       setPrivate = (SCNetworkSetPrivateRef)_CFRuntimeCreateInstance(allocator,
+                                                                     __kSCNetworkSetTypeID,
+                                                                     size,
+                                                                     NULL);
+       if (setPrivate == NULL) {
+               return NULL;
+       }
+
+       setPrivate->setID       = CFStringCreateCopy(NULL, setID);
+       setPrivate->prefs       = CFRetain(prefs);
+
+       return setPrivate;
+}
+
+
+#define        N_QUICK 16
+
+
+Boolean
+SCNetworkSetAddService(SCNetworkSetRef set, SCNetworkServiceRef service)
+{
+       SCNetworkInterfaceRef           interface;
+       CFArrayRef                      interface_config        = NULL;
+       CFStringRef                     link;
+       Boolean                         ok;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate          = (SCNetworkServicePrivateRef)service;
+       SCNetworkSetPrivateRef          setPrivate              = (SCNetworkSetPrivateRef)set;
+
+#define PREVENT_DUPLICATE_SETS
+#ifdef  PREVENT_DUPLICATE_SETS
+       CFArrayRef                      sets;
+
+       // ensure that each service is only a member of ONE set
+
+       sets = SCNetworkSetCopyAll(setPrivate->prefs);
+       if (sets != NULL) {
+               CFIndex         i;
+               CFIndex         n;
+
+               n = CFArrayGetCount(sets);
+               for (i = 0; i < n; i++) {
+                       Boolean         found;
+                       CFArrayRef      services;
+                       SCNetworkSetRef set;
+
+                       set = CFArrayGetValueAtIndex(sets, i);
+                       services = SCNetworkSetCopyServices(set);
+                       found = CFArrayContainsValue(services,
+                                                    CFRangeMake(0, CFArrayGetCount(services)),
+                                                    service);
+                       CFRelease(services);
+
+                       if (found) {
+                               CFRelease(sets);
+                               _SCErrorSet(kSCStatusKeyExists);
+                               return FALSE;
+                       }
+               }
+               CFRelease(sets);
+       }
+#endif  /* PREVENT_DUPLICATE_SETS */
+
+       // get the [deep] interface configuration settings
+       interface = SCNetworkServiceGetInterface(service);
+       if (interface != NULL) {
+               interface_config = __SCNetworkInterfaceCopyDeepConfiguration(interface);
+       }
+
+       // create the link between "set" and the "service"
+       path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,                          // allocator
+                                                                setPrivate->setID,             // set
+                                                                servicePrivate->serviceID,     // service
+                                                                NULL);                         // entity
+       link = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,                             // allocator
+                                                             servicePrivate->serviceID,        // service
+                                                             NULL);                            // entity
+       ok = SCPreferencesPathSetLink(setPrivate->prefs, path, link);
+       CFRelease(path);
+       CFRelease(link);
+       if (!ok) {
+               return ok;
+       }
+
+       // push the [deep] interface configuration into all sets which contain this service.
+       if (interface != NULL) {
+               __SCNetworkInterfaceSetDeepConfiguration(interface, interface_config);
+       }
+
+       return ok;
+}
+
+
+SCNetworkSetRef
+SCNetworkSetCopy(SCPreferencesRef prefs, CFStringRef setID)
+{
+       CFDictionaryRef         entity;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate;
+
+       path = SCPreferencesPathKeyCreateSet(NULL, setID);
+       entity = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
+
+       if (!isA_CFDictionary(entity)) {
+               _SCErrorSet(kSCStatusNoKey);
+               return NULL;
+       }
+
+       setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+       return (SCNetworkSetRef)setPrivate;
+}
+
+
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkSetCopyAll(SCPreferencesRef prefs)
+{
+       CFMutableArrayRef       array;
+       CFIndex                 n;
+       CFStringRef             path;
+       CFDictionaryRef         sets;
+
+       path = SCPreferencesPathKeyCreateSets(NULL);
+       sets = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
+
+       if ((sets != NULL) && !isA_CFDictionary(sets)) {
+               return NULL;
+       }
+
+       array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       n = (sets != NULL) ? CFDictionaryGetCount(sets) : 0;
+       if (n > 0) {
+               CFIndex         i;
+               const void *    keys_q[N_QUICK];
+               const void **   keys    = keys_q;
+               const void *    vals_q[N_QUICK];
+               const void **   vals    = vals_q;
+
+               if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+                       keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+                       vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0);
+               }
+               CFDictionaryGetKeysAndValues(sets, keys, vals);
+               for (i = 0; i < n; i++) {
+                       SCNetworkSetPrivateRef  setPrivate;
+
+                       if (!isA_CFDictionary(vals[i])) {
+                               SCLog(TRUE,
+                                     LOG_INFO,
+                                     CFSTR("SCNetworkSetCopyAll(): error w/set \"%@\"\n"),
+                                     keys[i]);
+                               continue;
+                       }
+
+                       setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, keys[i]);
+                       CFArrayAppendValue(array, (SCNetworkSetRef)setPrivate);
+                       CFRelease(setPrivate);
+               }
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(NULL, keys);
+                       CFAllocatorDeallocate(NULL, vals);
+               }
+       }
+
+       return array;
+}
+
+
+SCNetworkSetRef
+SCNetworkSetCopyCurrent(SCPreferencesRef prefs)
+{
+       CFArrayRef              components;
+       CFStringRef             currentID;
+       SCNetworkSetPrivateRef  setPrivate      = NULL;
+
+       currentID = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+       if (!isA_CFString(currentID)) {
+               return NULL;
+       }
+
+       components = CFStringCreateArrayBySeparatingStrings(NULL, currentID, CFSTR("/"));
+       if (CFArrayGetCount(components) == 3) {
+               CFStringRef     setID;
+               CFStringRef     path;
+
+               setID = CFArrayGetValueAtIndex(components, 2);
+               path = SCPreferencesPathKeyCreateSet(NULL, setID);
+               if (CFEqual(path, currentID)) {
+                       setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+               } else {
+                       SCLog(TRUE, LOG_ERR, CFSTR("SCNetworkSetCopyCurrent(): preferences are non-conformant"));
+               }
+               CFRelease(path);
+       }
+       CFRelease(components);
+
+       return (SCNetworkSetRef)setPrivate;
+}
+
+
+CFArrayRef /* of SCNetworkServiceRef's */
+SCNetworkSetCopyServices(SCNetworkSetRef set)
+{
+       CFMutableArrayRef       array;
+       CFDictionaryRef         dict;
+       CFIndex                 n;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       path = SCPreferencesPathKeyCreateSetNetworkService(NULL, setPrivate->setID, NULL);
+       dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
+       CFRelease(path);
+       if ((dict != NULL) && !isA_CFDictionary(dict)) {
+               return NULL;
+       }
+
+       array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       n = (dict != NULL) ? CFDictionaryGetCount(dict) : 0;
+       if (n > 0) {
+               CFIndex         i;
+               const void *    keys_q[N_QUICK];
+               const void **   keys    = keys_q;
+
+               if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+                       keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+               }
+               CFDictionaryGetKeysAndValues(dict, keys, NULL);
+               for (i = 0; i < n; i++) {
+                       CFArrayRef      components;
+                       CFStringRef     link;
+
+                       path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,
+                                                                                setPrivate->setID,
+                                                                                (CFStringRef)keys[i],
+                                                                                NULL);
+                       link = SCPreferencesPathGetLink(setPrivate->prefs, path);
+                       CFRelease(path);
+                       if (link == NULL) {
+                               SCLog(TRUE,
+                                     LOG_INFO,
+                                     CFSTR("SCNetworkSetCopyServices(): service \"%@\" for set \"%@\" is not a link\n"),
+                                     keys[i],
+                                     setPrivate->setID);
+                               continue;        // if the service is not a link
+                       }
+
+                       components = CFStringCreateArrayBySeparatingStrings(NULL, link, CFSTR("/"));
+                       if (CFArrayGetCount(components) == 3) {
+                               CFStringRef serviceID;
+
+                               serviceID = CFArrayGetValueAtIndex(components, 2);
+                               path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL,             // allocator
+                                                                                     serviceID,        // service
+                                                                                     NULL);            // entity
+                               if (CFEqual(path, link)) {
+                                       SCNetworkServicePrivateRef      servicePrivate;
+
+                                       servicePrivate = __SCNetworkServiceCreatePrivate(NULL,
+                                                                                        serviceID,
+                                                                                        NULL,
+                                                                                        setPrivate->prefs);
+                                       CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate);
+                                       CFRelease(servicePrivate);
+                               }
+                               CFRelease(path);
+                       }
+                       CFRelease(components);
+               }
+               if (keys != keys_q) {
+                       CFAllocatorDeallocate(NULL, keys);
+               }
+       }
+
+       return array;
+}
+
+
+SCNetworkSetRef
+SCNetworkSetCreate(SCPreferencesRef prefs)
+{
+       CFArrayRef              components;
+       CFStringRef             path;
+       CFStringRef             prefix;
+       CFStringRef             setID;
+       SCNetworkSetPrivateRef  setPrivate;
+
+       prefix = SCPreferencesPathKeyCreateSets(NULL);
+       path = SCPreferencesPathCreateUniqueChild(prefs, prefix);
+       CFRelease(prefix);
+       if (path == NULL) {
+               return NULL;
+       }
+
+       components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/"));
+       CFRelease(path);
+
+       setID = CFArrayGetValueAtIndex(components, 2);
+       setPrivate = __SCNetworkSetCreatePrivate(NULL, prefs, setID);
+       CFRelease(components);
+
+       return (SCNetworkSetRef)setPrivate;
+}
+
+
+CFStringRef
+SCNetworkSetGetSetID(SCNetworkSetRef set)
+{
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       return setPrivate->setID;
+}
+
+
+CFStringRef
+SCNetworkSetGetName(SCNetworkSetRef set)
+{
+       CFDictionaryRef         entity;
+       CFStringRef             name            = NULL;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+       entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
+       CFRelease(path);
+
+       if (isA_CFDictionary(entity)) {
+               name = CFDictionaryGetValue(entity, kSCPropUserDefinedName);
+       }
+
+       return isA_CFString(name) ? name : NULL;
+}
+
+
+CFArrayRef /* of serviceID CFStringRef's */
+SCNetworkSetGetServiceOrder(SCNetworkSetRef set)
+{
+       CFDictionaryRef         dict;
+       CFStringRef             path;
+       CFArrayRef              serviceOrder;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4);
+       if (path == NULL) {
+               return NULL;
+       }
+
+       dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
+       CFRelease(path);
+       if (!isA_CFDictionary(dict)) {
+               return NULL;
+       }
+
+       serviceOrder = CFDictionaryGetValue(dict, kSCPropNetServiceOrder);
+       serviceOrder = isA_CFArray(serviceOrder);
+
+       return serviceOrder;
+}
+
+
+CFTypeID
+SCNetworkSetGetTypeID(void)
+{
+       pthread_once(&initialized, __SCNetworkSetInitialize);   /* initialize runtime */
+       return __kSCNetworkSetTypeID;
+}
+
+
+Boolean
+SCNetworkSetRemove(SCNetworkSetRef set)
+{
+       CFStringRef             currentPath;
+       Boolean                 ok              = FALSE;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       currentPath = SCPreferencesGetValue(setPrivate->prefs, kSCPrefCurrentSet);
+       path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+       if (!isA_CFString(currentPath) || !CFEqual(currentPath, path)) {
+               ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path);
+       }
+       CFRelease(path);
+
+       return ok;
+}
+
+
+Boolean
+SCNetworkSetRemoveService(SCNetworkSetRef set, SCNetworkServiceRef service)
+{
+       SCNetworkInterfaceRef           interface;
+       CFArrayRef                      interface_config        = NULL;
+       Boolean                         ok;
+       CFStringRef                     path;
+       SCNetworkServicePrivateRef      servicePrivate          = (SCNetworkServicePrivateRef)service;
+       SCNetworkSetPrivateRef          setPrivate              = (SCNetworkSetPrivateRef)set;
+
+       // get the [deep] interface configuration settings
+       interface = SCNetworkServiceGetInterface(service);
+       if (interface != NULL) {
+               interface_config = __SCNetworkInterfaceCopyDeepConfiguration(interface);
+               if (interface_config != NULL) {
+                       // remove the interface configuration from all sets which contain this service.
+                       __SCNetworkInterfaceSetDeepConfiguration(interface, NULL);
+               }
+       }
+
+       // remove the link between "set" and the "service"
+       path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL,
+                                                                setPrivate->setID,
+                                                                servicePrivate->serviceID,
+                                                                NULL);
+       ok = SCPreferencesPathRemoveValue(setPrivate->prefs, path);
+       CFRelease(path);
+       if (!ok) {
+               goto done;
+       }
+
+       // push the [deep] interface configuration [back] into all sets which contain the service.
+       if (interface_config != NULL) {
+               __SCNetworkInterfaceSetDeepConfiguration(interface, interface_config);
+       }
+
+    done :
+
+       if (interface_config != NULL)     CFRelease(interface_config);
+       return ok;
+}
+
+
+Boolean
+SCNetworkSetSetCurrent(SCNetworkSetRef set)
+{
+       Boolean                 ok;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+       ok = SCPreferencesSetValue(setPrivate->prefs, kSCPrefCurrentSet, path);
+       CFRelease(path);
+       return ok;
+}
+
+
+Boolean
+SCNetworkSetSetName(SCNetworkSetRef set, CFStringRef name)
+{
+       CFDictionaryRef         entity;
+       Boolean                 ok              = FALSE;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+#define PREVENT_DUPLICATE_SET_NAMES
+#ifdef  PREVENT_DUPLICATE_SET_NAMES
+       if (isA_CFString(name)) {
+               CFArrayRef      sets;
+
+               // ensure that each set is uniquely named
+
+               sets = SCNetworkSetCopyAll(setPrivate->prefs);
+               if (sets != NULL) {
+                       CFIndex         i;
+                       CFIndex         n;
+
+                       n = CFArrayGetCount(sets);
+                       for (i = 0; i < n; i++) {
+                               CFStringRef     otherID;
+                               CFStringRef     otherName;
+                               SCNetworkSetRef set             = CFArrayGetValueAtIndex(sets, i);
+
+                               otherID = SCNetworkSetGetSetID(set);
+                               if (CFEqual(setPrivate->setID, otherID)) {
+                                       continue;       // skip current set
+                               }
+
+                               otherName = SCNetworkSetGetName(set);
+                               if ((otherName != NULL) && CFEqual(name, otherName)) {
+                                       // if "name" not unique
+                                       CFRelease(sets);
+                                       _SCErrorSet(kSCStatusKeyExists);
+                                       return FALSE;
+                               }
+                       }
+                       CFRelease(sets);
+               }
+       }
+#endif  /* PREVENT_DUPLICATE_SET_NAMES */
+
+       // update the "name"
+
+       path = SCPreferencesPathKeyCreateSet(NULL, setPrivate->setID);
+       entity = SCPreferencesPathGetValue(setPrivate->prefs, path);
+       if ((entity == NULL) && (name != NULL)) {
+               entity = CFDictionaryCreate(NULL,
+                                           NULL,
+                                           NULL,
+                                           0,
+                                           &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+       }
+       if (isA_CFDictionary(entity)) {
+               CFMutableDictionaryRef  newEntity;
+
+               newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+               if (isA_CFString(name)) {
+                       CFDictionarySetValue(newEntity, kSCPropUserDefinedName, name);
+               } else {
+                       CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName);
+               }
+               ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newEntity);
+               CFRelease(newEntity);
+       }
+       CFRelease(path);
+
+       return ok;
+}
+
+
+Boolean
+SCNetworkSetSetServiceOrder(SCNetworkSetRef set, CFArrayRef newOrder)
+{
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict;
+       Boolean                 ok;
+       CFStringRef             path;
+       SCNetworkSetPrivateRef  setPrivate      = (SCNetworkSetPrivateRef)set;
+
+       path = SCPreferencesPathKeyCreateSetNetworkGlobalEntity(NULL, setPrivate->setID, kSCEntNetIPv4);
+       if (path == NULL) {
+               return FALSE;
+       }
+
+       dict = SCPreferencesPathGetValue(setPrivate->prefs, path);
+       if (dict != NULL) {
+               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+       } else {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       CFDictionarySetValue(newDict, kSCPropNetServiceOrder, newOrder);
+       ok = SCPreferencesPathSetValue(setPrivate->prefs, path, newDict);
+       CFRelease(newDict);
+       CFRelease(path);
+
+       return ok;
+}
index 0d6474354c639a9075fc3d36f94990f040137488..e81b75f7d95774cc7a2563606377fb4ce6d3f797 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -160,14 +160,19 @@ __SCPreferencesPath(CFAllocatorRef        allocator,
 
 
 CFDataRef
 
 
 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         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 :
        switch (keyType) {
                case kSCPreferencesKeyLock :
-                       typeStr = "lock";
+                       keyStr = CFSTR("lock");
                        break;
                case kSCPreferencesKeyCommit :
                        break;
                case kSCPreferencesKeyCommit :
-                       typeStr = "commit";
+                       keyStr = CFSTR("commit");
                        break;
                case kSCPreferencesKeyApply :
                        break;
                case kSCPreferencesKeyApply :
-                       typeStr = "apply";
+                       keyStr = CFSTR("apply");
                        break;
                default :
                        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;
 }
 
 
 }
 
 
index 963c2f068c6d212f9b1d9214f382066f6f44532f..420fe3223f29a27f5b12e213439f487f067ecbb5 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
 #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;
        }
 
                _SCErrorSet(kSCStatusKeyExists);
                return FALSE;
        }
 
-       CFDictionaryAddValue(sessionPrivate->prefs, key, value);
-       sessionPrivate->changed  = TRUE;
+       CFDictionaryAddValue(prefsPrivate->prefs, key, value);
+       prefsPrivate->changed  = TRUE;
        return TRUE;
 }
        return TRUE;
 }
index 951eb4fdc287d5af3c9293239c05cd93b436b46d..775036f3a1cbb984d9694819d2cb5f02821de4de 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
 #include "SCPreferencesInternal.h"
 
 Boolean
-SCPreferencesApplyChanges(SCPreferencesRef session)
+SCPreferencesApplyChanges(SCPreferencesRef prefs)
 {
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        Boolean                 wasLocked;
 
        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.
         */
 
        /*
         * 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 (!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;
                }
        }
 
                        return FALSE;
                }
        }
 
-       if (!sessionPrivate->isRoot) {
+       if (!prefsPrivate->isRoot) {
                /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
                goto perUser;
        }
 
                /* 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 */
        /* 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 :
 
                _SCErrorSet(kSCStatusFailed);
                goto error;
        }
 
     perUser :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
        return TRUE;
 
     error :
 
        return TRUE;
 
     error :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
        return FALSE;
 }
        return FALSE;
 }
index 8998e4bcd7a04c9c4008348c058d3c691d216a05..0ea6dc9a53e580a98f500ad00b5a1f35b6041cac 100644 (file)
@@ -63,21 +63,25 @@ writen(int d, const void *buf, size_t nbytes)
 
 
 Boolean
 
 
 Boolean
-SCPreferencesCommitChanges(SCPreferencesRef session)
+SCPreferencesCommitChanges(SCPreferencesRef prefs)
 {
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        Boolean                 wasLocked;
 
        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.
         */
 
        /*
         * 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 (!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;
                }
        }
                        return FALSE;
                }
        }
@@ -85,7 +89,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
        /*
         * if necessary, apply changes
         */
        /*
         * if necessary, apply changes
         */
-       if (sessionPrivate->changed) {
+       if (prefsPrivate->changed) {
                int             fd;
                CFDataRef       newPrefs;
                char *          path;
                int             fd;
                CFDataRef       newPrefs;
                char *          path;
@@ -93,20 +97,20 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
                struct stat     statBuf;
                char *          thePath;
 
                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 {
                        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 */
                                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);
                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) &&
                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, '/');
                                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;
                }
                        CFAllocatorDeallocate(NULL, thePath);
                        goto error;
                }
@@ -141,84 +145,97 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
                (void) fchmod(fd, statBuf.st_mode);
 
                /* write the new preferences */
                (void) fchmod(fd, statBuf.st_mode);
 
                /* write the new preferences */
-               newPrefs = CFPropertyListCreateXMLData(NULL, sessionPrivate->prefs);
+               newPrefs = CFPropertyListCreateXMLData(NULL, prefsPrivate->prefs);
                if (!newPrefs) {
                        _SCErrorSet(kSCStatusFailed);
                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);
                        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) 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);
                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);
 
                        CFAllocatorDeallocate(NULL, thePath);
                        goto error;
                }
                CFAllocatorDeallocate(NULL, thePath);
 
-               if (sessionPrivate->newPath) {
+               if (prefsPrivate->newPath) {
                        /* prefs file saved in "new" directory */
                        /* 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);
                }
 
                /* 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;
                }
                        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;
        }
 
                /* 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 */
        /* 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 :
 
                _SCErrorSet(kSCStatusFailed);
                goto error;
        }
 
     perUser :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
-       sessionPrivate->changed = FALSE;
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
+       prefsPrivate->changed = FALSE;
        return TRUE;
 
     error :
 
        return TRUE;
 
     error :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
        return FALSE;
 }
        return FALSE;
 }
index 896d27c6c5ade02c476328e70b84f337ec643b93..297107ec1871b4b41a82c40d0087641153e45885 100644 (file)
 #include "SCPreferencesInternal.h"
 
 CFPropertyListRef
 #include "SCPreferencesInternal.h"
 
 CFPropertyListRef
-SCPreferencesGetValue(SCPreferencesRef session, CFStringRef key)
+SCPreferencesGetValue(SCPreferencesRef prefs, CFStringRef key)
 {
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        CFPropertyListRef       value;
 
        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);
        }
 
                _SCErrorSet(kSCStatusNoKey);
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value = %@"), value);
        return value;
 }
        return value;
 }
index 1626811c08409faad29413e1fe153ee455abfa3d..8a4266f3cf17ebf4ec9eac325f3614cae26b2370 100644 (file)
 #include "SCPreferencesInternal.h"
 
 CFArrayRef
 #include "SCPreferencesInternal.h"
 
 CFArrayRef
-SCPreferencesCopyKeyList(SCPreferencesRef session)
+SCPreferencesCopyKeyList(SCPreferencesRef prefs)
 {
 {
-       CFAllocatorRef          allocator       = CFGetAllocator(session);
+       CFAllocatorRef          allocator       = CFGetAllocator(prefs);
        CFArrayRef              keys;
        CFArrayRef              keys;
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        CFIndex                 prefsCnt;
        const void **           prefsKeys;
 
        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);
        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);
        }
 
                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;
 }
        return keys;
 }
index 88bd2819c8c0d890a53b3f3f4a447848be5bf9c4..f7b155170cfb7d3cbd91062410f05f79fe232dcd 100644 (file)
 
 #include <fcntl.h>
 #include <unistd.h>
 
 #include <fcntl.h>
 #include <unistd.h>
+#include <pthread.h>
 #include <sys/errno.h>
 
 Boolean
 #include <sys/errno.h>
 
 Boolean
-SCPreferencesLock(SCPreferencesRef session, Boolean wait)
+SCPreferencesLock(SCPreferencesRef prefs, Boolean wait)
 {
 {
-       CFAllocatorRef          allocator               = CFGetAllocator(session);
+       CFAllocatorRef          allocator               = CFGetAllocator(prefs);
        CFArrayRef              changes;
        CFArrayRef              changes;
-       CFDataRef               currentSignature        = NULL;
        Boolean                 haveLock                = FALSE;
        Boolean                 haveLock                = FALSE;
-       SCPreferencesPrivateRef sessionPrivate          = (SCPreferencesPrivateRef)session;
-       struct stat             statBuf;
+       SCPreferencesPrivateRef prefsPrivate            = (SCPreferencesPrivateRef)prefs;
        CFDateRef               value                   = NULL;
 
        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;
        }
 
                /* 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 {
                        _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 */
                /* 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)) {
                                         FALSE)) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreAddWatchedKey() failed"));
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreAddWatchedKey() failed"));
                goto error;
        }
 
                goto error;
        }
 
-       value  = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent());
+       value = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent());
 
        while (TRUE) {
                CFArrayRef      changedKeys;
 
        while (TRUE) {
                CFArrayRef      changedKeys;
@@ -104,8 +103,8 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
                /*
                 * Attempt to acquire the lock
                 */
                /*
                 * Attempt to acquire the lock
                 */
-               if (SCDynamicStoreAddTemporaryValue(sessionPrivate->session,
-                                                   sessionPrivate->sessionKeyLock,
+               if (SCDynamicStoreAddTemporaryValue(prefsPrivate->session,
+                                                   prefsPrivate->sessionKeyLock,
                                                    value)) {
                        haveLock = TRUE;
                        goto done;
                                                    value)) {
                        haveLock = TRUE;
                        goto done;
@@ -119,13 +118,13 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
                /*
                 * Wait for the lock to be released
                 */
                /*
                 * 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;
                }
                        goto error;
                }
-               changedKeys = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session);
+               changedKeys = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
                if (!changedKeys) {
                if (!changedKeys) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
+                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreCopyNotifiedKeys() failed"));
                        goto error;
                }
                CFRelease(changedKeys);
                        goto error;
                }
                CFRelease(changedKeys);
@@ -136,88 +135,71 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
        CFRelease(value);
        value = NULL;
 
        CFRelease(value);
        value = NULL;
 
-       if (!SCDynamicStoreRemoveWatchedKey(sessionPrivate->session,
-                                           sessionPrivate->sessionKeyLock,
+       if (!SCDynamicStoreRemoveWatchedKey(prefsPrivate->session,
+                                           prefsPrivate->sessionKeyLock,
                                            0)) {
                                            0)) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveWatchedKey() failed"));
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreRemoveWatchedKey() failed"));
                goto error;
        }
 
                goto error;
        }
 
-       changes = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session);
+       changes = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
        if (!changes) {
        if (!changes) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreCopyNotifiedKeys() failed"));
                goto error;
        }
        CFRelease(changes);
 
     perUser:
 
                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;
                         * 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) {
        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;
        if (value)              CFRelease(value);
 
        return FALSE;
index 47f21f22ae3c1d1ad3477e5ff316dc7599f666f2..2c45b5783ba83ae81dc3459b79c60b8e2f0e3e1c 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * February 16, 2004           Allan Nathanson <ajn@apple.com>
+ * - add preference notification APIs
+ *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
 #include <unistd.h>
 #include <sys/errno.h>
 
 #include <unistd.h>
 #include <sys/errno.h>
 
+
 static CFStringRef
 __SCPreferencesCopyDescription(CFTypeRef cf) {
        CFAllocatorRef          allocator       = CFGetAllocator(cf);
 static CFStringRef
 __SCPreferencesCopyDescription(CFTypeRef cf) {
        CFAllocatorRef          allocator       = CFGetAllocator(cf);
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)cf;
        CFMutableStringRef      result;
 
        result = CFStringCreateMutable(allocator, 0);
        CFMutableStringRef      result;
 
        result = CFStringCreateMutable(allocator, 0);
-       CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {\n"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("name = %@"), prefsPrivate->name);
+       CFStringAppendFormat(result, NULL, CFSTR(", id = %@"), prefsPrivate->prefsID);
+       if (prefsPrivate->perUser) {
+               CFStringAppendFormat(result, NULL, CFSTR(" (for user %@)"), prefsPrivate->user);
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(", path = %s"),
+                            prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path);
+       if (prefsPrivate->accessed) {
+               CFStringAppendFormat(result, NULL, CFSTR(", accessed"));
+       }
+       if (prefsPrivate->changed) {
+               CFStringAppendFormat(result, NULL, CFSTR(", changed"));
+       }
+       if (prefsPrivate->locked) {
+               CFStringAppendFormat(result, NULL, CFSTR(", locked"));
+       }
        CFStringAppendFormat(result, NULL, CFSTR("}"));
 
        return result;
        CFStringAppendFormat(result, NULL, CFSTR("}"));
 
        return result;
@@ -57,22 +78,26 @@ __SCPreferencesCopyDescription(CFTypeRef cf) {
 static void
 __SCPreferencesDeallocate(CFTypeRef cf)
 {
 static void
 __SCPreferencesDeallocate(CFTypeRef cf)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)cf;
-
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesDeallocate:"));
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)cf;
 
        /* release resources */
 
        /* 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;
 }
 
        return;
 }
@@ -82,14 +107,14 @@ static CFTypeID __kSCPreferencesTypeID     = _kCFRuntimeNotATypeID;
 
 
 static const CFRuntimeClass __SCPreferencesClass = {
 
 
 static const CFRuntimeClass __SCPreferencesClass = {
-       0,                                      // version
-       "SCPreferences",                        // className
-       NULL,                                   // init
-       NULL,                                   // copy
+       0,                              // version
+       "SCPreferences",                // className
+       NULL,                           // init
+       NULL,                           // copy
        __SCPreferencesDeallocate,      // dealloc
        __SCPreferencesDeallocate,      // dealloc
-       NULL,                                   // equal
-       NULL,                                   // hash
-       NULL,                                   // copyFormattingDesc
+       NULL,                           // equal
+       NULL,                           // hash
+       NULL,                           // copyFormattingDesc
        __SCPreferencesCopyDescription  // copyDebugDesc
 };
 
        __SCPreferencesCopyDescription  // copyDebugDesc
 };
 
@@ -112,32 +137,41 @@ __SCPreferencesCreatePrivate(CFAllocatorRef       allocator)
        /* initialize runtime */
        pthread_once(&initialized, __SCPreferencesInitialize);
 
        /* initialize runtime */
        pthread_once(&initialized, __SCPreferencesInitialize);
 
-       /* allocate session */
+       /* allocate prefs session */
        size  = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase);
        prefsPrivate = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
                                                                         __kSCPreferencesTypeID,
                                                                         size,
                                                                         NULL);
        size  = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase);
        prefsPrivate = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
                                                                         __kSCPreferencesTypeID,
                                                                         size,
                                                                         NULL);
-       if (!prefsPrivate) {
+       if (prefsPrivate == NULL) {
                return 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;
 }
 
        return prefsPrivate;
 }
@@ -153,15 +187,12 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
        int                             fd              = -1;
        SCPreferencesPrivateRef         prefsPrivate;
        int                             sc_status       = kSCStatusOK;
        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);
         */
        prefsPrivate = __SCPreferencesCreatePrivate(allocator);
-       if (!prefsPrivate) {
+       if (prefsPrivate == NULL) {
                return NULL;
        }
 
                return NULL;
        }
 
@@ -184,7 +215,9 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
         * open file
         */
        fd = open(prefsPrivate->path, O_RDONLY, 0644);
         * 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 */
                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;
                        case EACCES :
                                sc_status = kSCStatusAccessError;
                                break;
@@ -221,25 +253,78 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                                sc_status = kSCStatusFailed;
                                break;
                }
                                sc_status = kSCStatusFailed;
                                break;
                }
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("open() failed: %s"), strerror(errno));
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
                goto error;
        }
 
                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 :
 
                goto error;
        }
 
     create_1 :
 
+       if (prefsPrivate->signature != NULL) CFRelease(prefsPrivate->signature);
        prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
 
        if (statBuf.st_size > 0) {
        prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
 
        if (statBuf.st_size > 0) {
-               CFDictionaryRef dict;
+               CFDictionaryRef         dict;
+               CFMutableDataRef        xmlData;
+               CFStringRef             xmlError;
 
                /*
                 * extract property list
 
                /*
                 * 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 */
                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;
                        CFRelease(xmlData);
                        xmlData = NULL;
                        goto create_2;
@@ -262,11 +347,11 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                                                       kCFPropertyListImmutable,
                                                       &xmlError);
                CFRelease(xmlData);
                                                       kCFPropertyListImmutable,
                                                       &xmlError);
                CFRelease(xmlData);
-               if (!dict) {
+               if (dict == NULL) {
                        /* corrupt prefs file, start fresh */
                        /* corrupt prefs file, start fresh */
-                       if (xmlError) {
+                       if (xmlError != NULL) {
                                SCLog(TRUE, LOG_ERR,
                                SCLog(TRUE, LOG_ERR,
-                                     CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
+                                     CFSTR("__SCPreferencesAccess CFPropertyListCreateFromXMLData(): %@"),
                                      xmlError);
                                CFRelease(xmlError);
                        }
                                      xmlError);
                                CFRelease(xmlError);
                        }
@@ -278,7 +363,7 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                 */
                if (!isA_CFDictionary(dict)) {
                        /* corrupt prefs file, start fresh */
                 */
                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;
                }
                        CFRelease(dict);
                        goto create_2;
                }
@@ -298,7 +383,7 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                /*
                 * new file, create empty preferences
                 */
                /*
                 * new file, create empty preferences
                 */
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary."));
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess(): creating new dictionary."));
                prefsPrivate->prefs = CFDictionaryCreateMutable(allocator,
                                                                0,
                                                                &kCFTypeDictionaryKeyCallBacks,
                prefsPrivate->prefs = CFDictionaryCreateMutable(allocator,
                                                                0,
                                                                &kCFTypeDictionaryKeyCallBacks,
@@ -306,21 +391,15 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                prefsPrivate->changed = TRUE;
        }
 
                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);
 
     error :
 
        if (fd != -1)   (void) close(fd);
-       CFRelease(prefsPrivate);
        _SCErrorSet(sc_status);
        _SCErrorSet(sc_status);
-       return NULL;
+       return FALSE;
+
 }
 
 
 }
 
 
@@ -329,12 +408,6 @@ SCPreferencesCreate(CFAllocatorRef         allocator,
                    CFStringRef                 name,
                    CFStringRef                 prefsID)
 {
                    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);
 }
 
        return __SCPreferencesCreate(allocator, name, prefsID, FALSE, NULL);
 }
 
@@ -345,13 +418,6 @@ SCUserPreferencesCreate(CFAllocatorRef                     allocator,
                        CFStringRef                     prefsID,
                        CFStringRef                     user)
 {
                        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);
 }
 
        return __SCPreferencesCreate(allocator, name, prefsID, TRUE, user);
 }
 
@@ -361,3 +427,282 @@ SCPreferencesGetTypeID(void) {
        pthread_once(&initialized, __SCPreferencesInitialize);  /* initialize runtime */
        return __kSCPreferencesTypeID;
 }
        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;
+}
index 1fd06ed1d999cd1526d83cea9281ca2332c6cc3e..2a700dea6b66b22a697708094aeb4b720010a55a 100644 (file)
@@ -77,7 +77,7 @@ normalizePath(CFStringRef path)
 
 
 static Boolean
 
 
 static Boolean
-getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
+getPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef *entity)
 {
        CFStringRef             element;
        CFArrayRef              elements;
 {
        CFStringRef             element;
        CFArrayRef              elements;
@@ -86,7 +86,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
        CFIndex                 nElements;
        CFIndex                 nLinks          = 0;
        Boolean                 ok              = FALSE;
        CFIndex                 nElements;
        CFIndex                 nLinks          = 0;
        Boolean                 ok              = FALSE;
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        CFDictionaryRef         value           = NULL;
 
        elements = normalizePath(path);
        CFDictionaryRef         value           = NULL;
 
        elements = normalizePath(path);
@@ -95,14 +95,15 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
                return FALSE;
        }
 
                return FALSE;
        }
 
+       __SCPreferencesAccess(prefs);
+
     restart :
 
        nElements = CFArrayGetCount(elements);
        for (i = 0; i < nElements; i++) {
                element = CFArrayGetValueAtIndex(elements, i);
                if (i == 0) {
     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);
                                                     CFArrayGetValueAtIndex(elements, 0));
                } else {
                        value = CFDictionaryGetValue(value, element);
@@ -163,7 +164,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
 
 
 static Boolean
 
 
 static Boolean
-setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
+setPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef entity)
 {
        CFStringRef             element;
        CFArrayRef              elements;
 {
        CFStringRef             element;
        CFArrayRef              elements;
@@ -175,7 +176,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
        CFDictionaryRef         node            = NULL;
        CFMutableArrayRef       nodes;
        Boolean                 ok              = FALSE;
        CFDictionaryRef         node            = NULL;
        CFMutableArrayRef       nodes;
        Boolean                 ok              = FALSE;
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
 
        elements = normalizePath(path);
        if (elements == NULL) {
 
        elements = normalizePath(path);
        if (elements == NULL) {
@@ -183,6 +184,8 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
                return FALSE;
        }
 
                return FALSE;
        }
 
+       __SCPreferencesAccess(prefs);
+
     restart :
 
        nElements = CFArrayGetCount(elements);
     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) {
        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);
 
                } 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) {
                element = CFArrayGetValueAtIndex(elements, i);
                if (i == 0) {
                        if (newEntity) {
-                               CFDictionarySetValue(sessionPrivate->prefs, element, newEntity);
+                               CFDictionarySetValue(prefsPrivate->prefs, element, newEntity);
                        } else {
                        } else {
-                               CFDictionaryRemoveValue(sessionPrivate->prefs, element);
+                               CFDictionaryRemoveValue(prefsPrivate->prefs, element);
                        }
                        }
-                       sessionPrivate->changed  = TRUE;
+                       prefsPrivate->changed  = TRUE;
                        ok = TRUE;
                } else {
                        CFMutableDictionaryRef  newNode;
                        ok = TRUE;
                } else {
                        CFMutableDictionaryRef  newNode;
@@ -291,7 +293,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
 
 
 CFStringRef
 
 
 CFStringRef
-SCPreferencesPathCreateUniqueChild(SCPreferencesRef    session,
+SCPreferencesPathCreateUniqueChild(SCPreferencesRef    prefs,
                                   CFStringRef          prefix)
 {
        CFStringRef             child;
                                   CFStringRef          prefix)
 {
        CFStringRef             child;
@@ -300,12 +302,13 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef       session,
        CFUUIDRef               uuid;
        CFDictionaryRef         entity;
 
        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... */
                // if prefix path exists
                if (CFDictionaryContainsKey(entity, kSCResvLink)) {
                        /* the path is a link... */
@@ -328,9 +331,7 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef session,
                                            0,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);
                                            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;
        }
                CFRelease(newPath);
                newPath = NULL;
        }
@@ -341,55 +342,55 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef       session,
 
 
 CFDictionaryRef
 
 
 CFDictionaryRef
-SCPreferencesPathGetValue(SCPreferencesRef     session,
+SCPreferencesPathGetValue(SCPreferencesRef     prefs,
                          CFStringRef           path)
 {
        CFDictionaryRef entity;
        CFStringRef     entityLink;
 
                          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 */
                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;
                }
        }
 
                        /* if it was a bad link */
                        return NULL;
                }
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value = %@"), entity);
        return entity;
 }
 
 
 CFStringRef
        return entity;
 }
 
 
 CFStringRef
-SCPreferencesPathGetLink(SCPreferencesRef      session,
+SCPreferencesPathGetLink(SCPreferencesRef      prefs,
                         CFStringRef            path)
 {
        CFDictionaryRef entity;
        CFStringRef     entityLink;
 
                         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 */
                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;
        }
 
                return entityLink;
        }
 
@@ -398,16 +399,16 @@ SCPreferencesPathGetLink(SCPreferencesRef session,
 
 
 Boolean
 
 
 Boolean
-SCPreferencesPathSetValue(SCPreferencesRef     session,
+SCPreferencesPathSetValue(SCPreferencesRef     prefs,
                          CFStringRef           path,
                          CFDictionaryRef       value)
 {
        Boolean                 ok;
 
                          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) {
        }
 
        if (!value) {
@@ -415,13 +416,13 @@ SCPreferencesPathSetValue(SCPreferencesRef        session,
                return FALSE;
        }
 
                return FALSE;
        }
 
-       ok = setPath(session, path, value);
+       ok = setPath(prefs, path, value);
        return ok;
 }
 
 
 Boolean
        return ok;
 }
 
 
 Boolean
-SCPreferencesPathSetLink(SCPreferencesRef      session,
+SCPreferencesPathSetLink(SCPreferencesRef      prefs,
                         CFStringRef            path,
                         CFStringRef            link)
 {
                         CFStringRef            path,
                         CFStringRef            link)
 {
@@ -429,10 +430,10 @@ SCPreferencesPathSetLink(SCPreferencesRef session,
        CFDictionaryRef         entity;
        Boolean                 ok;
 
        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) {
        }
 
        if (!link) {
@@ -440,7 +441,7 @@ SCPreferencesPathSetLink(SCPreferencesRef   session,
                return FALSE;
        }
 
                return FALSE;
        }
 
-       if (!getPath(session, link, &entity)) {
+       if (!getPath(prefs, link, &entity)) {
                // if bad link
                return FALSE;
        }
                // if bad link
                return FALSE;
        }
@@ -450,7 +451,7 @@ SCPreferencesPathSetLink(SCPreferencesRef   session,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
        CFDictionaryAddValue(dict, kSCResvLink, link);
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
        CFDictionaryAddValue(dict, kSCResvLink, link);
-       ok = setPath(session, path, dict);
+       ok = setPath(prefs, path, dict);
        CFRelease(dict);
 
        return ok;
        CFRelease(dict);
 
        return ok;
@@ -458,19 +459,20 @@ SCPreferencesPathSetLink(SCPreferencesRef session,
 
 
 Boolean
 
 
 Boolean
-SCPreferencesPathRemoveValue(SCPreferencesRef  session,
+SCPreferencesPathRemoveValue(SCPreferencesRef  prefs,
                             CFStringRef        path)
 {
        CFArrayRef              elements        = NULL;
        Boolean                 ok              = FALSE;
        CFDictionaryRef         value;
 
                             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;
        }
                // if no such path
                return FALSE;
        }
@@ -481,7 +483,7 @@ SCPreferencesPathRemoveValue(SCPreferencesRef       session,
                return FALSE;
        }
 
                return FALSE;
        }
 
-       ok = setPath(session, path, NULL);
+       ok = setPath(prefs, path, NULL);
 
        CFRelease(elements);
        return ok;
 
        CFRelease(elements);
        return ok;
index 1de5c1df617dd16323972422eeaa764da237f9cb..9d7c73aec67a822def32b47f2cb3426ef2c2aea0 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
 #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;
        }
 
                _SCErrorSet(kSCStatusNoKey);
                return FALSE;
        }
 
-       CFDictionaryRemoveValue(sessionPrivate->prefs, key);
-       sessionPrivate->changed  = TRUE;
+       CFDictionaryRemoveValue(prefsPrivate->prefs, key);
+       prefsPrivate->changed  = TRUE;
        return TRUE;
 }
        return TRUE;
 }
index c5f6c3fb9fe300ba0bdd21422ace9330eda7f16e..ed4befffdd5ec29d44d165eaae9be165a3d8c475 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
 #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;
 }
        return TRUE;
 }
index c41ee1022a59a0ed2c0528eab4cf1102ac3c4a00..6b07676e8fc762dab6d91ae9b0e84e37d49904e9 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
 #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;
        }
 
                /* 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;
        }
 
                /* 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:
 
                return FALSE;
        }
 
     perUser:
 
-       sessionPrivate->locked = FALSE;
+       prefsPrivate->locked = FALSE;
        return TRUE;
 }
        return TRUE;
 }
index aaebc2a4b90d2911bcf461e917e1a86dd36f0ac5..b71d33dd26ae7e254c706831533040d5063317cd 100644 (file)
 
 
 #include <sys/cdefs.h>
 
 
 #include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 /*!
        @header SCPreferences
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 /*!
        @header SCPreferences
-       The SCPreferencesXXX() APIs allow an application to load and
-       store XML configuration data in a controlled manner and provide
-       the necessary notifications to other applications that need to
-       be aware of configuration changes.
-
-       The stored XML configuration data is accessed using a prefsID. A
-       NULL value indicates that the default system preferences are to
-       be accessed.
-       A string which starts with a leading "/" character specifies the
-       path to the file containing te preferences to be accessed.
-       A string which does not start with a leading "/" character
-       specifies a file relative to the default system preferences
-       directory.
+       @discussion The SCPreferences API allows an application to load and
+               store XML configuration data in a controlled manner and provide
+               the necessary notifications to other applications that need to
+               be aware of configuration changes.
+
+               To access configuration preferences, you must first establish a
+               preferences session using the SCPreferencesCreate function.
+               To identify a specific set of preferences to access, you pass a
+               value in the prefsID parameter.
+               A NULL value indicates that the default system preferences are
+               to be accessed.
+               A string that starts with a leading "/" character specifies
+               the absolute path to the file containing the preferences to
+               be accessed.
+               A string that does not start with a leading "/" character
+               specifies a file relative to the default system preferences
+               directory.
+
+               When you are finished with the preferences session, use
+               CFRelease to close it.
  */
 
 
 /*!
        @typedef SCPreferencesRef
  */
 
 
 /*!
        @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;
 
                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
 
 __BEGIN_DECLS
 
 /*!
        @function SCPreferencesGetTypeID
-       Returns the type identifier of all SCPreferences instances.
+       @discussion Returns the type identifier of all SCPreferences instances.
  */
 CFTypeID
 SCPreferencesGetTypeID         (void);
 
  */
 CFTypeID
 SCPreferencesGetTypeID         (void);
 
-
 /*!
        @function SCPreferencesCreate
        @discussion Initiates access to the per-system set of configuration
                preferences.
 /*!
        @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
        @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            (
  */
 SCPreferencesRef
 SCPreferencesCreate            (
@@ -91,120 +159,116 @@ SCPreferencesCreate              (
        @function SCPreferencesLock
        @discussion Locks access to the configuration preferences.
 
        @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.
        @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              (
  */
 Boolean
 SCPreferencesLock              (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                Boolean                 wait
                                );
 
 /*!
        @function SCPreferencesCommitChanges
        @discussion Commits changes made to the configuration preferences to
                                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     (
  */
 Boolean
 SCPreferencesCommitChanges     (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesApplyChanges
        @discussion Requests that the currently stored configuration
                preferences be applied to the active configuration.
                                );
 
 /*!
        @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      (
  */
 Boolean
 SCPreferencesApplyChanges      (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesUnlock
        @discussion Releases exclusive access to the configuration preferences.
 
                                );
 
 /*!
        @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            (
  */
 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.
                                );
 
 /*!
        @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      (
  */
 CFDataRef
 SCPreferencesGetSignature      (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesCopyKeyList
        @discussion Returns an array of currently defined preference keys.
                                );
 
 /*!
        @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       (
  */
 CFArrayRef
 SCPreferencesCopyKeyList       (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesGetValue
        @discussion Returns the data associated with a preference key.
 
                                );
 
 /*!
        @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.
        @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          (
  */
 CFPropertyListRef
 SCPreferencesGetValue          (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key
                                );
 
                                CFStringRef             key
                                );
 
@@ -212,20 +276,20 @@ SCPreferencesGetValue             (
        @function SCPreferencesAddValue
        @discussion Adds data for a preference key.
 
        @function SCPreferencesAddValue
        @discussion Adds data for a preference key.
 
-       This function associates new data with the specified key. In order
-       to commit these changes to permanent storage a call must be made to
-       SCPreferencesCommitChanges().
-       @param session The SCPreferencesRef handle that should be used to
-               communicate with the APIs.
+               This function associates new data with the specified key.
+               To commit these changes to permanent storage, a call must
+               be made to the SCPreferencesCommitChanges function.
+       @param prefs The preferences session.
        @param key The preference key to be updated.
        @param value The CFPropertyListRef object containing the
                value to be associated with the specified preference key.
        @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          (
                if an error occurred.
  */
 Boolean
 SCPreferencesAddValue          (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key,
                                CFPropertyListRef       value
                                );
                                CFStringRef             key,
                                CFPropertyListRef       value
                                );
@@ -234,19 +298,19 @@ SCPreferencesAddValue             (
        @function SCPreferencesSetValue
        @discussion Updates the data associated with a preference key.
 
        @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.
        @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          (
  */
 Boolean
 SCPreferencesSetValue          (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key,
                                CFPropertyListRef       value
                                );
                                CFStringRef             key,
                                CFPropertyListRef       value
                                );
@@ -255,21 +319,96 @@ SCPreferencesSetValue             (
        @function SCPreferencesRemoveValue
        @discussion Removes the data associated with a preference key.
 
        @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.
        @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       (
  */
 Boolean
 SCPreferencesRemoveValue       (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key
                                );
 
                                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 */
 __END_DECLS
 
 #endif /* _SCPREFERENCES_H */
diff --git a/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h b/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h
new file mode 100644 (file)
index 0000000..d0d56e8
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPreferences.h>
+
+
+/*!
+       @header SCPreferencesGetSpecificPrivate
+       @discussion The functions in the SCPreferencesGetSpecificPrivate API allow
+               an application to get specific configuration information
+               about the current system (for example, the host name).
+
+               To access configuration preferences, you must first establish
+               a preferences session using the SCPreferencesCreate function.
+ */
+
+
+__BEGIN_DECLS
+
+/*!
+       @function SCPreferencesGetHostName
+       @discussion Gets the host name preference.
+       @param prefs The preferences session.
+       @result name The host name to be set;
+               NULL if the name has not been set or if an error was encountered.
+ */
+CFStringRef
+SCPreferencesGetHostName               (
+                                       SCPreferencesRef        prefs
+                                       );
+
+__END_DECLS
+
+#endif /* _SCPREFERENCESGETSPECIFICPRIVATE_H */
index b1f669d3f1c80f8edb3dea8b07099abbd9e155fe..971cae9af80255c42efb2d246a690fe500a1129b 100644 (file)
@@ -48,6 +48,9 @@ typedef struct {
        /* base CFType information */
        CFRuntimeBase           cfBase;
 
        /* base CFType information */
        CFRuntimeBase           cfBase;
 
+       /* lock */
+       pthread_mutex_t         lock;
+
        /* session name */
        CFStringRef             name;
 
        /* session name */
        CFStringRef             name;
 
@@ -58,7 +61,7 @@ typedef struct {
        Boolean                 perUser;
        CFStringRef             user;
 
        Boolean                 perUser;
        CFStringRef             user;
 
-       /* configuration file path */
+       /* configuration file */
        char                    *path;
        char                    *newPath;
 
        char                    *path;
        char                    *newPath;
 
@@ -73,6 +76,12 @@ typedef struct {
        CFStringRef             sessionKeyCommit;
        CFStringRef             sessionKeyApply;
 
        CFStringRef             sessionKeyCommit;
        CFStringRef             sessionKeyApply;
 
+       /* run loop source, callout, context, rl scheduling info */
+       CFRunLoopSourceRef      rls;
+       SCPreferencesCallBack   rlsFunction;
+       SCPreferencesContext    rlsContext;
+       CFMutableArrayRef       rlList;
+
        /* preferences */
        CFMutableDictionaryRef  prefs;
 
        /* preferences */
        CFMutableDictionaryRef  prefs;
 
@@ -103,6 +112,12 @@ __SCPreferencesCreate                      (CFAllocatorRef         allocator,
                                         Boolean                perUser,
                                         CFStringRef            user);
 
                                         Boolean                perUser,
                                         CFStringRef            user);
 
+Boolean
+__SCPreferencesAccess                  (SCPreferencesRef       prefs);
+
+Boolean
+__SCPreferencesAddSession              (SCPreferencesRef       prefs);
+
 CFDataRef
 __SCPSignatureFromStatbuf              (const struct stat      *statBuf);
 
 CFDataRef
 __SCPSignatureFromStatbuf              (const struct stat      *statBuf);
 
index e3a85cd272f2fc7b2dc732ebf3800aa8b1324d59..7db6e6a1c8ef8081f6c08c2f044c97dc16aab56e 100644 (file)
 
 /*!
        @header SCPreferencesPath
 
 /*!
        @header SCPreferencesPath
-       The SCPreferencesPathXXX() APIs allow an application to
-       load and store XML configuration data in a controlled
-       manner and provide the necessary notifications to other
-       applications that need to be aware of configuration
-       changes.
-
-       The SCPreferencesPathXXX() APIs make certain assumptions
-       about the layout of the preferences data.  These APIs view
-       the data as a collection of dictionaries of key/value pairs
-       and an associated path name.  The root path ("/") identifies
-       the top-level dictionary.  Additional path components
-       specify the keys for sub-dictionaries.
-
-       For example, the following dictionary can be accessed via
-       two paths.  The root ("/") path would return a dictionary
-       with all keys and values.  The path "/path1" would only
-       return the dictionary with the "key3" and "key4" properties.
-
-       <PRE>
-       <BR>    &lt;dict&gt;
-       <BR>        &lt;key&gt;key1&lt;/key&gt;
-       <BR>        &lt;string&gt;val1&lt;/string&gt;
-       <BR>        &lt;key&gt;key2&lt;/key&gt;
-       <BR>        &lt;string&gt;val2&lt;/string&gt;
-       <BR>        &lt;key&gt;path1&lt;/key&gt;
-       <BR>        &lt;dict&gt;
-       <BR>            &lt;key&gt;key3&lt;/key&gt;
-       <BR>            &lt;string&gt;val3&lt;/string&gt;
-       <BR>        &lt;key&gt;key4&lt;/key&gt;
-       <BR>        &lt;string&gt;val4&lt;/string&gt;
-       <BR>        &lt;/dict&gt;
-       <BR>    &lt;/dict&gt;
-       </PRE>
-
-       Each dictionary can also include the kSCResvLink key.  The
-       value associated with this key is interpreted as a "link" to
+       @discussion The SCPreferencesPath API allows an application to
+               load and store XML configuration data in a controlled
+               manner and provide the necessary notifications to other
+               applications that need to be aware of configuration
+               changes.
+
+               The functions in the SCPreferencesPath API make certain
+               assumptions about the layout of the preferences data.
+               These functions view the data as a collection of dictionaries
+               of key-value pairs and an associated path name.
+               The root path ("/") identifies the top-level dictionary.
+               Additional path components specify the keys for subdictionaries.
+
+               For example, the following dictionary can be accessed via
+               two paths.  The root ("/") path would return a dictionary
+               with all keys and values.  The path "/path1" would only
+               return the dictionary with the "key3" and "key4" properties.
+
+       <pre>
+       @textblock
+       <dict>
+               <key>key1</key>
+               <string>val1</string>
+               <key>key2</key>
+               <string>val2</string>
+               <key>path1</key>
+               <dict>
+                       <key>key3</key>
+                       <string>val3</string>
+                       <key>key4</key>
+                       <string>val4</string>
+               </dict>
+       </dict>
+       @/textblock
+       </pre>
+
+       Each dictionary can also include the kSCResvLink ("__LINK__") key.
+       The value associated with this key is interpreted as a link to
        another path.  If this key is present, a call to the
        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.
  */
 
        specified by the link.
  */
 
@@ -79,15 +81,14 @@ __BEGIN_DECLS
        @function SCPreferencesPathCreateUniqueChild
        @discussion Creates a new path component within the dictionary
                hierarchy.
        @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.
        @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     (
                if the specified path does not exist.
  */
 CFStringRef
 SCPreferencesPathCreateUniqueChild     (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             prefix
                                        );
 
                                        CFStringRef             prefix
                                        );
 
@@ -95,15 +96,14 @@ SCPreferencesPathCreateUniqueChild  (
        @function SCPreferencesPathGetValue
        @discussion Returns the dictionary associated with the specified
                path.
        @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.
        @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              (
                if the path does not exist.
  */
 CFDictionaryRef
 SCPreferencesPathGetValue              (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path
                                        );
 
                                        CFStringRef             path
                                        );
 
@@ -111,31 +111,29 @@ SCPreferencesPathGetValue         (
        @function SCPreferencesPathGetLink
        @discussion Returns the link (if one exists) associated with the
                specified path.
        @function SCPreferencesPathGetLink
        @discussion Returns the link (if one exists) associated with the
                specified path.
-       @param session The SCPreferencesRef handle that should be used to
-        communicate with the APIs.
+       @param prefs The preferences session.
        @param path A string that represents the path to be returned.
        @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               (
                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.
                                        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.
        @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              (
  */
 Boolean
 SCPreferencesPathSetValue              (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path,
                                        CFDictionaryRef         value
                                        );
                                        CFStringRef             path,
                                        CFDictionaryRef         value
                                        );
@@ -144,16 +142,15 @@ SCPreferencesPathSetValue         (
        @function SCPreferencesPathSetLink
        @discussion Associates a link to a second dictionary at the
                specified path.
        @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.
        @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               (
  */
 Boolean
 SCPreferencesPathSetLink               (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path,
                                        CFStringRef             link
                                        );
                                        CFStringRef             path,
                                        CFStringRef             link
                                        );
@@ -161,14 +158,13 @@ SCPreferencesPathSetLink          (
 /*!
        @function SCPreferencesPathRemoveValue
        @discussion Removes the data associated with the specified path.
 /*!
        @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.
        @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           (
  */
 Boolean
 SCPreferencesPathRemoveValue           (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path
                                        );
 
                                        CFStringRef             path
                                        );
 
diff --git a/SystemConfiguration.fproj/SCPreferencesPathKey.c b/SystemConfiguration.fproj/SCPreferencesPathKey.c
new file mode 100644 (file)
index 0000000..ef4df79
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <SystemConfiguration/SystemConfiguration.h>
+
+#include <stdarg.h>
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreate(CFAllocatorRef      allocator,
+                          CFStringRef          fmt,
+                          ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       return (CFStringCreateWithFormatAndArguments(allocator,
+                                                    NULL,
+                                                    fmt,
+                                                    args));
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateNetworkServices(CFAllocatorRef       allocator)
+{
+       /*
+        * create "/NetworkServices"
+        */
+       return CFStringCreateWithFormat(allocator,
+                                       NULL,
+                                       CFSTR("/%@"),
+                                       kSCPrefNetworkServices);
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateNetworkServiceEntity(CFAllocatorRef  allocator,
+                                              CFStringRef      service,
+                                              CFStringRef      entity)
+{
+       CFStringRef path;
+
+       if (entity == NULL) {
+               /*
+                * create "/NetworkServices/service-id"
+                */
+               path = CFStringCreateWithFormat(allocator,
+                                               NULL,
+                                               CFSTR("/%@/%@"),
+                                               kSCPrefNetworkServices,
+                                               service);
+       } else {
+               /*
+                * create "/NetworkServices/service-id/entity"
+                */
+               path = CFStringCreateWithFormat(allocator,
+                                               NULL,
+                                               CFSTR("/%@/%@/%@"),
+                                               kSCPrefNetworkServices,
+                                               service,
+                                               entity);
+       }
+
+       return path;
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSets(CFAllocatorRef  allocator)
+{
+       /*
+        * create "/Sets"
+        */
+       return (CFStringCreateWithFormat(allocator,
+                                        NULL,
+                                        CFSTR("/%@"),
+                                        kSCPrefSets));
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSet(CFAllocatorRef   allocator,
+                             CFStringRef       set)
+{
+       /*
+        * create "/Sets/set-id"
+        */
+       return (CFStringCreateWithFormat(allocator,
+                                        NULL,
+                                        CFSTR("/%@/%@"),
+                                        kSCPrefSets,
+                                        set));
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkGlobalEntity(CFAllocatorRef        allocator,
+                                             CFStringRef       set,
+                                             CFStringRef       entity)
+{
+       /*
+        * create "/Sets/set-id/Network/Global/entity"
+        */
+       return CFStringCreateWithFormat(allocator,
+                                       NULL,
+                                       CFSTR("/%@/%@/%@/%@/%@"),
+                                       kSCPrefSets,
+                                       set,
+                                       kSCCompNetwork,
+                                       kSCCompGlobal,
+                                       entity);
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(CFAllocatorRef     allocator,
+                                                CFStringRef    set,
+                                                CFStringRef    ifname,
+                                                CFStringRef    entity)
+{
+       /*
+        * create "/Sets/set-id/Network/Interface/interface-name/entity"
+        */
+       return CFStringCreateWithFormat(allocator,
+                                       NULL,
+                                       CFSTR("/%@/%@/%@/%@/%@/%@"),
+                                       kSCPrefSets,
+                                       set,
+                                       kSCCompNetwork,
+                                       kSCCompInterface,
+                                       ifname,
+                                       entity);
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkService(CFAllocatorRef     allocator,
+                                           CFStringRef         set,
+                                           CFStringRef         service)
+{
+       CFStringRef path;
+
+       if (service == NULL) {
+               /*
+                * create "/Sets/set-id/Network/Service"
+                */
+               path = CFStringCreateWithFormat(allocator,
+                                               NULL,
+                                               CFSTR("/%@/%@/%@/%@"),
+                                               kSCPrefSets,
+                                               set,
+                                               kSCCompNetwork,
+                                               kSCCompService);
+       } else {
+               /*
+                * create "/Sets/set-id/Network/Service/service-id"
+                */
+               path = CFStringCreateWithFormat(allocator,
+                                               NULL,
+                                               CFSTR("/%@/%@/%@/%@/%@"),
+                                               kSCPrefSets,
+                                               set,
+                                               kSCCompNetwork,
+                                               kSCCompService,
+                                               service);
+       }
+
+       return path;
+}
+
+
+__private_extern__ CFStringRef
+SCPreferencesPathKeyCreateSetNetworkServiceEntity(CFAllocatorRef       allocator,
+                                                 CFStringRef           set,
+                                                 CFStringRef           service,
+                                                 CFStringRef           entity)
+{
+       CFStringRef path;
+
+       if (entity == NULL) {
+               /*
+                * create "/Sets/set-id/Network/Service/service-id"
+                */
+               path = CFStringCreateWithFormat(allocator,
+                                               NULL,
+                                               CFSTR("/%@/%@/%@/%@/%@"),
+                                               kSCPrefSets,
+                                               set,
+                                               kSCCompNetwork,
+                                               kSCCompService,
+                                               service);
+       } else {
+               /*
+                * create "/Sets/set-id/Network/Service/service-id/entity"
+                */
+               path = CFStringCreateWithFormat(allocator,
+                                               NULL,
+                                               CFSTR("/%@/%@/%@/%@/%@/%@"),
+                                               kSCPrefSets,
+                                               set,
+                                               kSCCompNetwork,
+                                               kSCCompService,
+                                               service,
+                                               entity);
+       }
+
+       return path;
+}
diff --git a/SystemConfiguration.fproj/SCPreferencesPathKey.h b/SystemConfiguration.fproj/SCPreferencesPathKey.h
new file mode 100644 (file)
index 0000000..67592cb
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <AvailabilityMacros.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+
+/*!
+       @header SCPreferencesPathKey
+ */
+
+
+__BEGIN_DECLS
+
+/*
+ * SCPreferencesPathKeyCreate*
+ * - convenience routines that create a CFString key for an item in the store
+ */
+
+/*!
+       @function SCPreferencesPathKeyCreate
+       @discussion Creates a preferences path key using the given format.
+ */
+CFStringRef
+SCPreferencesPathKeyCreate                     (
+                                               CFAllocatorRef  allocator,
+                                               CFStringRef     fmt,
+                                               ...
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateNetworkServices
+ */
+CFStringRef
+SCPreferencesPathKeyCreateNetworkServices      (
+                                               CFAllocatorRef  allocator
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateNetworkServiceEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateNetworkServiceEntity (
+                                               CFAllocatorRef  allocator,
+                                               CFStringRef     service,
+                                               CFStringRef     entity
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateSets
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSets                 (
+                                               CFAllocatorRef  allocator
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateSet
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSet                  (
+                                               CFAllocatorRef  allocator,
+                                               CFStringRef     set
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateSetNetworkInterfaceEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkInterfaceEntity(
+                                                  CFAllocatorRef       allocator,
+                                                  CFStringRef  set,
+                                                  CFStringRef  ifname,
+                                                  CFStringRef  entity
+                                                  )                            AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateSetNetworkGlobalEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkGlobalEntity(
+                                               CFAllocatorRef  allocator,
+                                               CFStringRef     set,
+                                               CFStringRef     entity
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateSetNetworkService
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkService     (
+                                               CFAllocatorRef  allocator,
+                                               CFStringRef     set,
+                                               CFStringRef     service
+                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesPathKeyCreateSetNetworkServiceEntity
+ */
+CFStringRef
+SCPreferencesPathKeyCreateSetNetworkServiceEntity(
+                                                CFAllocatorRef allocator,
+                                                CFStringRef    set,
+                                                CFStringRef    service,
+                                                CFStringRef    entity
+                                                )                              AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+__END_DECLS
+
+#endif /* _SCPREFERENCESPATHKEY_H */
index 23c37efd4115d060b982ee2ff88f7ac337f30103..3b687ce9aabe3f5965ea1fa25e118f71883609cd 100644 (file)
 #ifndef _SCPREFERENCESPRIVATE_H
 #define _SCPREFERENCESPRIVATE_H
 
 #ifndef _SCPREFERENCESPRIVATE_H
 #define _SCPREFERENCESPRIVATE_H
 
+
+#include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCPreferences.h>
 
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCPreferences.h>
 
 
+/*!
+       @header SCPreferencesPrivate
+ */
+
 /*!
        @enum SCPreferencesKeyType
        @discussion Used with the SCDynamicStoreKeyCreatePreferences() function
 /*!
        @enum SCPreferencesKeyType
        @discussion Used with the SCDynamicStoreKeyCreatePreferences() function
@@ -46,6 +53,7 @@ enum {
 };
 typedef        int32_t SCPreferencesKeyType;
 
 };
 typedef        int32_t SCPreferencesKeyType;
 
+
 __BEGIN_DECLS
 
 /*!
 __BEGIN_DECLS
 
 /*!
@@ -65,7 +73,7 @@ SCDynamicStoreKeyCreatePreferences    (
                                        CFAllocatorRef          allocator,
                                        CFStringRef             prefsID,
                                        SCPreferencesKeyType    keyType
                                        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                        (
 
 SCPreferencesRef
 SCUserPreferencesCreate                        (
index 4ff04ea5152f5a28e2fdf6ca8065bf25035f226f..6cce489d139f5b0f1013237793dd02c996021d91 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 /*!
        @header SCPreferencesSetSpecific
 
 /*!
        @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
 
 /*!
        @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           (
  */
 Boolean
 SCPreferencesSetComputerName           (
@@ -61,18 +65,18 @@ SCPreferencesSetComputerName                (
 
 /*!
        @function SCPreferencesSetLocalHostName
 
 /*!
        @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.
 
        @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).
                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          (
  */
 Boolean
 SCPreferencesSetLocalHostName          (
diff --git a/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h b/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h
new file mode 100644 (file)
index 0000000..51e4c7e
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPreferences.h>
+
+
+/*!
+       @header SCPreferencesSetSpecificPrivate
+       @discussion The functions in the SCPreferencesSetSpecificPrivate API allow
+               an application to set specific configuration information
+               about the current system (for example, the computer or
+               sharing name).
+
+               To access configuration preferences, you must first establish
+               a preferences session using the SCPreferencesCreate function.
+ */
+
+
+__BEGIN_DECLS
+
+/*!
+       @function SCPreferencesSetHostName
+       @discussion Updates the host name preference.
+
+               Note: To commit these changes to permanent storage you must
+               call the SCPreferencesCommitChanges function.
+               In addition, you must call the SCPreferencesApplyChanges
+               function for the new name to become active.
+       @param prefs The preferences session.
+       @param name The host name to be set.
+       @result Returns TRUE if successful; FALSE otherwise.
+ */
+Boolean
+SCPreferencesSetHostName               (
+                                       SCPreferencesRef        prefs,
+                                       CFStringRef             name
+                                       );
+
+__END_DECLS
+
+#endif /* _SCPREFERENCESSETSPECIFICPRIVATE_H */
index 5ee8e130d804a938daba05a74aa23b3dd78c6407..1b1d0a5aa4f7cc140f9c9b34110895a7952bfb8f 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -25,6 +25,8 @@
 #define _SCPRIVATE_H
 
 #include <sys/cdefs.h>
 #define _SCPRIVATE_H
 
 #include <sys/cdefs.h>
+#include <sys/syslog.h>
+#include <mach/message.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 
 
 #include <CoreFoundation/CoreFoundation.h>
 
 #include <SystemConfiguration/SCDynamicStoreSetSpecificPrivate.h>
 
 #include <SystemConfiguration/SCPreferencesPrivate.h>
 #include <SystemConfiguration/SCDynamicStoreSetSpecificPrivate.h>
 
 #include <SystemConfiguration/SCPreferencesPrivate.h>
+#include <SystemConfiguration/SCPreferencesGetSpecificPrivate.h>
+#include <SystemConfiguration/SCPreferencesSetSpecificPrivate.h>
+
+/*!
+       @header SCPrivate
+ */
 
 /* framework variables */
 extern Boolean _sc_debug;      /* TRUE if debugging enabled */
 
 /* framework variables */
 extern Boolean _sc_debug;      /* TRUE if debugging enabled */
@@ -43,19 +51,19 @@ __BEGIN_DECLS
 
 /*!
        @function _SCErrorSet
 
 /*!
        @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);
 
  */
 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.
        @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
  */
        @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);
 
                                                 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
        @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".
        @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);
 
                                                 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.
        @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
  */
        @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);
 
                                                 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
        @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".
        @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);
 
                                                 void                   *dataRef,
                                                 CFIndex                dataLen);
 
-/*
+/*!
        @function _SCSerializeData
        @discussion Serialize a CFData object for passing
                to/from configd.
        @param data CFData key to serialize
        @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
  */
        @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);
 
                                                 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.
        @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);
 
        @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
        @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);
 
  */
 CFDictionaryRef        _SCSerializeMultiple            (CFDictionaryRef        dict);
 
-/*
+/*!
        @function _SCUnserializeMultiple
        @discussion Convert a CFDictionary containing a set of CFData
                values into a CFDictionary containing a set of serialized
        @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);
 
  */
 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.
        @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.
                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);
 
                                                 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
        @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,
                                                 ...);
 
                                                 CFStringRef            formatString,
                                                 ...);
 
-/*
+/*!
        @function SCPrint
        @discussion Conditionally issue a debug message.
        @param condition A boolean value indicating if the message should be written
        @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,
                                                 ...);
 
                                                 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
        @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,
                                                 ...);
 
                                                 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 */
 __END_DECLS
 
 #endif /* _SCPRIVATE_H */
index 85f55ebcafa0547d2669969b60741dfc4681f822..9caf2cd29ab09630e925e82d2aa4414795cf6fad 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -32,6 +32,9 @@
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
+#include <netdb.h>
+
+
 CFStringRef
 SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator)
 {
 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
 SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
 {
-       CFDictionaryRef         dict            = NULL;
+       CFArrayRef              array;
        CFStringRef             key;
        CFStringRef             key;
-       CFDictionaryRef         proxies         = NULL;
+       CFMutableDictionaryRef  newProxies      = NULL;
+       CFNumberRef             num;
+       CFDictionaryRef         proxies;
        Boolean                 tempSession     = FALSE;
 
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+
+
+       /* copy proxy information from dynamic store */
+
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyProxies"),
                                             NULL,
                                             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;
        }
 
                        return NULL;
                }
                tempSession = TRUE;
        }
 
-       key  = SCDynamicStoreKeyCreateProxies(NULL);
-       dict = SCDynamicStoreCopyValue(store, key);
+       key = SCDynamicStoreKeyCreateProxies(NULL);
+       proxies = SCDynamicStoreCopyValue(store, key);
        CFRelease(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 (tempSession)        CFRelease(store);
-       if (dict)               CFRelease(dict);
        return proxies;
 }
        return proxies;
 }
diff --git a/SystemConfiguration.fproj/SCSchemaDefinitions.c b/SystemConfiguration.fproj/SCSchemaDefinitions.c
new file mode 100644 (file)
index 0000000..f7d2d40
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * This file is automatically generated
+ * DO NOT EDIT!
+ */
+
+#include <CoreFoundation/CFString.h>
+
+const CFStringRef kSCResvLink                                      = CFSTR("__LINK__");
+const CFStringRef kSCResvInactive                                  = CFSTR("__INACTIVE__");
+const CFStringRef kSCPropInterfaceName                             = CFSTR("InterfaceName");
+const CFStringRef kSCPropMACAddress                                = CFSTR("MACAddress");
+const CFStringRef kSCPropUserDefinedName                           = CFSTR("UserDefinedName");
+const CFStringRef kSCPropVersion                                   = CFSTR("Version");
+const CFStringRef kSCPrefCurrentSet                                = CFSTR("CurrentSet");
+const CFStringRef kSCPrefNetworkServices                           = CFSTR("NetworkServices");
+const CFStringRef kSCPrefSets                                      = CFSTR("Sets");
+const CFStringRef kSCPrefSystem                                    = CFSTR("System");
+const CFStringRef kSCCompNetwork                                   = CFSTR("Network");
+const CFStringRef kSCCompService                                   = CFSTR("Service");
+const CFStringRef kSCCompGlobal                                    = CFSTR("Global");
+const CFStringRef kSCCompHostNames                                 = CFSTR("HostNames");
+const CFStringRef kSCCompInterface                                 = CFSTR("Interface");
+const CFStringRef kSCCompSystem                                    = CFSTR("System");
+const CFStringRef kSCCompUsers                                     = CFSTR("Users");
+const CFStringRef kSCCompAnyRegex                                  = CFSTR("[^/]+");
+const CFStringRef kSCEntNetAirPort                                 = CFSTR("AirPort");
+const CFStringRef kSCEntNetAppleTalk                               = CFSTR("AppleTalk");
+const CFStringRef kSCEntNetDHCP                                    = CFSTR("DHCP");
+const CFStringRef kSCEntNetDNS                                     = CFSTR("DNS");
+const CFStringRef kSCEntNetEthernet                                = CFSTR("Ethernet");
+const CFStringRef kSCEntNetFireWire                                = CFSTR("FireWire");
+const CFStringRef kSCEntNetInterface                               = CFSTR("Interface");
+const CFStringRef kSCEntNetIPv4                                    = CFSTR("IPv4");
+const CFStringRef kSCEntNetIPv6                                    = CFSTR("IPv6");
+const CFStringRef kSCEntNetL2TP                                    = CFSTR("L2TP");
+const CFStringRef kSCEntNetLink                                    = CFSTR("Link");
+const CFStringRef kSCEntNetModem                                   = CFSTR("Modem");
+const CFStringRef kSCEntNetNetInfo                                 = CFSTR("NetInfo");
+const CFStringRef kSCEntNetPPP                                     = CFSTR("PPP");
+const CFStringRef kSCEntNetPPPoE                                   = CFSTR("PPPoE");
+const CFStringRef kSCEntNetPPPSerial                               = CFSTR("PPPSerial");
+const CFStringRef kSCEntNetPPTP                                    = CFSTR("PPTP");
+const CFStringRef kSCEntNetProxies                                 = CFSTR("Proxies");
+const CFStringRef kSCEntNet6to4                                    = CFSTR("6to4");
+const CFStringRef kSCPropNetOverridePrimary                        = CFSTR("OverridePrimary");
+const CFStringRef kSCPropNetServiceOrder                           = CFSTR("ServiceOrder");
+const CFStringRef kSCPropNetPPPOverridePrimary                     = CFSTR("PPPOverridePrimary");
+const CFStringRef kSCPropNetInterfaces                             = CFSTR("Interfaces");
+const CFStringRef kSCPropNetLocalHostName                          = CFSTR("LocalHostName");
+const CFStringRef kSCPropNetAirPortAllowNetCreation                = CFSTR("AllowNetCreation");
+const CFStringRef kSCPropNetAirPortAuthPassword                    = CFSTR("AuthPassword");
+const CFStringRef kSCPropNetAirPortAuthPasswordEncryption          = CFSTR("AuthPasswordEncryption");
+const CFStringRef kSCPropNetAirPortJoinMode                        = CFSTR("JoinMode");
+const CFStringRef kSCPropNetAirPortPowerEnabled                    = CFSTR("PowerEnabled");
+const CFStringRef kSCPropNetAirPortPreferredNetwork                = CFSTR("PreferredNetwork");
+const CFStringRef kSCPropNetAirPortSavePasswords                   = CFSTR("SavePasswords");
+const CFStringRef kSCValNetAirPortJoinModeAutomatic                = CFSTR("Automatic");
+const CFStringRef kSCValNetAirPortJoinModePreferred                = CFSTR("Preferred");
+const CFStringRef kSCValNetAirPortJoinModeRecent                   = CFSTR("Recent");
+const CFStringRef kSCValNetAirPortJoinModeStrongest                = CFSTR("Strongest");
+const CFStringRef kSCValNetAirPortAuthPasswordEncryptionKeychain   = CFSTR("Keychain");
+const CFStringRef kSCPropNetAppleTalkComputerName                  = CFSTR("ComputerName");
+const CFStringRef kSCPropNetAppleTalkComputerNameEncoding          = CFSTR("ComputerNameEncoding");
+const CFStringRef kSCPropNetAppleTalkConfigMethod                  = CFSTR("ConfigMethod");
+const CFStringRef kSCPropNetAppleTalkDefaultZone                   = CFSTR("DefaultZone");
+const CFStringRef kSCPropNetAppleTalkNetworkID                     = CFSTR("NetworkID");
+const CFStringRef kSCPropNetAppleTalkNetworkRange                  = CFSTR("NetworkRange");
+const CFStringRef kSCPropNetAppleTalkNodeID                        = CFSTR("NodeID");
+const CFStringRef kSCPropNetAppleTalkSeedNetworkRange              = CFSTR("SeedNetworkRange");
+const CFStringRef kSCPropNetAppleTalkSeedZones                     = CFSTR("SeedZones");
+const CFStringRef kSCValNetAppleTalkConfigMethodNode               = CFSTR("Node");
+const CFStringRef kSCValNetAppleTalkConfigMethodRouter             = CFSTR("Router");
+const CFStringRef kSCValNetAppleTalkConfigMethodSeedRouter         = CFSTR("SeedRouter");
+const CFStringRef kSCPropNetDNSDomainName                          = CFSTR("DomainName");
+const CFStringRef kSCPropNetDNSOptions                             = CFSTR("Options");
+const CFStringRef kSCPropNetDNSSearchDomains                       = CFSTR("SearchDomains");
+const CFStringRef kSCPropNetDNSSearchOrder                         = CFSTR("SearchOrder");
+const CFStringRef kSCPropNetDNSServerAddresses                     = CFSTR("ServerAddresses");
+const CFStringRef kSCPropNetDNSServerPort                          = CFSTR("ServerPort");
+const CFStringRef kSCPropNetDNSServerTimeout                       = CFSTR("ServerTimeout");
+const CFStringRef kSCPropNetDNSSortList                            = CFSTR("SortList");
+const CFStringRef kSCPropNetDNSSupplementalMatchDomains            = CFSTR("SupplementalMatchDomains");
+const CFStringRef kSCPropNetDNSSupplementalMatchOrders             = CFSTR("SupplementalMatchOrders");
+const CFStringRef kSCPropNetEthernetMediaSubType                   = CFSTR("MediaSubType");
+const CFStringRef kSCPropNetEthernetMediaOptions                   = CFSTR("MediaOptions");
+const CFStringRef kSCPropNetEthernetMTU                            = CFSTR("MTU");
+const CFStringRef kSCPropNetInterfaceDeviceName                    = CFSTR("DeviceName");
+const CFStringRef kSCPropNetInterfaceHardware                      = CFSTR("Hardware");
+const CFStringRef kSCPropNetInterfaceType                          = CFSTR("Type");
+const CFStringRef kSCPropNetInterfaceSubType                       = CFSTR("SubType");
+const CFStringRef kSCPropNetInterfaceSupportsModemOnHold           = CFSTR("SupportsModemOnHold");
+const CFStringRef kSCValNetInterfaceTypeEthernet                   = CFSTR("Ethernet");
+const CFStringRef kSCValNetInterfaceTypeFireWire                   = CFSTR("FireWire");
+const CFStringRef kSCValNetInterfaceTypePPP                        = CFSTR("PPP");
+const CFStringRef kSCValNetInterfaceType6to4                       = CFSTR("6to4");
+const CFStringRef kSCValNetInterfaceSubTypePPPoE                   = CFSTR("PPPoE");
+const CFStringRef kSCValNetInterfaceSubTypePPPSerial               = CFSTR("PPPSerial");
+const CFStringRef kSCValNetInterfaceSubTypePPTP                    = CFSTR("PPTP");
+const CFStringRef kSCValNetInterfaceSubTypeL2TP                    = CFSTR("L2TP");
+const CFStringRef kSCPropNetIPv4Addresses                          = CFSTR("Addresses");
+const CFStringRef kSCPropNetIPv4ConfigMethod                       = CFSTR("ConfigMethod");
+const CFStringRef kSCPropNetIPv4DHCPClientID                       = CFSTR("DHCPClientID");
+const CFStringRef kSCPropNetIPv4Router                             = CFSTR("Router");
+const CFStringRef kSCPropNetIPv4SubnetMasks                        = CFSTR("SubnetMasks");
+const CFStringRef kSCPropNetIPv4DestAddresses                      = CFSTR("DestAddresses");
+const CFStringRef kSCPropNetIPv4BroadcastAddresses                 = CFSTR("BroadcastAddresses");
+const CFStringRef kSCValNetIPv4ConfigMethodBOOTP                   = CFSTR("BOOTP");
+const CFStringRef kSCValNetIPv4ConfigMethodDHCP                    = CFSTR("DHCP");
+const CFStringRef kSCValNetIPv4ConfigMethodINFORM                  = CFSTR("INFORM");
+const CFStringRef kSCValNetIPv4ConfigMethodLinkLocal               = CFSTR("LinkLocal");
+const CFStringRef kSCValNetIPv4ConfigMethodManual                  = CFSTR("Manual");
+const CFStringRef kSCValNetIPv4ConfigMethodPPP                     = CFSTR("PPP");
+const CFStringRef kSCPropNetIPv6Addresses                          = CFSTR("Addresses");
+const CFStringRef kSCPropNetIPv6ConfigMethod                       = CFSTR("ConfigMethod");
+const CFStringRef kSCPropNetIPv6DestAddresses                      = CFSTR("DestAddresses");
+const CFStringRef kSCPropNetIPv6Flags                              = CFSTR("Flags");
+const CFStringRef kSCPropNetIPv6PrefixLength                       = CFSTR("PrefixLength");
+const CFStringRef kSCPropNetIPv6Router                             = CFSTR("Router");
+const CFStringRef kSCValNetIPv6ConfigMethodAutomatic               = CFSTR("Automatic");
+const CFStringRef kSCValNetIPv6ConfigMethodManual                  = CFSTR("Manual");
+const CFStringRef kSCValNetIPv6ConfigMethodRouterAdvertisement     = CFSTR("RouterAdvertisement");
+const CFStringRef kSCValNetIPv6ConfigMethod6to4                    = CFSTR("6to4");
+const CFStringRef kSCPropNet6to4Relay                              = CFSTR("Relay");
+const CFStringRef kSCPropNetLinkActive                             = CFSTR("Active");
+const CFStringRef kSCPropNetLinkDetaching                          = CFSTR("Detaching");
+const CFStringRef kSCPropNetModemConnectionScript                  = CFSTR("ConnectionScript");
+const CFStringRef kSCPropNetModemConnectSpeed                      = CFSTR("ConnectSpeed");
+const CFStringRef kSCPropNetModemDataCompression                   = CFSTR("DataCompression");
+const CFStringRef kSCPropNetModemDialMode                          = CFSTR("DialMode");
+const CFStringRef kSCPropNetModemErrorCorrection                   = CFSTR("ErrorCorrection");
+const CFStringRef kSCPropNetModemHoldCallWaitingAudibleAlert       = CFSTR("HoldCallWaitingAudibleAlert");
+const CFStringRef kSCPropNetModemHoldDisconnectOnAnswer            = CFSTR("HoldDisconnectOnAnswer");
+const CFStringRef kSCPropNetModemHoldEnabled                       = CFSTR("HoldEnabled");
+const CFStringRef kSCPropNetModemHoldReminder                      = CFSTR("HoldReminder");
+const CFStringRef kSCPropNetModemHoldReminderTime                  = CFSTR("HoldReminderTime");
+const CFStringRef kSCPropNetModemNote                              = CFSTR("Note");
+const CFStringRef kSCPropNetModemPulseDial                         = CFSTR("PulseDial");
+const CFStringRef kSCPropNetModemSpeaker                           = CFSTR("Speaker");
+const CFStringRef kSCPropNetModemSpeed                             = CFSTR("Speed");
+const CFStringRef kSCValNetModemDialModeIgnoreDialTone             = CFSTR("IgnoreDialTone");
+const CFStringRef kSCValNetModemDialModeManual                     = CFSTR("Manual");
+const CFStringRef kSCValNetModemDialModeWaitForDialTone            = CFSTR("WaitForDialTone");
+const CFStringRef kSCPropNetNetInfoBindingMethods                  = CFSTR("BindingMethods");
+const CFStringRef kSCPropNetNetInfoServerAddresses                 = CFSTR("ServerAddresses");
+const CFStringRef kSCPropNetNetInfoServerTags                      = CFSTR("ServerTags");
+const CFStringRef kSCPropNetNetInfoBroadcastServerTag              = CFSTR("BroadcastServerTag");
+const CFStringRef kSCValNetNetInfoBindingMethodsBroadcast          = CFSTR("Broadcast");
+const CFStringRef kSCValNetNetInfoBindingMethodsDHCP               = CFSTR("DHCP");
+const CFStringRef kSCValNetNetInfoBindingMethodsManual             = CFSTR("Manual");
+const CFStringRef kSCValNetNetInfoDefaultServerTag                 = CFSTR("network");
+const CFStringRef kSCPropNetPPPACSPEnabled                         = CFSTR("ACSPEnabled");
+const CFStringRef kSCPropNetPPPConnectTime                         = CFSTR("ConnectTime");
+const CFStringRef kSCPropNetPPPDeviceLastCause                     = CFSTR("DeviceLastCause");
+const CFStringRef kSCPropNetPPPDialOnDemand                        = CFSTR("DialOnDemand");
+const CFStringRef kSCPropNetPPPDisconnectOnFastUserSwitch          = CFSTR("DisconnectOnFastUserSwitch");
+const CFStringRef kSCPropNetPPPDisconnectOnIdle                    = CFSTR("DisconnectOnIdle");
+const CFStringRef kSCPropNetPPPDisconnectOnIdleTimer               = CFSTR("DisconnectOnIdleTimer");
+const CFStringRef kSCPropNetPPPDisconnectOnLogout                  = CFSTR("DisconnectOnLogout");
+const CFStringRef kSCPropNetPPPDisconnectOnSleep                   = CFSTR("DisconnectOnSleep");
+const CFStringRef kSCPropNetPPPDisconnectTime                      = CFSTR("DisconnectTime");
+const CFStringRef kSCPropNetPPPIdleReminderTimer                   = CFSTR("IdleReminderTimer");
+const CFStringRef kSCPropNetPPPIdleReminder                        = CFSTR("IdleReminder");
+const CFStringRef kSCPropNetPPPLastCause                           = CFSTR("LastCause");
+const CFStringRef kSCPropNetPPPLogfile                             = CFSTR("Logfile");
+const CFStringRef kSCPropNetPPPPlugins                             = CFSTR("Plugins");
+const CFStringRef kSCPropNetPPPRetryConnectTime                    = CFSTR("RetryConnectTime");
+const CFStringRef kSCPropNetPPPSessionTimer                        = CFSTR("SessionTimer");
+const CFStringRef kSCPropNetPPPStatus                              = CFSTR("Status");
+const CFStringRef kSCPropNetPPPUseSessionTimer                     = CFSTR("UseSessionTimer");
+const CFStringRef kSCPropNetPPPVerboseLogging                      = CFSTR("VerboseLogging");
+const CFStringRef kSCPropNetPPPAuthEAPPlugins                      = CFSTR("AuthEAPPlugins");
+const CFStringRef kSCPropNetPPPAuthName                            = CFSTR("AuthName");
+const CFStringRef kSCPropNetPPPAuthPassword                        = CFSTR("AuthPassword");
+const CFStringRef kSCPropNetPPPAuthPasswordEncryption              = CFSTR("AuthPasswordEncryption");
+const CFStringRef kSCPropNetPPPAuthPrompt                          = CFSTR("AuthPrompt");
+const CFStringRef kSCPropNetPPPAuthProtocol                        = CFSTR("AuthProtocol");
+const CFStringRef kSCValNetPPPAuthPasswordEncryptionKeychain       = CFSTR("Keychain");
+const CFStringRef kSCValNetPPPAuthPromptBefore                     = CFSTR("Before");
+const CFStringRef kSCValNetPPPAuthPromptAfter                      = CFSTR("After");
+const CFStringRef kSCValNetPPPAuthProtocolCHAP                     = CFSTR("CHAP");
+const CFStringRef kSCValNetPPPAuthProtocolEAP                      = CFSTR("EAP");
+const CFStringRef kSCValNetPPPAuthProtocolMSCHAP1                  = CFSTR("MSCHAP1");
+const CFStringRef kSCValNetPPPAuthProtocolMSCHAP2                  = CFSTR("MSCHAP2");
+const CFStringRef kSCValNetPPPAuthProtocolPAP                      = CFSTR("PAP");
+const CFStringRef kSCPropNetPPPCommAlternateRemoteAddress          = CFSTR("CommAlternateRemoteAddress");
+const CFStringRef kSCPropNetPPPCommConnectDelay                    = CFSTR("CommConnectDelay");
+const CFStringRef kSCPropNetPPPCommDisplayTerminalWindow           = CFSTR("CommDisplayTerminalWindow");
+const CFStringRef kSCPropNetPPPCommRedialCount                     = CFSTR("CommRedialCount");
+const CFStringRef kSCPropNetPPPCommRedialEnabled                   = CFSTR("CommRedialEnabled");
+const CFStringRef kSCPropNetPPPCommRedialInterval                  = CFSTR("CommRedialInterval");
+const CFStringRef kSCPropNetPPPCommRemoteAddress                   = CFSTR("CommRemoteAddress");
+const CFStringRef kSCPropNetPPPCommTerminalScript                  = CFSTR("CommTerminalScript");
+const CFStringRef kSCPropNetPPPCommUseTerminalScript               = CFSTR("CommUseTerminalScript");
+const CFStringRef kSCPropNetPPPCCPEnabled                          = CFSTR("CCPEnabled");
+const CFStringRef kSCPropNetPPPCCPMPPE40Enabled                    = CFSTR("CCPMPPE40Enabled");
+const CFStringRef kSCPropNetPPPCCPMPPE128Enabled                   = CFSTR("CCPMPPE128Enabled");
+const CFStringRef kSCPropNetPPPIPCPCompressionVJ                   = CFSTR("IPCPCompressionVJ");
+const CFStringRef kSCPropNetPPPIPCPUsePeerDNS                      = CFSTR("IPCPUsePeerDNS");
+const CFStringRef kSCPropNetPPPLCPEchoEnabled                      = CFSTR("LCPEchoEnabled");
+const CFStringRef kSCPropNetPPPLCPEchoFailure                      = CFSTR("LCPEchoFailure");
+const CFStringRef kSCPropNetPPPLCPEchoInterval                     = CFSTR("LCPEchoInterval");
+const CFStringRef kSCPropNetPPPLCPCompressionACField               = CFSTR("LCPCompressionACField");
+const CFStringRef kSCPropNetPPPLCPCompressionPField                = CFSTR("LCPCompressionPField");
+const CFStringRef kSCPropNetPPPLCPMRU                              = CFSTR("LCPMRU");
+const CFStringRef kSCPropNetPPPLCPMTU                              = CFSTR("LCPMTU");
+const CFStringRef kSCPropNetPPPLCPReceiveACCM                      = CFSTR("LCPReceiveACCM");
+const CFStringRef kSCPropNetPPPLCPTransmitACCM                     = CFSTR("LCPTransmitACCM");
+const CFStringRef kSCPropNetL2TPIPSecSharedSecret                  = CFSTR("IPSecSharedSecret");
+const CFStringRef kSCPropNetL2TPIPSecSharedSecretEncryption        = CFSTR("IPSecSharedSecretEncryption");
+const CFStringRef kSCPropNetL2TPTransport                          = CFSTR("Transport");
+const CFStringRef kSCValNetL2TPIPSecSharedSecretEncryptionKeychain = CFSTR("Keychain");
+const CFStringRef kSCValNetL2TPTransportIP                         = CFSTR("IP");
+const CFStringRef kSCValNetL2TPTransportIPSec                      = CFSTR("IPSec");
+const CFStringRef kSCPropNetProxiesExceptionsList                  = CFSTR("ExceptionsList");
+const CFStringRef kSCPropNetProxiesExcludeSimpleHostnames          = CFSTR("ExcludeSimpleHostnames");
+const CFStringRef kSCPropNetProxiesFTPEnable                       = CFSTR("FTPEnable");
+const CFStringRef kSCPropNetProxiesFTPPassive                      = CFSTR("FTPPassive");
+const CFStringRef kSCPropNetProxiesFTPPort                         = CFSTR("FTPPort");
+const CFStringRef kSCPropNetProxiesFTPProxy                        = CFSTR("FTPProxy");
+const CFStringRef kSCPropNetProxiesGopherEnable                    = CFSTR("GopherEnable");
+const CFStringRef kSCPropNetProxiesGopherPort                      = CFSTR("GopherPort");
+const CFStringRef kSCPropNetProxiesGopherProxy                     = CFSTR("GopherProxy");
+const CFStringRef kSCPropNetProxiesHTTPEnable                      = CFSTR("HTTPEnable");
+const CFStringRef kSCPropNetProxiesHTTPPort                        = CFSTR("HTTPPort");
+const CFStringRef kSCPropNetProxiesHTTPProxy                       = CFSTR("HTTPProxy");
+const CFStringRef kSCPropNetProxiesHTTPSEnable                     = CFSTR("HTTPSEnable");
+const CFStringRef kSCPropNetProxiesHTTPSPort                       = CFSTR("HTTPSPort");
+const CFStringRef kSCPropNetProxiesHTTPSProxy                      = CFSTR("HTTPSProxy");
+const CFStringRef kSCPropNetProxiesRTSPEnable                      = CFSTR("RTSPEnable");
+const CFStringRef kSCPropNetProxiesRTSPPort                        = CFSTR("RTSPPort");
+const CFStringRef kSCPropNetProxiesRTSPProxy                       = CFSTR("RTSPProxy");
+const CFStringRef kSCPropNetProxiesSOCKSEnable                     = CFSTR("SOCKSEnable");
+const CFStringRef kSCPropNetProxiesSOCKSPort                       = CFSTR("SOCKSPort");
+const CFStringRef kSCPropNetProxiesSOCKSProxy                      = CFSTR("SOCKSProxy");
+const CFStringRef kSCPropNetProxiesProxyAutoConfigEnable           = CFSTR("ProxyAutoConfigEnable");
+const CFStringRef kSCPropNetProxiesProxyAutoConfigURLString        = CFSTR("ProxyAutoConfigURLString");
+const CFStringRef kSCPropNetProxiesProxyAutoDiscoveryEnable        = CFSTR("ProxyAutoDiscoveryEnable");
+const CFStringRef kSCEntUsersConsoleUser                           = CFSTR("ConsoleUser");
+const CFStringRef kSCPropSystemComputerName                        = CFSTR("ComputerName");
+const CFStringRef kSCPropSystemComputerNameEncoding                = CFSTR("ComputerNameEncoding");
+const CFStringRef kSCDynamicStoreDomainFile                        = CFSTR("File:");
+const CFStringRef kSCDynamicStoreDomainPlugin                      = CFSTR("Plugin:");
+const CFStringRef kSCDynamicStoreDomainSetup                       = CFSTR("Setup:");
+const CFStringRef kSCDynamicStoreDomainState                       = CFSTR("State:");
+const CFStringRef kSCDynamicStoreDomainPrefs                       = CFSTR("Prefs:");
+const CFStringRef kSCDynamicStorePropSetupCurrentSet               = CFSTR("CurrentSet");
+const CFStringRef kSCDynamicStorePropSetupLastUpdated              = CFSTR("LastUpdated");
+const CFStringRef kSCDynamicStorePropNetInterfaces                 = CFSTR("Interfaces");
+const CFStringRef kSCDynamicStorePropNetPrimaryInterface           = CFSTR("PrimaryInterface");
+const CFStringRef kSCDynamicStorePropNetPrimaryService             = CFSTR("PrimaryService");
+const CFStringRef kSCDynamicStorePropNetServiceIDs                 = CFSTR("ServiceIDs");
+const CFStringRef kSCPropUsersConsoleUserName                      = CFSTR("Name");
+const CFStringRef kSCPropUsersConsoleUserUID                       = CFSTR("UID");
+const CFStringRef kSCPropUsersConsoleUserGID                       = CFSTR("GID");
diff --git a/SystemConfiguration.fproj/SCSchemaDefinitions.h b/SystemConfiguration.fproj/SCSchemaDefinitions.h
new file mode 100644 (file)
index 0000000..d29c11d
--- /dev/null
@@ -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 <SystemConfiguration/SystemConfiguration.h>
+ */
+
+/*
+ * Note: For CFM applications using these schema keys you may want to
+ *       consider the following :
+ *
+ *       #define SC_SCHEMA_KV(k,v,t)   lookup_SC_key( CFSTR( #k ) )
+ *       #define SC_SCHEMA_DECLARATION(k,q)
+ *       #include <SystemConfiguration/SystemConfiguration.h>
+ *
+ *       CFStringRef lookup_SC_key(CFStringRef key)
+ *       {
+ *         // this function should [dynamically, on-demand] load the
+ *         // SystemConfiguration.framework, look up the provided key,
+ *         // and return the associated value.
+ *       }
+ */
+
+/*
+ * Note: Earlier versions of this header file defined a "SCSTR" macro
+ *       which helped to facilitate Obj-C development. Use of this macro
+ *       has been deprecated (in Mac OS X 10.4) in favor of the newer
+ *       "SC_SCHEMA_KV" and "SC_SCHEMA_DECLARATION" macros
+ */
+
+
+#ifndef _SCSCHEMADEFINITIONS_H
+#define _SCSCHEMADEFINITIONS_H
+
+/* -------------------- Macro declarations -------------------- */
+
+#include <AvailabilityMacros.h>
+
+/*
+ * let's "do the right thing" for those wishing to build for
+ * Mac OS X 10.1 and 10.2
+ */
+#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED
+  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED
+    #ifndef SCSTR
+      #include <CoreFoundation/CFString.h>
+      #define SCSTR(s) CFSTR(s)
+    #endif
+    #ifndef SC_SCHEMA_KV
+      #define SC_SCHEMA_KV(k,v,t)      SCSTR( v )
+    #endif
+    #ifndef SC_SCHEMA_DECLARATION
+      #define SC_SCHEMA_DECLARATION(k,q)
+    #endif
+  #endif
+#endif
+
+/*
+ * Define a schema key/value/type tuple
+ */
+#ifndef SC_SCHEMA_KV
+  #define SC_SCHEMA_KV(k,v,t)  k
+#endif
+
+/*
+ * Provide an "extern" for the key/value
+ */
+#ifndef SC_SCHEMA_DECLARATION
+  #ifndef SCSTR
+    #include <CoreFoundation/CFString.h>
+    #define SC_SCHEMA_DECLARATION(k,q) extern const CFStringRef k q
+  #else
+    #import <Foundation/NSString.h>
+    #define SC_SCHEMA_DECLARATION(k,q) extern NSString * k q
+  #endif
+#endif
+#if MAC_OS_X_VERSION_10_4 >= MAC_OS_X_VERSION_MIN_REQUIRED
+  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED
+    #ifndef SCSTR
+      #include <CoreFoundation/CFString.h>
+      #define SCSTR(s) CFSTR(s)
+    #endif
+  #endif
+#endif
+
+
+/* -------------------- HeaderDoc comments -------------------- */
+
+
+#if    0
+/*!
+ *     @header SCSchemaDefinitions
+ */
+
+/*!
+  @const kSCResvLink
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCResvLink;
+
+/*!
+  @const kSCResvInactive
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCResvInactive;
+
+/*!
+  @const kSCPropInterfaceName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropInterfaceName;
+
+/*!
+  @const kSCPropMACAddress
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropMACAddress;
+
+/*!
+  @const kSCPropUserDefinedName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropUserDefinedName;
+
+/*!
+  @const kSCPropVersion
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropVersion;
+
+/*!
+  @group Preference Keys
+ */
+
+/*!
+  @const kSCPrefCurrentSet
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefCurrentSet;
+
+/*!
+  @const kSCPrefNetworkServices
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefNetworkServices;
+
+/*!
+  @const kSCPrefSets
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefSets;
+
+/*!
+  @const kSCPrefSystem
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPrefSystem;
+
+/*!
+  @group Component Keys
+ */
+
+/*!
+  @const kSCCompNetwork
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompNetwork;
+
+/*!
+  @const kSCCompService
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompService;
+
+/*!
+  @const kSCCompGlobal
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompGlobal;
+
+/*!
+  @const kSCCompHostNames
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCCompHostNames;
+
+/*!
+  @const kSCCompInterface
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompInterface;
+
+/*!
+  @const kSCCompSystem
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompSystem;
+
+/*!
+  @const kSCCompUsers
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompUsers;
+
+/*!
+  @const kSCCompAnyRegex
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCCompAnyRegex;
+
+/*!
+  @group Network Entity Keys
+ */
+
+/*!
+  @const kSCEntNetAirPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetAirPort;
+
+/*!
+  @const kSCEntNetAppleTalk
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetAppleTalk;
+
+/*!
+  @const kSCEntNetDHCP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetDHCP;
+
+/*!
+  @const kSCEntNetDNS
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetDNS;
+
+/*!
+  @const kSCEntNetEthernet
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetEthernet;
+
+/*!
+  @const kSCEntNetFireWire
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetFireWire;
+
+/*!
+  @const kSCEntNetInterface
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetInterface;
+
+/*!
+  @const kSCEntNetIPv4
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetIPv4;
+
+/*!
+  @const kSCEntNetIPv6
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetIPv6;
+
+/*!
+  @const kSCEntNetL2TP
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetL2TP;
+
+/*!
+  @const kSCEntNetLink
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetLink;
+
+/*!
+  @const kSCEntNetModem
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetModem;
+
+/*!
+  @const kSCEntNetNetInfo
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetNetInfo;
+
+/*!
+  @const kSCEntNetPPP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetPPP;
+
+/*!
+  @const kSCEntNetPPPoE
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetPPPoE;
+
+/*!
+  @const kSCEntNetPPPSerial
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetPPPSerial;
+
+/*!
+  @const kSCEntNetPPTP
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNetPPTP;
+
+/*!
+  @const kSCEntNetProxies
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntNetProxies;
+
+/*!
+  @const kSCEntNet6to4
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCEntNet6to4;
+
+/*!
+  @group kSCCompNetwork Properties
+ */
+
+/*!
+  @const kSCPropNetOverridePrimary
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetOverridePrimary;
+
+/*!
+  @const kSCPropNetServiceOrder
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetServiceOrder;
+
+/*!
+  @const kSCPropNetPPPOverridePrimary
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPOverridePrimary;
+
+/*!
+  @group kSCCompNetworkInterface Properties
+ */
+
+/*!
+  @const kSCPropNetInterfaces
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetInterfaces;
+
+/*!
+  @group kSCCompNetworkHostNames Properties
+ */
+
+/*!
+  @const kSCPropNetLocalHostName
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetLocalHostName;
+
+/*!
+  @group kSCEntNetAirPort (Hardware) Entity Keys
+ */
+
+/*!
+  @const kSCPropNetAirPortAllowNetCreation
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAirPortAllowNetCreation;
+
+/*!
+  @const kSCPropNetAirPortAuthPassword
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortAuthPassword;
+
+/*!
+  @const kSCPropNetAirPortAuthPasswordEncryption
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortAuthPasswordEncryption;
+
+/*!
+  @const kSCPropNetAirPortJoinMode
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAirPortJoinMode;
+
+/*!
+  @const kSCPropNetAirPortPowerEnabled
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortPowerEnabled;
+
+/*!
+  @const kSCPropNetAirPortPreferredNetwork
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAirPortPreferredNetwork;
+
+/*!
+  @const kSCPropNetAirPortSavePasswords
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAirPortSavePasswords;
+
+/*!
+  @const kSCValNetAirPortJoinModeAutomatic
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModeAutomatic;
+
+/*!
+  @const kSCValNetAirPortJoinModePreferred
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModePreferred;
+
+/*!
+  @const kSCValNetAirPortJoinModeRecent
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModeRecent;
+
+/*!
+  @const kSCValNetAirPortJoinModeStrongest
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetAirPortJoinModeStrongest;
+
+/*!
+  @const kSCValNetAirPortAuthPasswordEncryptionKeychain
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetAirPortAuthPasswordEncryptionKeychain;
+
+/*!
+  @group kSCEntNetAppleTalk Entity Keys
+ */
+
+/*!
+  @const kSCPropNetAppleTalkComputerName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkComputerName;
+
+/*!
+  @const kSCPropNetAppleTalkComputerNameEncoding
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkComputerNameEncoding;
+
+/*!
+  @const kSCPropNetAppleTalkConfigMethod
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkConfigMethod;
+
+/*!
+  @const kSCPropNetAppleTalkDefaultZone
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkDefaultZone;
+
+/*!
+  @const kSCPropNetAppleTalkNetworkID
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkNetworkID;
+
+/*!
+  @const kSCPropNetAppleTalkNetworkRange
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetAppleTalkNetworkRange;
+
+/*!
+  @const kSCPropNetAppleTalkNodeID
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkNodeID;
+
+/*!
+  @const kSCPropNetAppleTalkSeedNetworkRange
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkSeedNetworkRange;
+
+/*!
+  @const kSCPropNetAppleTalkSeedZones
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetAppleTalkSeedZones;
+
+/*!
+  @const kSCValNetAppleTalkConfigMethodNode
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetAppleTalkConfigMethodNode;
+
+/*!
+  @const kSCValNetAppleTalkConfigMethodRouter
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetAppleTalkConfigMethodRouter;
+
+/*!
+  @const kSCValNetAppleTalkConfigMethodSeedRouter
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetAppleTalkConfigMethodSeedRouter;
+
+/*!
+  @group kSCEntNetDNS Entity Keys
+ */
+
+/*!
+  @const kSCPropNetDNSDomainName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSDomainName;
+
+/*!
+  @const kSCPropNetDNSOptions
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSOptions;
+
+/*!
+  @const kSCPropNetDNSSearchDomains
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSSearchDomains;
+
+/*!
+  @const kSCPropNetDNSSearchOrder
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSSearchOrder;
+
+/*!
+  @const kSCPropNetDNSServerAddresses
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSServerAddresses;
+
+/*!
+  @const kSCPropNetDNSServerPort
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSServerPort;
+
+/*!
+  @const kSCPropNetDNSServerTimeout
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSServerTimeout;
+
+/*!
+  @const kSCPropNetDNSSortList
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetDNSSortList;
+
+/*!
+  @const kSCPropNetDNSSupplementalMatchDomains
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSSupplementalMatchDomains;
+
+/*!
+  @const kSCPropNetDNSSupplementalMatchOrders
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetDNSSupplementalMatchOrders;
+
+/*!
+  @group kSCEntNetEthernet (Hardware) Entity Keys
+ */
+
+/*!
+  @const kSCPropNetEthernetMediaSubType
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetEthernetMediaSubType;
+
+/*!
+  @const kSCPropNetEthernetMediaOptions
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetEthernetMediaOptions;
+
+/*!
+  @const kSCPropNetEthernetMTU
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetEthernetMTU;
+
+/*!
+  @group kSCEntNetFireWire (Hardware) Entity Keys
+ */
+
+/*!
+  @group kSCEntNetInterface Entity Keys
+ */
+
+/*!
+  @const kSCPropNetInterfaceDeviceName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceDeviceName;
+
+/*!
+  @const kSCPropNetInterfaceHardware
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceHardware;
+
+/*!
+  @const kSCPropNetInterfaceType
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceType;
+
+/*!
+  @const kSCPropNetInterfaceSubType
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetInterfaceSubType;
+
+/*!
+  @const kSCPropNetInterfaceSupportsModemOnHold
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetInterfaceSupportsModemOnHold;
+
+/*!
+  @const kSCValNetInterfaceTypeEthernet
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceTypeEthernet;
+
+/*!
+  @const kSCValNetInterfaceTypeFireWire
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetInterfaceTypeFireWire;
+
+/*!
+  @const kSCValNetInterfaceTypePPP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceTypePPP;
+
+/*!
+  @const kSCValNetInterfaceType6to4
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetInterfaceType6to4;
+
+/*!
+  @const kSCValNetInterfaceSubTypePPPoE
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypePPPoE;
+
+/*!
+  @const kSCValNetInterfaceSubTypePPPSerial
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypePPPSerial;
+
+/*!
+  @const kSCValNetInterfaceSubTypePPTP
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypePPTP;
+
+/*!
+  @const kSCValNetInterfaceSubTypeL2TP
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetInterfaceSubTypeL2TP;
+
+/*!
+  @group kSCEntNetIPv4 Entity Keys
+ */
+
+/*!
+  @const kSCPropNetIPv4Addresses
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4Addresses;
+
+/*!
+  @const kSCPropNetIPv4ConfigMethod
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4ConfigMethod;
+
+/*!
+  @const kSCPropNetIPv4DHCPClientID
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4DHCPClientID;
+
+/*!
+  @const kSCPropNetIPv4Router
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4Router;
+
+/*!
+  @const kSCPropNetIPv4SubnetMasks
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4SubnetMasks;
+
+/*!
+  @const kSCPropNetIPv4DestAddresses
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4DestAddresses;
+
+/*!
+  @const kSCPropNetIPv4BroadcastAddresses
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv4BroadcastAddresses;
+
+/*!
+  @const kSCValNetIPv4ConfigMethodBOOTP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodBOOTP;
+
+/*!
+  @const kSCValNetIPv4ConfigMethodDHCP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodDHCP;
+
+/*!
+  @const kSCValNetIPv4ConfigMethodINFORM
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodINFORM;
+
+/*!
+  @const kSCValNetIPv4ConfigMethodLinkLocal
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodLinkLocal;
+
+/*!
+  @const kSCValNetIPv4ConfigMethodManual
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodManual;
+
+/*!
+  @const kSCValNetIPv4ConfigMethodPPP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetIPv4ConfigMethodPPP;
+
+/*!
+  @group kSCEntNetIPv6 Entity Keys
+ */
+
+/*!
+  @const kSCPropNetIPv6Addresses
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv6Addresses;
+
+/*!
+  @const kSCPropNetIPv6ConfigMethod
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetIPv6ConfigMethod;
+
+/*!
+  @const kSCPropNetIPv6DestAddresses
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6DestAddresses;
+
+/*!
+  @const kSCPropNetIPv6Flags
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6Flags;
+
+/*!
+  @const kSCPropNetIPv6PrefixLength
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6PrefixLength;
+
+/*!
+  @const kSCPropNetIPv6Router
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetIPv6Router;
+
+/*!
+  @const kSCValNetIPv6ConfigMethodAutomatic
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethodAutomatic;
+
+/*!
+  @const kSCValNetIPv6ConfigMethodManual
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethodManual;
+
+/*!
+  @const kSCValNetIPv6ConfigMethodRouterAdvertisement
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethodRouterAdvertisement;
+
+/*!
+  @const kSCValNetIPv6ConfigMethod6to4
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetIPv6ConfigMethod6to4;
+
+/*!
+  @group kSCEntNet6to4 Entity Keys
+ */
+
+/*!
+  @const kSCPropNet6to4Relay
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNet6to4Relay;
+
+/*!
+  @group kSCEntNetLink Entity Keys
+ */
+
+/*!
+  @const kSCPropNetLinkActive
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetLinkActive;
+
+/*!
+  @const kSCPropNetLinkDetaching
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetLinkDetaching;
+
+/*!
+  @group kSCEntNetModem (Hardware) Entity Keys
+ */
+
+/*!
+  @const kSCPropNetModemConnectionScript
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemConnectionScript;
+
+/*!
+  @const kSCPropNetModemConnectSpeed
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemConnectSpeed;
+
+/*!
+  @const kSCPropNetModemDataCompression
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemDataCompression;
+
+/*!
+  @const kSCPropNetModemDialMode
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemDialMode;
+
+/*!
+  @const kSCPropNetModemErrorCorrection
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemErrorCorrection;
+
+/*!
+  @const kSCPropNetModemHoldCallWaitingAudibleAlert
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldCallWaitingAudibleAlert;
+
+/*!
+  @const kSCPropNetModemHoldDisconnectOnAnswer
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldDisconnectOnAnswer;
+
+/*!
+  @const kSCPropNetModemHoldEnabled
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldEnabled;
+
+/*!
+  @const kSCPropNetModemHoldReminder
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldReminder;
+
+/*!
+  @const kSCPropNetModemHoldReminderTime
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemHoldReminderTime;
+
+/*!
+  @const kSCPropNetModemNote
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetModemNote;
+
+/*!
+  @const kSCPropNetModemPulseDial
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemPulseDial;
+
+/*!
+  @const kSCPropNetModemSpeaker
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemSpeaker;
+
+/*!
+  @const kSCPropNetModemSpeed
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetModemSpeed;
+
+/*!
+  @const kSCValNetModemDialModeIgnoreDialTone
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetModemDialModeIgnoreDialTone;
+
+/*!
+  @const kSCValNetModemDialModeManual
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetModemDialModeManual;
+
+/*!
+  @const kSCValNetModemDialModeWaitForDialTone
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetModemDialModeWaitForDialTone;
+
+/*!
+  @group kSCEntNetNetInfo Entity Keys
+ */
+
+/*!
+  @const kSCPropNetNetInfoBindingMethods
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoBindingMethods;
+
+/*!
+  @const kSCPropNetNetInfoServerAddresses
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoServerAddresses;
+
+/*!
+  @const kSCPropNetNetInfoServerTags
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoServerTags;
+
+/*!
+  @const kSCPropNetNetInfoBroadcastServerTag
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetNetInfoBroadcastServerTag;
+
+/*!
+  @const kSCValNetNetInfoBindingMethodsBroadcast
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoBindingMethodsBroadcast;
+
+/*!
+  @const kSCValNetNetInfoBindingMethodsDHCP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoBindingMethodsDHCP;
+
+/*!
+  @const kSCValNetNetInfoBindingMethodsManual
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoBindingMethodsManual;
+
+/*!
+  @const kSCValNetNetInfoDefaultServerTag
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetNetInfoDefaultServerTag;
+
+/*!
+  @group kSCEntNetPPP Entity Keys
+ */
+
+/*!
+  @const kSCPropNetPPPACSPEnabled
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPACSPEnabled;
+
+/*!
+  @const kSCPropNetPPPConnectTime
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPConnectTime;
+
+/*!
+  @const kSCPropNetPPPDeviceLastCause
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPDeviceLastCause;
+
+/*!
+  @const kSCPropNetPPPDialOnDemand
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDialOnDemand;
+
+/*!
+  @const kSCPropNetPPPDisconnectOnFastUserSwitch
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnFastUserSwitch;
+
+/*!
+  @const kSCPropNetPPPDisconnectOnIdle
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnIdle;
+
+/*!
+  @const kSCPropNetPPPDisconnectOnIdleTimer
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnIdleTimer;
+
+/*!
+  @const kSCPropNetPPPDisconnectOnLogout
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnLogout;
+
+/*!
+  @const kSCPropNetPPPDisconnectOnSleep
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectOnSleep;
+
+/*!
+  @const kSCPropNetPPPDisconnectTime
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPDisconnectTime;
+
+/*!
+  @const kSCPropNetPPPIdleReminderTimer
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPIdleReminderTimer;
+
+/*!
+  @const kSCPropNetPPPIdleReminder
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPIdleReminder;
+
+/*!
+  @const kSCPropNetPPPLastCause
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPLastCause;
+
+/*!
+  @const kSCPropNetPPPLogfile
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLogfile;
+
+/*!
+  @const kSCPropNetPPPPlugins
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPPlugins;
+
+/*!
+  @const kSCPropNetPPPRetryConnectTime
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPRetryConnectTime;
+
+/*!
+  @const kSCPropNetPPPSessionTimer
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPSessionTimer;
+
+/*!
+  @const kSCPropNetPPPStatus
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPStatus;
+
+/*!
+  @const kSCPropNetPPPUseSessionTimer
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPUseSessionTimer;
+
+/*!
+  @const kSCPropNetPPPVerboseLogging
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPVerboseLogging;
+
+/*!
+  @const kSCPropNetPPPAuthEAPPlugins
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPAuthEAPPlugins;
+
+/*!
+  @const kSCPropNetPPPAuthName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthName;
+
+/*!
+  @const kSCPropNetPPPAuthPassword
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthPassword;
+
+/*!
+  @const kSCPropNetPPPAuthPasswordEncryption
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthPasswordEncryption;
+
+/*!
+  @const kSCPropNetPPPAuthPrompt
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetPPPAuthPrompt;
+
+/*!
+  @const kSCPropNetPPPAuthProtocol
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPAuthProtocol;
+
+/*!
+  @const kSCValNetPPPAuthPasswordEncryptionKeychain
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthPasswordEncryptionKeychain;
+
+/*!
+  @const kSCValNetPPPAuthPromptBefore
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthPromptBefore;
+
+/*!
+  @const kSCValNetPPPAuthPromptAfter
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthPromptAfter;
+
+/*!
+  @const kSCValNetPPPAuthProtocolCHAP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolCHAP;
+
+/*!
+  @const kSCValNetPPPAuthProtocolEAP
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolEAP;
+
+/*!
+  @const kSCValNetPPPAuthProtocolMSCHAP1
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolMSCHAP1;
+
+/*!
+  @const kSCValNetPPPAuthProtocolMSCHAP2
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolMSCHAP2;
+
+/*!
+  @const kSCValNetPPPAuthProtocolPAP
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCValNetPPPAuthProtocolPAP;
+
+/*!
+  @const kSCPropNetPPPCommAlternateRemoteAddress
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommAlternateRemoteAddress;
+
+/*!
+  @const kSCPropNetPPPCommConnectDelay
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommConnectDelay;
+
+/*!
+  @const kSCPropNetPPPCommDisplayTerminalWindow
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommDisplayTerminalWindow;
+
+/*!
+  @const kSCPropNetPPPCommRedialCount
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRedialCount;
+
+/*!
+  @const kSCPropNetPPPCommRedialEnabled
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRedialEnabled;
+
+/*!
+  @const kSCPropNetPPPCommRedialInterval
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRedialInterval;
+
+/*!
+  @const kSCPropNetPPPCommRemoteAddress
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommRemoteAddress;
+
+/*!
+  @const kSCPropNetPPPCommTerminalScript
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPCommTerminalScript;
+
+/*!
+  @const kSCPropNetPPPCommUseTerminalScript
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPCommUseTerminalScript;
+
+/*!
+  @const kSCPropNetPPPCCPEnabled
+  @availability Introduced in Mac OS X 10.2.
+ */
+extern const CFStringRef kSCPropNetPPPCCPEnabled;
+
+/*!
+  @const kSCPropNetPPPCCPMPPE40Enabled
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPCCPMPPE40Enabled;
+
+/*!
+  @const kSCPropNetPPPCCPMPPE128Enabled
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPCCPMPPE128Enabled;
+
+/*!
+  @const kSCPropNetPPPIPCPCompressionVJ
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPIPCPCompressionVJ;
+
+/*!
+  @const kSCPropNetPPPIPCPUsePeerDNS
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetPPPIPCPUsePeerDNS;
+
+/*!
+  @const kSCPropNetPPPLCPEchoEnabled
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPEchoEnabled;
+
+/*!
+  @const kSCPropNetPPPLCPEchoFailure
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPEchoFailure;
+
+/*!
+  @const kSCPropNetPPPLCPEchoInterval
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPEchoInterval;
+
+/*!
+  @const kSCPropNetPPPLCPCompressionACField
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPCompressionACField;
+
+/*!
+  @const kSCPropNetPPPLCPCompressionPField
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPCompressionPField;
+
+/*!
+  @const kSCPropNetPPPLCPMRU
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPMRU;
+
+/*!
+  @const kSCPropNetPPPLCPMTU
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPMTU;
+
+/*!
+  @const kSCPropNetPPPLCPReceiveACCM
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPReceiveACCM;
+
+/*!
+  @const kSCPropNetPPPLCPTransmitACCM
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetPPPLCPTransmitACCM;
+
+/*!
+  @group kSCEntNetPPPoE Entity Keys
+ */
+
+/*!
+  @group kSCEntNetPPPSerial Entity Keys
+ */
+
+/*!
+  @group kSCEntNetPPTP Entity Keys
+ */
+
+/*!
+  @group kSCEntNetL2TP Entity Keys
+ */
+
+/*!
+  @const kSCPropNetL2TPIPSecSharedSecret
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetL2TPIPSecSharedSecret;
+
+/*!
+  @const kSCPropNetL2TPIPSecSharedSecretEncryption
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetL2TPIPSecSharedSecretEncryption;
+
+/*!
+  @const kSCPropNetL2TPTransport
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCPropNetL2TPTransport;
+
+/*!
+  @const kSCValNetL2TPIPSecSharedSecretEncryptionKeychain
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetL2TPIPSecSharedSecretEncryptionKeychain;
+
+/*!
+  @const kSCValNetL2TPTransportIP
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetL2TPTransportIP;
+
+/*!
+  @const kSCValNetL2TPTransportIPSec
+  @availability Introduced in Mac OS X 10.3.
+ */
+extern const CFStringRef kSCValNetL2TPTransportIPSec;
+
+/*!
+  @group kSCEntNetProxies Entity Keys
+ */
+
+/*!
+  @const kSCPropNetProxiesExceptionsList
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesExceptionsList;
+
+/*!
+  @const kSCPropNetProxiesExcludeSimpleHostnames
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesExcludeSimpleHostnames;
+
+/*!
+  @const kSCPropNetProxiesFTPEnable
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPEnable;
+
+/*!
+  @const kSCPropNetProxiesFTPPassive
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPPassive;
+
+/*!
+  @const kSCPropNetProxiesFTPPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPPort;
+
+/*!
+  @const kSCPropNetProxiesFTPProxy
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesFTPProxy;
+
+/*!
+  @const kSCPropNetProxiesGopherEnable
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesGopherEnable;
+
+/*!
+  @const kSCPropNetProxiesGopherPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesGopherPort;
+
+/*!
+  @const kSCPropNetProxiesGopherProxy
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesGopherProxy;
+
+/*!
+  @const kSCPropNetProxiesHTTPEnable
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPEnable;
+
+/*!
+  @const kSCPropNetProxiesHTTPPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPPort;
+
+/*!
+  @const kSCPropNetProxiesHTTPProxy
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPProxy;
+
+/*!
+  @const kSCPropNetProxiesHTTPSEnable
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPSEnable;
+
+/*!
+  @const kSCPropNetProxiesHTTPSPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPSPort;
+
+/*!
+  @const kSCPropNetProxiesHTTPSProxy
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesHTTPSProxy;
+
+/*!
+  @const kSCPropNetProxiesRTSPEnable
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesRTSPEnable;
+
+/*!
+  @const kSCPropNetProxiesRTSPPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesRTSPPort;
+
+/*!
+  @const kSCPropNetProxiesRTSPProxy
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesRTSPProxy;
+
+/*!
+  @const kSCPropNetProxiesSOCKSEnable
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesSOCKSEnable;
+
+/*!
+  @const kSCPropNetProxiesSOCKSPort
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesSOCKSPort;
+
+/*!
+  @const kSCPropNetProxiesSOCKSProxy
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropNetProxiesSOCKSProxy;
+
+/*!
+  @const kSCPropNetProxiesProxyAutoConfigEnable
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesProxyAutoConfigEnable;
+
+/*!
+  @const kSCPropNetProxiesProxyAutoConfigURLString
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesProxyAutoConfigURLString;
+
+/*!
+  @const kSCPropNetProxiesProxyAutoDiscoveryEnable
+  @availability Introduced in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropNetProxiesProxyAutoDiscoveryEnable;
+
+/*!
+  @group kSCCompUsers Entity Keys
+ */
+
+/*!
+  @const kSCEntUsersConsoleUser
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCEntUsersConsoleUser;
+
+/*!
+  @group kSCCompSystem Properties
+ */
+
+/*!
+  @const kSCPropSystemComputerName
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropSystemComputerName;
+
+/*!
+  @const kSCPropSystemComputerNameEncoding
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCPropSystemComputerNameEncoding;
+
+/*!
+  @group SCDynamicStore "domain" prefixes
+ */
+
+/*!
+  @const kSCDynamicStoreDomainFile
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainFile;
+
+/*!
+  @const kSCDynamicStoreDomainPlugin
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainPlugin;
+
+/*!
+  @const kSCDynamicStoreDomainSetup
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainSetup;
+
+/*!
+  @const kSCDynamicStoreDomainState
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainState;
+
+/*!
+  @const kSCDynamicStoreDomainPrefs
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStoreDomainPrefs;
+
+/*!
+  @group Preference ("location") Keys
+ */
+
+/*!
+  @const kSCDynamicStorePropSetupCurrentSet
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropSetupCurrentSet;
+
+/*!
+  @const kSCDynamicStorePropSetupLastUpdated
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropSetupLastUpdated;
+
+/*!
+  @group Common/shared Keys
+ */
+
+/*!
+  @const kSCDynamicStorePropNetInterfaces
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetInterfaces;
+
+/*!
+  @const kSCDynamicStorePropNetPrimaryInterface
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetPrimaryInterface;
+
+/*!
+  @const kSCDynamicStorePropNetPrimaryService
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetPrimaryService;
+
+/*!
+  @const kSCDynamicStorePropNetServiceIDs
+  @availability Introduced in Mac OS X 10.1.
+ */
+extern const CFStringRef kSCDynamicStorePropNetServiceIDs;
+
+/*!
+  @const kSCPropUsersConsoleUserName
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropUsersConsoleUserName;
+
+/*!
+  @const kSCPropUsersConsoleUserUID
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropUsersConsoleUserUID;
+
+/*!
+  @const kSCPropUsersConsoleUserGID
+  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.
+ */
+extern const CFStringRef kSCPropUsersConsoleUserGID;
+
+#endif /* 0 */
+
+
+/* -------------------- Schema declarations -------------------- */
+
+
+#define kSCResvLink                                                   \
+       SC_SCHEMA_KV(kSCResvLink                                      \
+                   ,"__LINK__"                                       \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCResvLink,);
+
+#define kSCResvInactive                                               \
+       SC_SCHEMA_KV(kSCResvInactive                                  \
+                   ,"__INACTIVE__"                                   \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCResvInactive,);
+
+#define kSCPropInterfaceName                                          \
+       SC_SCHEMA_KV(kSCPropInterfaceName                             \
+                   ,"InterfaceName"                                  \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropInterfaceName,);
+
+#define kSCPropMACAddress                                             \
+       SC_SCHEMA_KV(kSCPropMACAddress                                \
+                   ,"MACAddress"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropMACAddress,);
+
+#define kSCPropUserDefinedName                                        \
+       SC_SCHEMA_KV(kSCPropUserDefinedName                           \
+                   ,"UserDefinedName"                                \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropUserDefinedName,);
+
+#define kSCPropVersion                                                \
+       SC_SCHEMA_KV(kSCPropVersion                                   \
+                   ,"Version"                                        \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropVersion,);
+
+#define kSCPrefCurrentSet                                             \
+       SC_SCHEMA_KV(kSCPrefCurrentSet                                \
+                   ,"CurrentSet"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPrefCurrentSet,);
+
+#define kSCPrefNetworkServices                                        \
+       SC_SCHEMA_KV(kSCPrefNetworkServices                           \
+                   ,"NetworkServices"                                \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCPrefNetworkServices,);
+
+#define kSCPrefSets                                                   \
+       SC_SCHEMA_KV(kSCPrefSets                                      \
+                   ,"Sets"                                           \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCPrefSets,);
+
+#define kSCPrefSystem                                                 \
+       SC_SCHEMA_KV(kSCPrefSystem                                    \
+                   ,"System"                                         \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCPrefSystem,);
+
+#define kSCCompNetwork                                                \
+       SC_SCHEMA_KV(kSCCompNetwork                                   \
+                   ,"Network"                                        \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompNetwork,);
+
+#define kSCCompService                                                \
+       SC_SCHEMA_KV(kSCCompService                                   \
+                   ,"Service"                                        \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompService,);
+
+#define kSCCompGlobal                                                 \
+       SC_SCHEMA_KV(kSCCompGlobal                                    \
+                   ,"Global"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompGlobal,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCCompHostNames                                              \
+       SC_SCHEMA_KV(kSCCompHostNames                                 \
+                   ,"HostNames"                                      \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCCompHostNames, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCCompInterface                                              \
+       SC_SCHEMA_KV(kSCCompInterface                                 \
+                   ,"Interface"                                      \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompInterface,);
+
+#define kSCCompSystem                                                 \
+       SC_SCHEMA_KV(kSCCompSystem                                    \
+                   ,"System"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompSystem,);
+
+#define kSCCompUsers                                                  \
+       SC_SCHEMA_KV(kSCCompUsers                                     \
+                   ,"Users"                                          \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompUsers,);
+
+#define kSCCompAnyRegex                                               \
+       SC_SCHEMA_KV(kSCCompAnyRegex                                  \
+                   ,"[^/]+"                                          \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCCompAnyRegex,);
+
+#define kSCEntNetAirPort                                              \
+       SC_SCHEMA_KV(kSCEntNetAirPort                                 \
+                   ,"AirPort"                                        \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetAirPort,);
+
+#define kSCEntNetAppleTalk                                            \
+       SC_SCHEMA_KV(kSCEntNetAppleTalk                               \
+                   ,"AppleTalk"                                      \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetAppleTalk,);
+
+#define kSCEntNetDHCP                                                 \
+       SC_SCHEMA_KV(kSCEntNetDHCP                                    \
+                   ,"DHCP"                                           \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetDHCP,);
+
+#define kSCEntNetDNS                                                  \
+       SC_SCHEMA_KV(kSCEntNetDNS                                     \
+                   ,"DNS"                                            \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetDNS,);
+
+#define kSCEntNetEthernet                                             \
+       SC_SCHEMA_KV(kSCEntNetEthernet                                \
+                   ,"Ethernet"                                       \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetEthernet,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetFireWire                                             \
+       SC_SCHEMA_KV(kSCEntNetFireWire                                \
+                   ,"FireWire"                                       \
+                   ,CFDictionary                                     )
+#endif
+       SC_SCHEMA_DECLARATION(kSCEntNetFireWire, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCEntNetInterface                                            \
+       SC_SCHEMA_KV(kSCEntNetInterface                               \
+                   ,"Interface"                                      \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetInterface,);
+
+#define kSCEntNetIPv4                                                 \
+       SC_SCHEMA_KV(kSCEntNetIPv4                                    \
+                   ,"IPv4"                                           \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetIPv4,);
+
+#define kSCEntNetIPv6                                                 \
+       SC_SCHEMA_KV(kSCEntNetIPv6                                    \
+                   ,"IPv6"                                           \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetIPv6,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetL2TP                                                 \
+       SC_SCHEMA_KV(kSCEntNetL2TP                                    \
+                   ,"L2TP"                                           \
+                   ,CFDictionary                                     )
+#endif
+       SC_SCHEMA_DECLARATION(kSCEntNetL2TP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCEntNetLink                                                 \
+       SC_SCHEMA_KV(kSCEntNetLink                                    \
+                   ,"Link"                                           \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetLink,);
+
+#define kSCEntNetModem                                                \
+       SC_SCHEMA_KV(kSCEntNetModem                                   \
+                   ,"Modem"                                          \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetModem,);
+
+#define kSCEntNetNetInfo                                              \
+       SC_SCHEMA_KV(kSCEntNetNetInfo                                 \
+                   ,"NetInfo"                                        \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetNetInfo,);
+
+#define kSCEntNetPPP                                                  \
+       SC_SCHEMA_KV(kSCEntNetPPP                                     \
+                   ,"PPP"                                            \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetPPP,);
+
+#define kSCEntNetPPPoE                                                \
+       SC_SCHEMA_KV(kSCEntNetPPPoE                                   \
+                   ,"PPPoE"                                          \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetPPPoE,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetPPPSerial                                            \
+       SC_SCHEMA_KV(kSCEntNetPPPSerial                               \
+                   ,"PPPSerial"                                      \
+                   ,CFDictionary                                     )
+#endif
+       SC_SCHEMA_DECLARATION(kSCEntNetPPPSerial, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNetPPTP                                                 \
+       SC_SCHEMA_KV(kSCEntNetPPTP                                    \
+                   ,"PPTP"                                           \
+                   ,CFDictionary                                     )
+#endif
+       SC_SCHEMA_DECLARATION(kSCEntNetPPTP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCEntNetProxies                                              \
+       SC_SCHEMA_KV(kSCEntNetProxies                                 \
+                   ,"Proxies"                                        \
+                   ,CFDictionary                                     )
+       SC_SCHEMA_DECLARATION(kSCEntNetProxies,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCEntNet6to4                                                 \
+       SC_SCHEMA_KV(kSCEntNet6to4                                    \
+                   ,"6to4"                                           \
+                   ,CFDictionary                                     )
+#endif
+       SC_SCHEMA_DECLARATION(kSCEntNet6to4, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetOverridePrimary                                     \
+       SC_SCHEMA_KV(kSCPropNetOverridePrimary                        \
+                   ,"OverridePrimary"                                \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetOverridePrimary, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetServiceOrder                                        \
+       SC_SCHEMA_KV(kSCPropNetServiceOrder                           \
+                   ,"ServiceOrder"                                   \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetServiceOrder,);
+
+#define kSCPropNetPPPOverridePrimary                                  \
+       SC_SCHEMA_KV(kSCPropNetPPPOverridePrimary                     \
+                   ,"PPPOverridePrimary"                             \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPOverridePrimary,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetInterfaces                                          \
+       SC_SCHEMA_KV(kSCPropNetInterfaces                             \
+                   ,"Interfaces"                                     \
+                   ,CFArray[CFString]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetInterfaces, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetLocalHostName                                       \
+       SC_SCHEMA_KV(kSCPropNetLocalHostName                          \
+                   ,"LocalHostName"                                  \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetLocalHostName, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAirPortAllowNetCreation                             \
+       SC_SCHEMA_KV(kSCPropNetAirPortAllowNetCreation                \
+                   ,"AllowNetCreation"                               \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortAllowNetCreation, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetAirPortAuthPassword                                 \
+       SC_SCHEMA_KV(kSCPropNetAirPortAuthPassword                    \
+                   ,"AuthPassword"                                   \
+                   ,CFData                                           )
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPassword,);
+
+#define kSCPropNetAirPortAuthPasswordEncryption                       \
+       SC_SCHEMA_KV(kSCPropNetAirPortAuthPasswordEncryption          \
+                   ,"AuthPasswordEncryption"                         \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortAuthPasswordEncryption,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAirPortJoinMode                                     \
+       SC_SCHEMA_KV(kSCPropNetAirPortJoinMode                        \
+                   ,"JoinMode"                                       \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortJoinMode, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetAirPortPowerEnabled                                 \
+       SC_SCHEMA_KV(kSCPropNetAirPortPowerEnabled                    \
+                   ,"PowerEnabled"                                   \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortPowerEnabled,);
+
+#define kSCPropNetAirPortPreferredNetwork                             \
+       SC_SCHEMA_KV(kSCPropNetAirPortPreferredNetwork                \
+                   ,"PreferredNetwork"                               \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortPreferredNetwork,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAirPortSavePasswords                                \
+       SC_SCHEMA_KV(kSCPropNetAirPortSavePasswords                   \
+                   ,"SavePasswords"                                  \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetAirPortSavePasswords, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetAirPortJoinModeAutomatic                             \
+       SC_SCHEMA_KV(kSCValNetAirPortJoinModeAutomatic                \
+                   ,"Automatic"                                      \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeAutomatic, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetAirPortJoinModePreferred                             \
+       SC_SCHEMA_KV(kSCValNetAirPortJoinModePreferred                \
+                   ,"Preferred"                                      \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModePreferred, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetAirPortJoinModeRecent                                \
+       SC_SCHEMA_KV(kSCValNetAirPortJoinModeRecent                   \
+                   ,"Recent"                                         \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeRecent, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetAirPortJoinModeStrongest                             \
+       SC_SCHEMA_KV(kSCValNetAirPortJoinModeStrongest                \
+                   ,"Strongest"                                      \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetAirPortJoinModeStrongest, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetAirPortAuthPasswordEncryptionKeychain                \
+       SC_SCHEMA_KV(kSCValNetAirPortAuthPasswordEncryptionKeychain   \
+                   ,"Keychain"                                       \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetAirPortAuthPasswordEncryptionKeychain, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetAppleTalkComputerName                               \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkComputerName                  \
+                   ,"ComputerName"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkComputerName,);
+
+#define kSCPropNetAppleTalkComputerNameEncoding                       \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkComputerNameEncoding          \
+                   ,"ComputerNameEncoding"                           \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkComputerNameEncoding,);
+
+#define kSCPropNetAppleTalkConfigMethod                               \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkConfigMethod                  \
+                   ,"ConfigMethod"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkConfigMethod,);
+
+#define kSCPropNetAppleTalkDefaultZone                                \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkDefaultZone                   \
+                   ,"DefaultZone"                                    \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkDefaultZone,);
+
+#define kSCPropNetAppleTalkNetworkID                                  \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkNetworkID                     \
+                   ,"NetworkID"                                      \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkNetworkID,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetAppleTalkNetworkRange                               \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkNetworkRange                  \
+                   ,"NetworkRange"                                   \
+                   ,CFArray[CFNumber]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkNetworkRange, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetAppleTalkNodeID                                     \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkNodeID                        \
+                   ,"NodeID"                                         \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkNodeID,);
+
+#define kSCPropNetAppleTalkSeedNetworkRange                           \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkSeedNetworkRange              \
+                   ,"SeedNetworkRange"                               \
+                   ,CFArray[CFNumber]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkSeedNetworkRange,);
+
+#define kSCPropNetAppleTalkSeedZones                                  \
+       SC_SCHEMA_KV(kSCPropNetAppleTalkSeedZones                     \
+                   ,"SeedZones"                                      \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetAppleTalkSeedZones,);
+
+#define kSCValNetAppleTalkConfigMethodNode                            \
+       SC_SCHEMA_KV(kSCValNetAppleTalkConfigMethodNode               \
+                   ,"Node"                                           \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetAppleTalkConfigMethodNode,);
+
+#define kSCValNetAppleTalkConfigMethodRouter                          \
+       SC_SCHEMA_KV(kSCValNetAppleTalkConfigMethodRouter             \
+                   ,"Router"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetAppleTalkConfigMethodRouter,);
+
+#define kSCValNetAppleTalkConfigMethodSeedRouter                      \
+       SC_SCHEMA_KV(kSCValNetAppleTalkConfigMethodSeedRouter         \
+                   ,"SeedRouter"                                     \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetAppleTalkConfigMethodSeedRouter,);
+
+#define kSCPropNetDNSDomainName                                       \
+       SC_SCHEMA_KV(kSCPropNetDNSDomainName                          \
+                   ,"DomainName"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSDomainName,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSOptions                                          \
+       SC_SCHEMA_KV(kSCPropNetDNSOptions                             \
+                   ,"Options"                                        \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSOptions, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetDNSSearchDomains                                    \
+       SC_SCHEMA_KV(kSCPropNetDNSSearchDomains                       \
+                   ,"SearchDomains"                                  \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSSearchDomains,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSSearchOrder                                      \
+       SC_SCHEMA_KV(kSCPropNetDNSSearchOrder                         \
+                   ,"SearchOrder"                                    \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSSearchOrder, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetDNSServerAddresses                                  \
+       SC_SCHEMA_KV(kSCPropNetDNSServerAddresses                     \
+                   ,"ServerAddresses"                                \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSServerAddresses,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSServerPort                                       \
+       SC_SCHEMA_KV(kSCPropNetDNSServerPort                          \
+                   ,"ServerPort"                                     \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSServerPort, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSServerTimeout                                    \
+       SC_SCHEMA_KV(kSCPropNetDNSServerTimeout                       \
+                   ,"ServerTimeout"                                  \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSServerTimeout, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetDNSSortList                                         \
+       SC_SCHEMA_KV(kSCPropNetDNSSortList                            \
+                   ,"SortList"                                       \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSSortList,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSSupplementalMatchDomains                         \
+       SC_SCHEMA_KV(kSCPropNetDNSSupplementalMatchDomains            \
+                   ,"SupplementalMatchDomains"                       \
+                   ,CFArray[CFString]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSSupplementalMatchDomains, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetDNSSupplementalMatchOrders                          \
+       SC_SCHEMA_KV(kSCPropNetDNSSupplementalMatchOrders             \
+                   ,"SupplementalMatchOrders"                        \
+                   ,CFArray[CFNumber]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetDNSSupplementalMatchOrders, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetEthernetMediaSubType                                \
+       SC_SCHEMA_KV(kSCPropNetEthernetMediaSubType                   \
+                   ,"MediaSubType"                                   \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetEthernetMediaSubType, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetEthernetMediaOptions                                \
+       SC_SCHEMA_KV(kSCPropNetEthernetMediaOptions                   \
+                   ,"MediaOptions"                                   \
+                   ,CFArray[CFString]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetEthernetMediaOptions, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetEthernetMTU                                         \
+       SC_SCHEMA_KV(kSCPropNetEthernetMTU                            \
+                   ,"MTU"                                            \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetEthernetMTU, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetInterfaceDeviceName                                 \
+       SC_SCHEMA_KV(kSCPropNetInterfaceDeviceName                    \
+                   ,"DeviceName"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetInterfaceDeviceName,);
+
+#define kSCPropNetInterfaceHardware                                   \
+       SC_SCHEMA_KV(kSCPropNetInterfaceHardware                      \
+                   ,"Hardware"                                       \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetInterfaceHardware,);
+
+#define kSCPropNetInterfaceType                                       \
+       SC_SCHEMA_KV(kSCPropNetInterfaceType                          \
+                   ,"Type"                                           \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetInterfaceType,);
+
+#define kSCPropNetInterfaceSubType                                    \
+       SC_SCHEMA_KV(kSCPropNetInterfaceSubType                       \
+                   ,"SubType"                                        \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetInterfaceSubType,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetInterfaceSupportsModemOnHold                        \
+       SC_SCHEMA_KV(kSCPropNetInterfaceSupportsModemOnHold           \
+                   ,"SupportsModemOnHold"                            \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetInterfaceSupportsModemOnHold, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCValNetInterfaceTypeEthernet                                \
+       SC_SCHEMA_KV(kSCValNetInterfaceTypeEthernet                   \
+                   ,"Ethernet"                                       \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceTypeEthernet,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetInterfaceTypeFireWire                                \
+       SC_SCHEMA_KV(kSCValNetInterfaceTypeFireWire                   \
+                   ,"FireWire"                                       \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceTypeFireWire, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetInterfaceTypePPP                                     \
+       SC_SCHEMA_KV(kSCValNetInterfaceTypePPP                        \
+                   ,"PPP"                                            \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceTypePPP,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetInterfaceType6to4                                    \
+       SC_SCHEMA_KV(kSCValNetInterfaceType6to4                       \
+                   ,"6to4"                                           \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceType6to4, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetInterfaceSubTypePPPoE                                \
+       SC_SCHEMA_KV(kSCValNetInterfaceSubTypePPPoE                   \
+                   ,"PPPoE"                                          \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypePPPoE,);
+
+#define kSCValNetInterfaceSubTypePPPSerial                            \
+       SC_SCHEMA_KV(kSCValNetInterfaceSubTypePPPSerial               \
+                   ,"PPPSerial"                                      \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypePPPSerial,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetInterfaceSubTypePPTP                                 \
+       SC_SCHEMA_KV(kSCValNetInterfaceSubTypePPTP                    \
+                   ,"PPTP"                                           \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypePPTP, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetInterfaceSubTypeL2TP                                 \
+       SC_SCHEMA_KV(kSCValNetInterfaceSubTypeL2TP                    \
+                   ,"L2TP"                                           \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetInterfaceSubTypeL2TP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetIPv4Addresses                                       \
+       SC_SCHEMA_KV(kSCPropNetIPv4Addresses                          \
+                   ,"Addresses"                                      \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4Addresses,);
+
+#define kSCPropNetIPv4ConfigMethod                                    \
+       SC_SCHEMA_KV(kSCPropNetIPv4ConfigMethod                       \
+                   ,"ConfigMethod"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4ConfigMethod,);
+
+#define kSCPropNetIPv4DHCPClientID                                    \
+       SC_SCHEMA_KV(kSCPropNetIPv4DHCPClientID                       \
+                   ,"DHCPClientID"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4DHCPClientID,);
+
+#define kSCPropNetIPv4Router                                          \
+       SC_SCHEMA_KV(kSCPropNetIPv4Router                             \
+                   ,"Router"                                         \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4Router,);
+
+#define kSCPropNetIPv4SubnetMasks                                     \
+       SC_SCHEMA_KV(kSCPropNetIPv4SubnetMasks                        \
+                   ,"SubnetMasks"                                    \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4SubnetMasks,);
+
+#define kSCPropNetIPv4DestAddresses                                   \
+       SC_SCHEMA_KV(kSCPropNetIPv4DestAddresses                      \
+                   ,"DestAddresses"                                  \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4DestAddresses,);
+
+#define kSCPropNetIPv4BroadcastAddresses                              \
+       SC_SCHEMA_KV(kSCPropNetIPv4BroadcastAddresses                 \
+                   ,"BroadcastAddresses"                             \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv4BroadcastAddresses,);
+
+#define kSCValNetIPv4ConfigMethodBOOTP                                \
+       SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodBOOTP                   \
+                   ,"BOOTP"                                          \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodBOOTP,);
+
+#define kSCValNetIPv4ConfigMethodDHCP                                 \
+       SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodDHCP                    \
+                   ,"DHCP"                                           \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodDHCP,);
+
+#define kSCValNetIPv4ConfigMethodINFORM                               \
+       SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodINFORM                  \
+                   ,"INFORM"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodINFORM,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCValNetIPv4ConfigMethodLinkLocal                            \
+       SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodLinkLocal               \
+                   ,"LinkLocal"                                      \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodLinkLocal, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCValNetIPv4ConfigMethodManual                               \
+       SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodManual                  \
+                   ,"Manual"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodManual,);
+
+#define kSCValNetIPv4ConfigMethodPPP                                  \
+       SC_SCHEMA_KV(kSCValNetIPv4ConfigMethodPPP                     \
+                   ,"PPP"                                            \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetIPv4ConfigMethodPPP,);
+
+#define kSCPropNetIPv6Addresses                                       \
+       SC_SCHEMA_KV(kSCPropNetIPv6Addresses                          \
+                   ,"Addresses"                                      \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv6Addresses,);
+
+#define kSCPropNetIPv6ConfigMethod                                    \
+       SC_SCHEMA_KV(kSCPropNetIPv6ConfigMethod                       \
+                   ,"ConfigMethod"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv6ConfigMethod,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6DestAddresses                                   \
+       SC_SCHEMA_KV(kSCPropNetIPv6DestAddresses                      \
+                   ,"DestAddresses"                                  \
+                   ,CFArray[CFString]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv6DestAddresses, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6Flags                                           \
+       SC_SCHEMA_KV(kSCPropNetIPv6Flags                              \
+                   ,"Flags"                                          \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv6Flags, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6PrefixLength                                    \
+       SC_SCHEMA_KV(kSCPropNetIPv6PrefixLength                       \
+                   ,"PrefixLength"                                   \
+                   ,CFArray[CFNumber]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv6PrefixLength, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetIPv6Router                                          \
+       SC_SCHEMA_KV(kSCPropNetIPv6Router                             \
+                   ,"Router"                                         \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetIPv6Router, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethodAutomatic                            \
+       SC_SCHEMA_KV(kSCValNetIPv6ConfigMethodAutomatic               \
+                   ,"Automatic"                                      \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethodAutomatic, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethodManual                               \
+       SC_SCHEMA_KV(kSCValNetIPv6ConfigMethodManual                  \
+                   ,"Manual"                                         \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethodManual, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethodRouterAdvertisement                  \
+       SC_SCHEMA_KV(kSCValNetIPv6ConfigMethodRouterAdvertisement     \
+                   ,"RouterAdvertisement"                            \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethodRouterAdvertisement, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetIPv6ConfigMethod6to4                                 \
+       SC_SCHEMA_KV(kSCValNetIPv6ConfigMethod6to4                    \
+                   ,"6to4"                                           \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetIPv6ConfigMethod6to4, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNet6to4Relay                                           \
+       SC_SCHEMA_KV(kSCPropNet6to4Relay                              \
+                   ,"Relay"                                          \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNet6to4Relay, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetLinkActive                                          \
+       SC_SCHEMA_KV(kSCPropNetLinkActive                             \
+                   ,"Active"                                         \
+                   ,CFBoolean                                        )
+       SC_SCHEMA_DECLARATION(kSCPropNetLinkActive,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetLinkDetaching                                       \
+       SC_SCHEMA_KV(kSCPropNetLinkDetaching                          \
+                   ,"Detaching"                                      \
+                   ,CFBoolean                                        )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetLinkDetaching, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetModemConnectionScript                               \
+       SC_SCHEMA_KV(kSCPropNetModemConnectionScript                  \
+                   ,"ConnectionScript"                               \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemConnectionScript,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemConnectSpeed                                   \
+       SC_SCHEMA_KV(kSCPropNetModemConnectSpeed                      \
+                   ,"ConnectSpeed"                                   \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemConnectSpeed, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetModemDataCompression                                \
+       SC_SCHEMA_KV(kSCPropNetModemDataCompression                   \
+                   ,"DataCompression"                                \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemDataCompression,);
+
+#define kSCPropNetModemDialMode                                       \
+       SC_SCHEMA_KV(kSCPropNetModemDialMode                          \
+                   ,"DialMode"                                       \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemDialMode,);
+
+#define kSCPropNetModemErrorCorrection                                \
+       SC_SCHEMA_KV(kSCPropNetModemErrorCorrection                   \
+                   ,"ErrorCorrection"                                \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemErrorCorrection,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldCallWaitingAudibleAlert                    \
+       SC_SCHEMA_KV(kSCPropNetModemHoldCallWaitingAudibleAlert       \
+                   ,"HoldCallWaitingAudibleAlert"                    \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemHoldCallWaitingAudibleAlert, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldDisconnectOnAnswer                         \
+       SC_SCHEMA_KV(kSCPropNetModemHoldDisconnectOnAnswer            \
+                   ,"HoldDisconnectOnAnswer"                         \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemHoldDisconnectOnAnswer, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldEnabled                                    \
+       SC_SCHEMA_KV(kSCPropNetModemHoldEnabled                       \
+                   ,"HoldEnabled"                                    \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemHoldEnabled, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldReminder                                   \
+       SC_SCHEMA_KV(kSCPropNetModemHoldReminder                      \
+                   ,"HoldReminder"                                   \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemHoldReminder, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemHoldReminderTime                               \
+       SC_SCHEMA_KV(kSCPropNetModemHoldReminderTime                  \
+                   ,"HoldReminderTime"                               \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemHoldReminderTime, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetModemNote                                           \
+       SC_SCHEMA_KV(kSCPropNetModemNote                              \
+                   ,"Note"                                           \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetModemNote, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetModemPulseDial                                      \
+       SC_SCHEMA_KV(kSCPropNetModemPulseDial                         \
+                   ,"PulseDial"                                      \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemPulseDial,);
+
+#define kSCPropNetModemSpeaker                                        \
+       SC_SCHEMA_KV(kSCPropNetModemSpeaker                           \
+                   ,"Speaker"                                        \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemSpeaker,);
+
+#define kSCPropNetModemSpeed                                          \
+       SC_SCHEMA_KV(kSCPropNetModemSpeed                             \
+                   ,"Speed"                                          \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetModemSpeed,);
+
+#define kSCValNetModemDialModeIgnoreDialTone                          \
+       SC_SCHEMA_KV(kSCValNetModemDialModeIgnoreDialTone             \
+                   ,"IgnoreDialTone"                                 \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetModemDialModeIgnoreDialTone,);
+
+#define kSCValNetModemDialModeManual                                  \
+       SC_SCHEMA_KV(kSCValNetModemDialModeManual                     \
+                   ,"Manual"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetModemDialModeManual,);
+
+#define kSCValNetModemDialModeWaitForDialTone                         \
+       SC_SCHEMA_KV(kSCValNetModemDialModeWaitForDialTone            \
+                   ,"WaitForDialTone"                                \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetModemDialModeWaitForDialTone,);
+
+#define kSCPropNetNetInfoBindingMethods                               \
+       SC_SCHEMA_KV(kSCPropNetNetInfoBindingMethods                  \
+                   ,"BindingMethods"                                 \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetNetInfoBindingMethods,);
+
+#define kSCPropNetNetInfoServerAddresses                              \
+       SC_SCHEMA_KV(kSCPropNetNetInfoServerAddresses                 \
+                   ,"ServerAddresses"                                \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetNetInfoServerAddresses,);
+
+#define kSCPropNetNetInfoServerTags                                   \
+       SC_SCHEMA_KV(kSCPropNetNetInfoServerTags                      \
+                   ,"ServerTags"                                     \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetNetInfoServerTags,);
+
+#define kSCPropNetNetInfoBroadcastServerTag                           \
+       SC_SCHEMA_KV(kSCPropNetNetInfoBroadcastServerTag              \
+                   ,"BroadcastServerTag"                             \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetNetInfoBroadcastServerTag,);
+
+#define kSCValNetNetInfoBindingMethodsBroadcast                       \
+       SC_SCHEMA_KV(kSCValNetNetInfoBindingMethodsBroadcast          \
+                   ,"Broadcast"                                      \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetNetInfoBindingMethodsBroadcast,);
+
+#define kSCValNetNetInfoBindingMethodsDHCP                            \
+       SC_SCHEMA_KV(kSCValNetNetInfoBindingMethodsDHCP               \
+                   ,"DHCP"                                           \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetNetInfoBindingMethodsDHCP,);
+
+#define kSCValNetNetInfoBindingMethodsManual                          \
+       SC_SCHEMA_KV(kSCValNetNetInfoBindingMethodsManual             \
+                   ,"Manual"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetNetInfoBindingMethodsManual,);
+
+#define kSCValNetNetInfoDefaultServerTag                              \
+       SC_SCHEMA_KV(kSCValNetNetInfoDefaultServerTag                 \
+                   ,"network"                                        \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCValNetNetInfoDefaultServerTag,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPACSPEnabled                                      \
+       SC_SCHEMA_KV(kSCPropNetPPPACSPEnabled                         \
+                   ,"ACSPEnabled"                                    \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPACSPEnabled, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPConnectTime                                      \
+       SC_SCHEMA_KV(kSCPropNetPPPConnectTime                         \
+                   ,"ConnectTime"                                    \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPConnectTime, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPDeviceLastCause                                  \
+       SC_SCHEMA_KV(kSCPropNetPPPDeviceLastCause                     \
+                   ,"DeviceLastCause"                                \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDeviceLastCause, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetPPPDialOnDemand                                     \
+       SC_SCHEMA_KV(kSCPropNetPPPDialOnDemand                        \
+                   ,"DialOnDemand"                                   \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDialOnDemand,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPDisconnectOnFastUserSwitch                       \
+       SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnFastUserSwitch          \
+                   ,"DisconnectOnFastUserSwitch"                     \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnFastUserSwitch, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetPPPDisconnectOnIdle                                 \
+       SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnIdle                    \
+                   ,"DisconnectOnIdle"                               \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnIdle,);
+
+#define kSCPropNetPPPDisconnectOnIdleTimer                            \
+       SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnIdleTimer               \
+                   ,"DisconnectOnIdleTimer"                          \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnIdleTimer,);
+
+#define kSCPropNetPPPDisconnectOnLogout                               \
+       SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnLogout                  \
+                   ,"DisconnectOnLogout"                             \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnLogout,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPDisconnectOnSleep                                \
+       SC_SCHEMA_KV(kSCPropNetPPPDisconnectOnSleep                   \
+                   ,"DisconnectOnSleep"                              \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectOnSleep, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPDisconnectTime                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPDisconnectTime                      \
+                   ,"DisconnectTime"                                 \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPDisconnectTime, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPIdleReminderTimer                                \
+       SC_SCHEMA_KV(kSCPropNetPPPIdleReminderTimer                   \
+                   ,"IdleReminderTimer"                              \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPIdleReminderTimer,);
+
+#define kSCPropNetPPPIdleReminder                                     \
+       SC_SCHEMA_KV(kSCPropNetPPPIdleReminder                        \
+                   ,"IdleReminder"                                   \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPIdleReminder,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPLastCause                                        \
+       SC_SCHEMA_KV(kSCPropNetPPPLastCause                           \
+                   ,"LastCause"                                      \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLastCause, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetPPPLogfile                                          \
+       SC_SCHEMA_KV(kSCPropNetPPPLogfile                             \
+                   ,"Logfile"                                        \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLogfile,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPPlugins                                          \
+       SC_SCHEMA_KV(kSCPropNetPPPPlugins                             \
+                   ,"Plugins"                                        \
+                   ,CFArray[CFString]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPPlugins, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPRetryConnectTime                                 \
+       SC_SCHEMA_KV(kSCPropNetPPPRetryConnectTime                    \
+                   ,"RetryConnectTime"                               \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPRetryConnectTime, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPSessionTimer                                     \
+       SC_SCHEMA_KV(kSCPropNetPPPSessionTimer                        \
+                   ,"SessionTimer"                                   \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPSessionTimer,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPStatus                                           \
+       SC_SCHEMA_KV(kSCPropNetPPPStatus                              \
+                   ,"Status"                                         \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPStatus, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPUseSessionTimer                                  \
+       SC_SCHEMA_KV(kSCPropNetPPPUseSessionTimer                     \
+                   ,"UseSessionTimer"                                \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPUseSessionTimer, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#define kSCPropNetPPPVerboseLogging                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPVerboseLogging                      \
+                   ,"VerboseLogging"                                 \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPVerboseLogging,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPAuthEAPPlugins                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPAuthEAPPlugins                      \
+                   ,"AuthEAPPlugins"                                 \
+                   ,CFArray[CFString]                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthEAPPlugins, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPAuthName                                         \
+       SC_SCHEMA_KV(kSCPropNetPPPAuthName                            \
+                   ,"AuthName"                                       \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthName,);
+
+#define kSCPropNetPPPAuthPassword                                     \
+       SC_SCHEMA_KV(kSCPropNetPPPAuthPassword                        \
+                   ,"AuthPassword"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthPassword,);
+
+#define kSCPropNetPPPAuthPasswordEncryption                           \
+       SC_SCHEMA_KV(kSCPropNetPPPAuthPasswordEncryption              \
+                   ,"AuthPasswordEncryption"                         \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthPasswordEncryption,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetPPPAuthPrompt                                       \
+       SC_SCHEMA_KV(kSCPropNetPPPAuthPrompt                          \
+                   ,"AuthPrompt"                                     \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthPrompt, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetPPPAuthProtocol                                     \
+       SC_SCHEMA_KV(kSCPropNetPPPAuthProtocol                        \
+                   ,"AuthProtocol"                                   \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPAuthProtocol,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthPasswordEncryptionKeychain                    \
+       SC_SCHEMA_KV(kSCValNetPPPAuthPasswordEncryptionKeychain       \
+                   ,"Keychain"                                       \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthPasswordEncryptionKeychain, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthPromptBefore                                  \
+       SC_SCHEMA_KV(kSCValNetPPPAuthPromptBefore                     \
+                   ,"Before"                                         \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthPromptBefore, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthPromptAfter                                   \
+       SC_SCHEMA_KV(kSCValNetPPPAuthPromptAfter                      \
+                   ,"After"                                          \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthPromptAfter, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetPPPAuthProtocolCHAP                                  \
+       SC_SCHEMA_KV(kSCValNetPPPAuthProtocolCHAP                     \
+                   ,"CHAP"                                           \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolCHAP,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthProtocolEAP                                   \
+       SC_SCHEMA_KV(kSCValNetPPPAuthProtocolEAP                      \
+                   ,"EAP"                                            \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolEAP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthProtocolMSCHAP1                               \
+       SC_SCHEMA_KV(kSCValNetPPPAuthProtocolMSCHAP1                  \
+                   ,"MSCHAP1"                                        \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolMSCHAP1, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetPPPAuthProtocolMSCHAP2                               \
+       SC_SCHEMA_KV(kSCValNetPPPAuthProtocolMSCHAP2                  \
+                   ,"MSCHAP2"                                        \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolMSCHAP2, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCValNetPPPAuthProtocolPAP                                   \
+       SC_SCHEMA_KV(kSCValNetPPPAuthProtocolPAP                      \
+                   ,"PAP"                                            \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCValNetPPPAuthProtocolPAP,);
+
+#define kSCPropNetPPPCommAlternateRemoteAddress                       \
+       SC_SCHEMA_KV(kSCPropNetPPPCommAlternateRemoteAddress          \
+                   ,"CommAlternateRemoteAddress"                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommAlternateRemoteAddress,);
+
+#define kSCPropNetPPPCommConnectDelay                                 \
+       SC_SCHEMA_KV(kSCPropNetPPPCommConnectDelay                    \
+                   ,"CommConnectDelay"                               \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommConnectDelay,);
+
+#define kSCPropNetPPPCommDisplayTerminalWindow                        \
+       SC_SCHEMA_KV(kSCPropNetPPPCommDisplayTerminalWindow           \
+                   ,"CommDisplayTerminalWindow"                      \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommDisplayTerminalWindow,);
+
+#define kSCPropNetPPPCommRedialCount                                  \
+       SC_SCHEMA_KV(kSCPropNetPPPCommRedialCount                     \
+                   ,"CommRedialCount"                                \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRedialCount,);
+
+#define kSCPropNetPPPCommRedialEnabled                                \
+       SC_SCHEMA_KV(kSCPropNetPPPCommRedialEnabled                   \
+                   ,"CommRedialEnabled"                              \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRedialEnabled,);
+
+#define kSCPropNetPPPCommRedialInterval                               \
+       SC_SCHEMA_KV(kSCPropNetPPPCommRedialInterval                  \
+                   ,"CommRedialInterval"                             \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRedialInterval,);
+
+#define kSCPropNetPPPCommRemoteAddress                                \
+       SC_SCHEMA_KV(kSCPropNetPPPCommRemoteAddress                   \
+                   ,"CommRemoteAddress"                              \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommRemoteAddress,);
+
+#define kSCPropNetPPPCommTerminalScript                               \
+       SC_SCHEMA_KV(kSCPropNetPPPCommTerminalScript                  \
+                   ,"CommTerminalScript"                             \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommTerminalScript,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPCommUseTerminalScript                            \
+       SC_SCHEMA_KV(kSCPropNetPPPCommUseTerminalScript               \
+                   ,"CommUseTerminalScript"                          \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCommUseTerminalScript, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+#define kSCPropNetPPPCCPEnabled                                       \
+       SC_SCHEMA_KV(kSCPropNetPPPCCPEnabled                          \
+                   ,"CCPEnabled"                                     \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCCPEnabled, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPCCPMPPE40Enabled                                 \
+       SC_SCHEMA_KV(kSCPropNetPPPCCPMPPE40Enabled                    \
+                   ,"CCPMPPE40Enabled"                               \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCCPMPPE40Enabled, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPCCPMPPE128Enabled                                \
+       SC_SCHEMA_KV(kSCPropNetPPPCCPMPPE128Enabled                   \
+                   ,"CCPMPPE128Enabled"                              \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPCCPMPPE128Enabled, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetPPPIPCPCompressionVJ                                \
+       SC_SCHEMA_KV(kSCPropNetPPPIPCPCompressionVJ                   \
+                   ,"IPCPCompressionVJ"                              \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPIPCPCompressionVJ,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetPPPIPCPUsePeerDNS                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPIPCPUsePeerDNS                      \
+                   ,"IPCPUsePeerDNS"                                 \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPIPCPUsePeerDNS, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetPPPLCPEchoEnabled                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPEchoEnabled                      \
+                   ,"LCPEchoEnabled"                                 \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPEchoEnabled,);
+
+#define kSCPropNetPPPLCPEchoFailure                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPEchoFailure                      \
+                   ,"LCPEchoFailure"                                 \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPEchoFailure,);
+
+#define kSCPropNetPPPLCPEchoInterval                                  \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPEchoInterval                     \
+                   ,"LCPEchoInterval"                                \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPEchoInterval,);
+
+#define kSCPropNetPPPLCPCompressionACField                            \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPCompressionACField               \
+                   ,"LCPCompressionACField"                          \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPCompressionACField,);
+
+#define kSCPropNetPPPLCPCompressionPField                             \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPCompressionPField                \
+                   ,"LCPCompressionPField"                           \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPCompressionPField,);
+
+#define kSCPropNetPPPLCPMRU                                           \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPMRU                              \
+                   ,"LCPMRU"                                         \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPMRU,);
+
+#define kSCPropNetPPPLCPMTU                                           \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPMTU                              \
+                   ,"LCPMTU"                                         \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPMTU,);
+
+#define kSCPropNetPPPLCPReceiveACCM                                   \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPReceiveACCM                      \
+                   ,"LCPReceiveACCM"                                 \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPReceiveACCM,);
+
+#define kSCPropNetPPPLCPTransmitACCM                                  \
+       SC_SCHEMA_KV(kSCPropNetPPPLCPTransmitACCM                     \
+                   ,"LCPTransmitACCM"                                \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetPPPLCPTransmitACCM,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetL2TPIPSecSharedSecret                               \
+       SC_SCHEMA_KV(kSCPropNetL2TPIPSecSharedSecret                  \
+                   ,"IPSecSharedSecret"                              \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetL2TPIPSecSharedSecret, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetL2TPIPSecSharedSecretEncryption                     \
+       SC_SCHEMA_KV(kSCPropNetL2TPIPSecSharedSecretEncryption        \
+                   ,"IPSecSharedSecretEncryption"                    \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetL2TPIPSecSharedSecretEncryption, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCPropNetL2TPTransport                                       \
+       SC_SCHEMA_KV(kSCPropNetL2TPTransport                          \
+                   ,"Transport"                                      \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetL2TPTransport, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetL2TPIPSecSharedSecretEncryptionKeychain              \
+       SC_SCHEMA_KV(kSCValNetL2TPIPSecSharedSecretEncryptionKeychain \
+                   ,"Keychain"                                       \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetL2TPIPSecSharedSecretEncryptionKeychain, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetL2TPTransportIP                                      \
+       SC_SCHEMA_KV(kSCValNetL2TPTransportIP                         \
+                   ,"IP"                                             \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetL2TPTransportIP, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
+#define kSCValNetL2TPTransportIPSec                                   \
+       SC_SCHEMA_KV(kSCValNetL2TPTransportIPSec                      \
+                   ,"IPSec"                                          \
+                   ,                                                 )
+#endif
+       SC_SCHEMA_DECLARATION(kSCValNetL2TPTransportIPSec, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);
+
+#define kSCPropNetProxiesExceptionsList                               \
+       SC_SCHEMA_KV(kSCPropNetProxiesExceptionsList                  \
+                   ,"ExceptionsList"                                 \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesExceptionsList,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesExcludeSimpleHostnames                       \
+       SC_SCHEMA_KV(kSCPropNetProxiesExcludeSimpleHostnames          \
+                   ,"ExcludeSimpleHostnames"                         \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesExcludeSimpleHostnames, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCPropNetProxiesFTPEnable                                    \
+       SC_SCHEMA_KV(kSCPropNetProxiesFTPEnable                       \
+                   ,"FTPEnable"                                      \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPEnable,);
+
+#define kSCPropNetProxiesFTPPassive                                   \
+       SC_SCHEMA_KV(kSCPropNetProxiesFTPPassive                      \
+                   ,"FTPPassive"                                     \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPPassive,);
+
+#define kSCPropNetProxiesFTPPort                                      \
+       SC_SCHEMA_KV(kSCPropNetProxiesFTPPort                         \
+                   ,"FTPPort"                                        \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPPort,);
+
+#define kSCPropNetProxiesFTPProxy                                     \
+       SC_SCHEMA_KV(kSCPropNetProxiesFTPProxy                        \
+                   ,"FTPProxy"                                       \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesFTPProxy,);
+
+#define kSCPropNetProxiesGopherEnable                                 \
+       SC_SCHEMA_KV(kSCPropNetProxiesGopherEnable                    \
+                   ,"GopherEnable"                                   \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesGopherEnable,);
+
+#define kSCPropNetProxiesGopherPort                                   \
+       SC_SCHEMA_KV(kSCPropNetProxiesGopherPort                      \
+                   ,"GopherPort"                                     \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesGopherPort,);
+
+#define kSCPropNetProxiesGopherProxy                                  \
+       SC_SCHEMA_KV(kSCPropNetProxiesGopherProxy                     \
+                   ,"GopherProxy"                                    \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesGopherProxy,);
+
+#define kSCPropNetProxiesHTTPEnable                                   \
+       SC_SCHEMA_KV(kSCPropNetProxiesHTTPEnable                      \
+                   ,"HTTPEnable"                                     \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPEnable,);
+
+#define kSCPropNetProxiesHTTPPort                                     \
+       SC_SCHEMA_KV(kSCPropNetProxiesHTTPPort                        \
+                   ,"HTTPPort"                                       \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPPort,);
+
+#define kSCPropNetProxiesHTTPProxy                                    \
+       SC_SCHEMA_KV(kSCPropNetProxiesHTTPProxy                       \
+                   ,"HTTPProxy"                                      \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPProxy,);
+
+#define kSCPropNetProxiesHTTPSEnable                                  \
+       SC_SCHEMA_KV(kSCPropNetProxiesHTTPSEnable                     \
+                   ,"HTTPSEnable"                                    \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPSEnable,);
+
+#define kSCPropNetProxiesHTTPSPort                                    \
+       SC_SCHEMA_KV(kSCPropNetProxiesHTTPSPort                       \
+                   ,"HTTPSPort"                                      \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPSPort,);
+
+#define kSCPropNetProxiesHTTPSProxy                                   \
+       SC_SCHEMA_KV(kSCPropNetProxiesHTTPSProxy                      \
+                   ,"HTTPSProxy"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesHTTPSProxy,);
+
+#define kSCPropNetProxiesRTSPEnable                                   \
+       SC_SCHEMA_KV(kSCPropNetProxiesRTSPEnable                      \
+                   ,"RTSPEnable"                                     \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesRTSPEnable,);
+
+#define kSCPropNetProxiesRTSPPort                                     \
+       SC_SCHEMA_KV(kSCPropNetProxiesRTSPPort                        \
+                   ,"RTSPPort"                                       \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesRTSPPort,);
+
+#define kSCPropNetProxiesRTSPProxy                                    \
+       SC_SCHEMA_KV(kSCPropNetProxiesRTSPProxy                       \
+                   ,"RTSPProxy"                                      \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesRTSPProxy,);
+
+#define kSCPropNetProxiesSOCKSEnable                                  \
+       SC_SCHEMA_KV(kSCPropNetProxiesSOCKSEnable                     \
+                   ,"SOCKSEnable"                                    \
+                   ,CFNumber (0 or 1)                                )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesSOCKSEnable,);
+
+#define kSCPropNetProxiesSOCKSPort                                    \
+       SC_SCHEMA_KV(kSCPropNetProxiesSOCKSPort                       \
+                   ,"SOCKSPort"                                      \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesSOCKSPort,);
+
+#define kSCPropNetProxiesSOCKSProxy                                   \
+       SC_SCHEMA_KV(kSCPropNetProxiesSOCKSProxy                      \
+                   ,"SOCKSProxy"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesSOCKSProxy,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesProxyAutoConfigEnable                        \
+       SC_SCHEMA_KV(kSCPropNetProxiesProxyAutoConfigEnable           \
+                   ,"ProxyAutoConfigEnable"                          \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesProxyAutoConfigEnable, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesProxyAutoConfigURLString                     \
+       SC_SCHEMA_KV(kSCPropNetProxiesProxyAutoConfigURLString        \
+                   ,"ProxyAutoConfigURLString"                       \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesProxyAutoConfigURLString, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
+#define kSCPropNetProxiesProxyAutoDiscoveryEnable                     \
+       SC_SCHEMA_KV(kSCPropNetProxiesProxyAutoDiscoveryEnable        \
+                   ,"ProxyAutoDiscoveryEnable"                       \
+                   ,CFNumber (0 or 1)                                )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropNetProxiesProxyAutoDiscoveryEnable, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);
+
+#define kSCEntUsersConsoleUser                                        \
+       SC_SCHEMA_KV(kSCEntUsersConsoleUser                           \
+                   ,"ConsoleUser"                                    \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCEntUsersConsoleUser,);
+
+#define kSCPropSystemComputerName                                     \
+       SC_SCHEMA_KV(kSCPropSystemComputerName                        \
+                   ,"ComputerName"                                   \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCPropSystemComputerName,);
+
+#define kSCPropSystemComputerNameEncoding                             \
+       SC_SCHEMA_KV(kSCPropSystemComputerNameEncoding                \
+                   ,"ComputerNameEncoding"                           \
+                   ,CFNumber                                         )
+       SC_SCHEMA_DECLARATION(kSCPropSystemComputerNameEncoding,);
+
+#define kSCDynamicStoreDomainFile                                     \
+       SC_SCHEMA_KV(kSCDynamicStoreDomainFile                        \
+                   ,"File:"                                          \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainFile,);
+
+#define kSCDynamicStoreDomainPlugin                                   \
+       SC_SCHEMA_KV(kSCDynamicStoreDomainPlugin                      \
+                   ,"Plugin:"                                        \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainPlugin,);
+
+#define kSCDynamicStoreDomainSetup                                    \
+       SC_SCHEMA_KV(kSCDynamicStoreDomainSetup                       \
+                   ,"Setup:"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainSetup,);
+
+#define kSCDynamicStoreDomainState                                    \
+       SC_SCHEMA_KV(kSCDynamicStoreDomainState                       \
+                   ,"State:"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainState,);
+
+#define kSCDynamicStoreDomainPrefs                                    \
+       SC_SCHEMA_KV(kSCDynamicStoreDomainPrefs                       \
+                   ,"Prefs:"                                         \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCDynamicStoreDomainPrefs,);
+
+#define kSCDynamicStorePropSetupCurrentSet                            \
+       SC_SCHEMA_KV(kSCDynamicStorePropSetupCurrentSet               \
+                   ,"CurrentSet"                                     \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCDynamicStorePropSetupCurrentSet,);
+
+#define kSCDynamicStorePropSetupLastUpdated                           \
+       SC_SCHEMA_KV(kSCDynamicStorePropSetupLastUpdated              \
+                   ,"LastUpdated"                                    \
+                   ,                                                 )
+       SC_SCHEMA_DECLARATION(kSCDynamicStorePropSetupLastUpdated,);
+
+#define kSCDynamicStorePropNetInterfaces                              \
+       SC_SCHEMA_KV(kSCDynamicStorePropNetInterfaces                 \
+                   ,"Interfaces"                                     \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetInterfaces,);
+
+#define kSCDynamicStorePropNetPrimaryInterface                        \
+       SC_SCHEMA_KV(kSCDynamicStorePropNetPrimaryInterface           \
+                   ,"PrimaryInterface"                               \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetPrimaryInterface,);
+
+#define kSCDynamicStorePropNetPrimaryService                          \
+       SC_SCHEMA_KV(kSCDynamicStorePropNetPrimaryService             \
+                   ,"PrimaryService"                                 \
+                   ,CFString                                         )
+       SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetPrimaryService,);
+
+#define kSCDynamicStorePropNetServiceIDs                              \
+       SC_SCHEMA_KV(kSCDynamicStorePropNetServiceIDs                 \
+                   ,"ServiceIDs"                                     \
+                   ,CFArray[CFString]                                )
+       SC_SCHEMA_DECLARATION(kSCDynamicStorePropNetServiceIDs,);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \
+    MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
+#define kSCPropUsersConsoleUserName                                   \
+       SC_SCHEMA_KV(kSCPropUsersConsoleUserName                      \
+                   ,"Name"                                           \
+                   ,CFString                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropUsersConsoleUserName, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \
+    MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
+#define kSCPropUsersConsoleUserUID                                    \
+       SC_SCHEMA_KV(kSCPropUsersConsoleUserUID                       \
+                   ,"UID"                                            \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropUsersConsoleUserUID, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \
+    MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3
+#define kSCPropUsersConsoleUserGID                                    \
+       SC_SCHEMA_KV(kSCPropUsersConsoleUserGID                       \
+                   ,"GID"                                            \
+                   ,CFNumber                                         )
+#endif
+       SC_SCHEMA_DECLARATION(kSCPropUsersConsoleUserGID, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);
+
+#endif /* _SCSCHEMADEFINITIONS_H */
index 5d74bbc0a8d314287e22615f3ae7debdd1927a7c..5ea4d25707057f8f4be5f1a4c0c4819d94b6fe81 100644 (file)
 
 
 /*!
 
 
 /*!
-       @header SystemConfiguration.h
-       The SystemConfiguration framework provides access to the
-       data used to configure a running system.  The APIs provided
-       by this framework communicate with the "configd" daemon.
-
-       The "configd" daemon manages a "dynamic store" reflecting the
-       desired configuration settings as well as the current state
-       of the system.  The daemon provides a notification mechanism
-       for user-level processes which need to be aware of changes
-       made to the data.  Lastly, the daemon loads a number of
-       bundles (or plug-ins) that monitor low-level kernel events
-       and, via a set of policy modules, keep the state data up
-       to date.
+       @header SystemConfiguration
+       @discussion The System Configuration framework provides access to the
+               data used to configure a running system.  The APIs provided
+               by this framework communicate with the configd daemon.
+
+               The configd daemon manages a dynamic store reflecting the
+               desired configuration settings as well as the current state
+               of the system.  The daemon provides a notification mechanism
+               for processes that need to be aware of changes made to the
+               data.  Lastly, the daemon loads a number of bundles (or
+               plug-ins) that monitor low-level kernel events and, through
+               a set of policy modules, keep the state data up to date.
  */
 
 /*!
  */
 
 /*!
-       @enum
-       @discussion Returned status codes.
-
+       @enum Error codes
+       @discussion Returned error codes.
        @constant kSCStatusOK                   Success
        @constant kSCStatusFailed               Non-specific Failure
        @constant kSCStatusInvalidArgument      Invalid argument
        @constant kSCStatusOK                   Success
        @constant kSCStatusFailed               Non-specific Failure
        @constant kSCStatusInvalidArgument      Invalid argument
        @constant kSCStatusKeyExists            Data associated with key already defined
        @constant kSCStatusLocked               Lock already held
        @constant kSCStatusNeedLock             Lock required for this operation
        @constant 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 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 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 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
        @constant kSCStatusReachabilityUnknown
                A determination could not be made regarding the reachability
-               of the specified nodename/address.
+               of the specified nodename or address.
 */
 enum {
        /*
 */
 enum {
        /*
-        * Generic status codes
+        * Generic error codes
         */
        kSCStatusOK                             = 0,    /* Success */
        kSCStatusFailed                         = 1001, /* Non-specific failure */
         */
        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 */
        /*
        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 */
        /*
         */
        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 */
         */
        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 */
        /*
        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 */
 };
         */
        kSCStatusReachabilityUnknown            = 4001  /* Network reachability cannot be determined */
 };
@@ -118,6 +113,9 @@ enum {
 #include <SystemConfiguration/SCPreferences.h>
 #include <SystemConfiguration/SCPreferencesPath.h>
 
 #include <SystemConfiguration/SCPreferences.h>
 #include <SystemConfiguration/SCPreferencesPath.h>
 
+/* network configuration */
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+
 /* store and preference scheme definitions */
 #include <SystemConfiguration/SCSchemaDefinitions.h>
 
 /* store and preference scheme definitions */
 #include <SystemConfiguration/SCSchemaDefinitions.h>
 
@@ -130,17 +128,18 @@ __BEGIN_DECLS
 
 /*!
        @function SCError
 
 /*!
        @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
  */
 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.
        @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);
 
  */
 const char *   SCErrorString           (int    status);
 
index 70728920960e088532f178848bc247aa99cbb620..97367ce8e681ac0aca7f9bb9bccba578e1cc3609 100644 (file)
 #include <CoreFoundation/CFRuntime.h>
 
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <CoreFoundation/CFRuntime.h>
 
 #include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <ifaddrs.h>
 #include <pthread.h>
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <ifaddrs.h>
 #include <pthread.h>
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/types.h>
-#define        KERNEL_PRIVATE
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
-#undef KERNEL_PRIVATE
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <net/ethernet.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <net/ethernet.h>
-#define        KERNEL_PRIVATE  1
+#define        KERNEL_PRIVATE
 #include <net/if.h>
 #include <net/if_var.h>
 #undef KERNEL_PRIVATE
 #include <net/if.h>
 #include <net/if_var.h>
 #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)
 {
 static Boolean
 _VLANDevice_set(int s, CFStringRef interface, CFStringRef device, CFNumberRef tag)
 {
-#ifdef SIOCSETVLAN
        struct ifreq    ifr;
        int             tag_val;
        struct vlanreq  vreq;
        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
        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;
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
 
        return TRUE;
-#else  /* SIOCSETVLAN */
-       return FALSE;
-#endif /* SIOCSETVLAN */
 }
 
 
 static Boolean
 _VLANDevice_unset(int s, CFStringRef interface)
 {
 }
 
 
 static Boolean
 _VLANDevice_unset(int s, CFStringRef interface)
 {
-#ifdef SIOCSETVLAN
        struct ifreq    ifr;
        struct vlanreq  vreq;
 
        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
        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;
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
 
        return TRUE;
-#else  /* SIOCSETVLAN */
-       return FALSE;
-#endif /* SIOCSETVLAN */
 }
 
 
 }
 
 
@@ -217,7 +165,7 @@ IsVLANSupported(CFStringRef device)
 
        /* get the interface index */
 
 
        /* 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
        }
        if (if_name == NULL) {
                return FALSE;   // if conversion error
        }
@@ -335,8 +283,6 @@ __VLANInterfaceDeallocate(CFTypeRef cf)
 {
        VLANInterfacePrivateRef vlanPrivate     = (VLANInterfacePrivateRef)cf;
 
 {
        VLANInterfacePrivateRef vlanPrivate     = (VLANInterfacePrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceDeallocate:"));
-
        /* release resources */
 
        CFRelease(vlanPrivate->ifname);
        /* release resources */
 
        CFRelease(vlanPrivate->ifname);
@@ -430,8 +376,6 @@ __VLANInterfaceCreatePrivate(CFAllocatorRef allocator,
        VLANInterfacePrivateRef         vlanPrivate;
        uint32_t                        size;
 
        VLANInterfacePrivateRef         vlanPrivate;
        uint32_t                        size;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceCreatePrivate:"));
-
        /* initialize runtime */
        pthread_once(&vlanInterface_init, __VLANInterfaceInitialize);
 
        /* initialize runtime */
        pthread_once(&vlanInterface_init, __VLANInterfaceInitialize);
 
@@ -655,8 +599,6 @@ __VLANPreferencesDeallocate(CFTypeRef cf)
 {
        VLANPreferencesPrivateRef       prefsPrivate    = (VLANPreferencesPrivateRef)cf;
 
 {
        VLANPreferencesPrivateRef       prefsPrivate    = (VLANPreferencesPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesDeallocate:"));
-
        /* release resources */
 
        pthread_mutex_destroy(&prefsPrivate->lock);
        /* 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;
 
                                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);
                                        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;
 
        VLANPreferencesPrivateRef       prefsPrivate;
        uint32_t                        size;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesCreate:"));
-
        /* initialize runtime */
        pthread_once(&vlanPreferences_init, __VLANPreferencesInitialize);
 
        /* initialize runtime */
        pthread_once(&vlanPreferences_init, __VLANPreferencesInitialize);
 
@@ -865,7 +805,7 @@ VLANPreferencesCreate(CFAllocatorRef allocator)
                                                                           __kVLANPreferencesTypeID,
                                                                           size,
                                                                           NULL);
                                                                           __kVLANPreferencesTypeID,
                                                                           size,
                                                                           NULL);
-       if (!prefsPrivate) {
+       if (prefsPrivate == NULL) {
                return NULL;
        }
 
                return NULL;
        }
 
@@ -1099,6 +1039,9 @@ VLANPreferencesAddInterface(VLANPreferencesRef    prefs,
 
                newVlan = __VLANInterfaceCreatePrivate(allocator, vlan_if, device, tag, options);
 
 
                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) {
                /* save in the prefs */
 
                if (nConfig == 0) {
@@ -1112,9 +1055,6 @@ VLANPreferencesAddInterface(VLANPreferencesRef    prefs,
                (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
                CFRelease(newVlans);
 
                (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
                CFRelease(newVlans);
 
-               /* yes, we've change the configuration */
-               setConfigurationChanged(prefs);
-
            next_if :
                CFRelease(vlan_if);
        }
            next_if :
                CFRelease(vlan_if);
        }
@@ -1253,19 +1193,18 @@ VLANPreferencesUpdateInterface(VLANPreferencesRef       prefs,
                CFDictionaryAddValue(newDict, __kVLANInterface_options, newOptions);
        }
 
                CFDictionaryAddValue(newDict, __kVLANInterface_options, newOptions);
        }
 
+       /* yes, we're going to be changing the configuration */
+       setConfigurationChanged(prefs);
+
        /* update the prefs */
 
        newVlans = CFArrayCreateMutableCopy(allocator, 0, vlans);
        /* 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);
 
        CFRelease(newDict);
 
        (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
        CFRelease(newVlans);
 
-       /* yes, we've change the configuration */
-       setConfigurationChanged(prefs);
-
        ok = TRUE;
 
     done :
        ok = TRUE;
 
     done :
@@ -1313,6 +1252,9 @@ VLANPreferencesRemoveInterface(VLANPreferencesRef prefs,
                goto done;
        }
 
                goto done;
        }
 
+       /* yes, we're going to be changing the configuration */
+       setConfigurationChanged(prefs);
+
        /* remove the vlan */
 
        allocator = CFGetAllocator(prefs);
        /* remove the vlan */
 
        allocator = CFGetAllocator(prefs);
@@ -1322,9 +1264,6 @@ VLANPreferencesRemoveInterface(VLANPreferencesRef prefs,
        (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
        CFRelease(newVlans);
 
        (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
        CFRelease(newVlans);
 
-       /* yes, we've change the configuration */
-       setConfigurationChanged(prefs);
-
        ok = TRUE;
 
     done :
        ok = TRUE;
 
     done :
@@ -1433,8 +1372,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs)
                                s = inet_dgram_socket();
                        }
 
                                s = inet_dgram_socket();
                        }
 
-                       ok = _VLAN_destroy(s, a_vlan_if);
+                       ok = __destroyInterface(s, a_vlan_if);
                        if (!ok) {
                        if (!ok) {
+                               _SCErrorSet(kSCStatusFailed);
                                goto done;
                        }
                }
                                goto done;
                        }
                }
@@ -1491,8 +1431,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs)
                                                }
                                        } else {
                                                // if the new [parent] device does not support VLANs
                                                }
                                        } 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) {
                                                if (!ok) {
+                                                       _SCErrorSet(kSCStatusFailed);
                                                        goto done;
                                                }
                                        }
                                                        goto done;
                                                }
                                        }
@@ -1509,8 +1450,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs)
                                s = inet_dgram_socket();
                        }
 
                                s = inet_dgram_socket();
                        }
 
-                       ok = _VLAN_create(s, c_vlan_if);
+                       ok = __createInterface(s, c_vlan_if);
                        if (!ok) {
                        if (!ok) {
+                               _SCErrorSet(kSCStatusFailed);
                                goto done;
                        }
 
                                goto done;
                        }
 
@@ -1563,8 +1505,6 @@ VLANPreferencesApplyChanges(VLANPreferencesRef prefs)
                goto done;
        }
 
                goto done;
        }
 
-       ok = TRUE;
-
     done :
 
        pthread_mutex_unlock(&prefsPrivate->lock);
     done :
 
        pthread_mutex_unlock(&prefsPrivate->lock);
index bfa115e35c705196f60e89e1cce9c9baebafc3f6..9fa8c9be9173fac6c069b0a7656bd54cdd267413 100644 (file)
@@ -24,6 +24,9 @@
 #ifndef _VLANCONFIGURATION_H
 #define _VLANCONFIGURATION_H
 
 #ifndef _VLANCONFIGURATION_H
 #define _VLANCONFIGURATION_H
 
+/*!
+       @header VLANConfiguration
+*/
 
 #include <sys/cdefs.h>
 #include <CoreFoundation/CoreFoundation.h>
 
 #include <sys/cdefs.h>
 #include <CoreFoundation/CoreFoundation.h>
index 811e616520ae65b943579b03d28f6208a522337b..bf0b4054ef54440188e6c2fcd0829cc31cf97958 100644 (file)
 #include <CoreFoundation/CoreFoundation.h>
 
 
 #include <CoreFoundation/CoreFoundation.h>
 
 
+#include <SystemConfiguration/VLANConfiguration.h>
+
+
+/*!
+       @header VLANConfigurationPrivate
+ */
+
+
 #define VLAN_PREFERENCES_ID    CFSTR("VirtualNetworkInterfaces.plist")
 
 
 #define VLAN_PREFERENCES_ID    CFSTR("VirtualNetworkInterfaces.plist")
 
 
index b1ed4c81ebb8b9bcf81daebd5bd3faec86b47da8..fc9f340e5011ac61487f0c78ace87b3c6669db48 100644 (file)
@@ -66,6 +66,7 @@ type task_move_send_t = MACH_MSG_TYPE_MOVE_SEND
 
 routine configopen     (       server          : mach_port_t;
                                name            : xmlData;
 
 routine configopen     (       server          : mach_port_t;
                                name            : xmlData;
+                               options         : xmlData;
                         out    session         : mach_port_move_send_t;
                         out    status          : int);
 
                         out    session         : mach_port_move_send_t;
                         out    status          : int);
 
index 33046cd9abaac780b5e7d13d69539bab00ed0fb7..f31634d3ed26140c1f6ba6bb88c277567fa4f645 100644 (file)
@@ -61,7 +61,8 @@ __loadIOKit(void) {
 __private_extern__ CFMutableDictionaryRef
 _IOBSDNameMatching(mach_port_t masterPort, unsigned int options, const char *bsdName)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        }
        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)
 {
 }
 
 
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        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)
 {
 __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));
        if (!dyfunc) {
                void *image = __loadSecurity();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCreateFromAttributes", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
index 6560839ad444ce1301582a2865a9486903e81733..e21bcb8ce73939c347a6243f3a8b47f6e2586a17 100644 (file)
@@ -54,6 +54,20 @@ _IOMasterPort                                (
                                        );
 #define IOMasterPort _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
 kern_return_t
 _IOObjectRelease                       (
                                        io_object_t             object
@@ -78,6 +92,22 @@ _IORegistryEntryCreateCFProperties   (
                                        );
 #define IORegistryEntryCreateCFProperties _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,
 kern_return_t
 _IORegistryEntryGetParentEntry         (
                                        io_registry_entry_t     entry,
@@ -94,6 +124,16 @@ _IORegistryEntryGetPath                     (
                                        );
 #define IORegistryEntryGetPath _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,
 kern_return_t
 _IOServiceGetMatchingServices          (
                                        mach_port_t             masterPort,
index 49d96c46b3a29b9b55a87a0ae14812651e234bb6..9785c7a47805a95872cc375a8513143ee7eefe81 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 /*
  * Modification History
  *
 /*
  * 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
  *
  * 16 July 2003                        Allan Nathanson (ajn@apple.com)
  * - changes to facilitate cross-compilation to earlier releases
  *
@@ -54,7 +59,7 @@
 
 char copyright_string[] =
 "/*\n"
 
 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"
 " *\n"
 " * @APPLE_LICENSE_HEADER_START@\n"
 " * \n"
@@ -79,13 +84,16 @@ char copyright_string[] =
 
 typedef enum {
        COMMENT,
 
 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;
 
        END
 } controlType;
 
+#define SC_SCHEMA_KV           "SC_SCHEMA_KV"
 #define SC_SCHEMA_DECLARATION  "SC_SCHEMA_DECLARATION"
 
 #define KEY_PREFIX             "kSC"
 #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 CFNUMBER_BOOL          "CFNumber (0 or 1)"
 #define CFSTRING               "CFString"
 
-#define ACSPENABLED            "ACSPEnabled"           // Apple Client Server Protocol
+#define ACSP                   "ACSP"                  // Apple Client Server Protocol
 #define ACTIVE                 "Active"
 #define ADDRESSES              "Addresses"
 #define AFTER                  "After"
 #define ACTIVE                 "Active"
 #define ADDRESSES              "Addresses"
 #define AFTER                  "After"
@@ -127,14 +135,15 @@ typedef enum {
 #define ANYREGEX               "AnyRegex"
 #define APPLETALK              "AppleTalk"
 #define AUTH                   "Auth"
 #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 AUTOMATIC              "Automatic"
 #define BEFORE                 "Before"
 #define BINDINGMETHODS         "BindingMethods"
 #define BOOTP                  "BOOTP"
 #define BROADCAST              "Broadcast"
-#define BROADCASTADDRESSES     "BroadcastAddresses"
-#define BROADCASTSERVERTAG     "BroadcastServerTag"
 #define CALLWAITINGAUDIBLEALERT        "CallWaitingAudibleAlert"
 #define CALLWAITINGAUDIBLEALERT        "CallWaitingAudibleAlert"
+#define CAUSE                  "Cause"
 #define CCP                    "CCP"
 #define CHAP                   "CHAP"
 #define COMM                   "Comm"
 #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 CONSOLEUSER            "ConsoleUser"
 #define CURRENTSET             "CurrentSet"
 #define DATACOMPRESSION                "DataCompression"
-#define DEFAULTSERVERTAG       "DefaultServerTag"
+#define DEFAULT                        "Default"
 #define DEFAULTZONE            "DefaultZone"
 #define DEFAULTZONE            "DefaultZone"
-#define DESTADDRESSES          "DestAddresses"
+#define DEST                   "Dest"
 #define DETACHING              "Detaching"
 #define DEVICE                 "Device"
 #define DEVICENAME             "DeviceName"
 #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 DIALMODE               "DialMode"
 #define DIALONDEMAND           "DialOnDemand"
 #define DISCONNECTONANSWER     "DisconnectOnAnswer"
+#define DISCONNECTONFASTUSERSWITCH     "DisconnectOnFastUserSwitch"
 #define DISCONNECTONIDLE       "DisconnectOnIdle"
 #define DISCONNECTONIDLETIMER  "DisconnectOnIdleTimer"
 #define DISCONNECTONLOGOUT     "DisconnectOnLogout"
 #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 DISPLAYTERMINALWINDOW  "DisplayTerminalWindow"
 #define DNS                    "DNS"
 #define DOMAIN                         "Domain"
-#define DOMAINNAME             "DomainName"
-#define DOMAINSEPARATOR                "DomainSeparator"
+#define DOMAINS                        "Domains"
 #define EAP                    "EAP"
 #define EAP                    "EAP"
-#define ECHOENABLED            "EchoEnabled"
+#define ECHO                   "Echo"
 #define ECHOFAILURE            "EchoFailure"
 #define ECHOINTERVAL           "EchoInterval"
 #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 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 FILE                   "File"
 #define FIREWIRE               "FireWire"
+#define FIRST                  "First"
 #define FLAGS                  "Flags"
 #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 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 HARDWARE               "Hardware"
 #define HOLD                   "Hold"
 #define HOSTNAMES              "HostNames"
-#define HTTPENABLE             "HTTPEnable"
-#define HTTPPORT               "HTTPPort"
-#define HTTPPROXY              "HTTPProxy"
-#define HTTPSENABLE            "HTTPSEnable"
-#define HTTPSPORT              "HTTPSPort"
-#define HTTPSPROXY             "HTTPSProxy"
+#define HTTP                   "HTTP"
+#define HTTPS                  "HTTPS"
 #define IDLEREMINDER           "IdleReminder"
 #define IDLEREMINDERTIMER      "IdleReminderTimer"
 #define IGNOREDIALTONE         "IgnoreDialTone"
 #define IDLEREMINDER           "IdleReminder"
 #define IDLEREMINDERTIMER      "IdleReminderTimer"
 #define IGNOREDIALTONE         "IgnoreDialTone"
@@ -218,8 +221,7 @@ typedef enum {
 #define JOINMODE               "JoinMode"
 #define KEYCHAIN               "Keychain"
 #define L2TP                   "L2TP"
 #define JOINMODE               "JoinMode"
 #define KEYCHAIN               "Keychain"
 #define L2TP                   "L2TP"
-#define LASTCAUSE              "LastCause"
-#define LASTUPDATED            "LastUpdated"
+#define LAST                   "Last"
 #define LCP                    "LCP"
 #define LINK                   "Link"
 #define LINKLOCAL              "LinkLocal"
 #define LCP                    "LCP"
 #define LINK                   "Link"
 #define LINKLOCAL              "LinkLocal"
@@ -227,9 +229,12 @@ typedef enum {
 #define LOGFILE                        "Logfile"
 #define MACADDRESS             "MACAddress"
 #define MANUAL                 "Manual"
 #define LOGFILE                        "Logfile"
 #define MACADDRESS             "MACAddress"
 #define MANUAL                 "Manual"
+#define MATCH                  "Match"
 #define MEDIA                  "Media"
 #define OPTIONS                        "Options"
 #define MODEM                  "Modem"
 #define MEDIA                  "Media"
 #define OPTIONS                        "Options"
 #define MODEM                  "Modem"
+#define MPPE40                 "MPPE40"
+#define MPPE128                        "MPPE128"
 #define MRU                    "MRU"
 #define MSCHAP1                        "MSCHAP1"
 #define MSCHAP2                        "MSCHAP2"
 #define MRU                    "MRU"
 #define MSCHAP1                        "MSCHAP1"
 #define MSCHAP2                        "MSCHAP2"
@@ -240,23 +245,25 @@ typedef enum {
 #define NETWORKID              "NetworkID"
 #define NETWORKRANGE           "NetworkRange"
 #define NETWORKSERVICES                "NetworkServices"
 #define NETWORKID              "NetworkID"
 #define NETWORKRANGE           "NetworkRange"
 #define NETWORKSERVICES                "NetworkServices"
-#define NIS                    "NIS"
 #define NODE                   "Node"
 #define NODEID                 "NodeID"
 #define NOTE                   "Note"
 #define NODE                   "Node"
 #define NODEID                 "NodeID"
 #define NOTE                   "Note"
+#define ORDER                  "Order"
+#define ORDERS                 "Orders"
 #define OVERRIDEPRIMARY                "OverridePrimary"
 #define PAP                    "PAP"
 #define OVERRIDEPRIMARY                "OverridePrimary"
 #define PAP                    "PAP"
+#define PASSIVE                        "Passive"
 #define PASSWORD               "Password"
 #define PASSWORD               "Password"
+#define PEERDNS                        "PeerDNS"
 #define PLUGIN                 "Plugin"
 #define PLUGINS                        "Plugins"
 #define PLUGIN                 "Plugin"
 #define PLUGINS                        "Plugins"
-#define POWERENABLED           "PowerEnabled"
+#define POWER                  "Power"
+#define PORT                   "Port"
 #define PPP                    "PPP"
 #define PPPOE                  "PPPoE"
 #define PPP                    "PPP"
 #define PPPOE                  "PPPoE"
-#define PPPOVERRIDEPRIMARY     "PPPOverridePrimary"
 #define PPPSERIAL              "PPPSerial"
 #define PPTP                   "PPTP"
 #define PREFERRED              "Preferred"
 #define PPPSERIAL              "PPPSerial"
 #define PPTP                   "PPTP"
 #define PREFERRED              "Preferred"
-#define PREFERREDNETWORK       "PreferredNetwork"
 #define PREFIXLENGTH           "PrefixLength"
 #define PREFS                  "Prefs"
 #define PRIMARYINTERFACE       "PrimaryInterface"
 #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 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 PULSEDIAL              "PulseDial"
 #define RECEIVEACCM            "ReceiveACCM"
 #define RECENT                 "Recent"
 #define REDIALCOUNT            "RedialCount"
-#define REDIALENABLED          "RedialEnabled"
+#define REDIAL                 "Redial"
 #define REDIALINTERVAL         "RedialInterval"
 #define RELAY                  "Relay"
 #define REMINDER               "Reminder"
 #define REDIALINTERVAL         "RedialInterval"
 #define RELAY                  "Relay"
 #define REMINDER               "Reminder"
@@ -280,26 +286,20 @@ typedef enum {
 #define ROOTSEPARATOR          "RootSeparator"
 #define ROUTER                 "Router"
 #define ROUTERADVERTISEMENT    "RouterAdvertisement"
 #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 SAVEPASSWORDS          "SavePasswords"
-#define SEARCHDOMAINS          "SearchDomains"
+#define SEARCH                 "Search"
 #define SEEDNETWORKRANGE       "SeedNetworkRange"
 #define SEEDROUTER             "SeedRouter"
 #define SEEDZONES              "SeedZones"
 #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 SERVICE                        "Service"
 #define SERVICEIDS             "ServiceIDs"
-#define SERVICEORDER           "ServiceOrder"
 #define SESSIONTIMER           "SessionTimer"
 #define SETS                   "Sets"
 #define SETUP                  "Setup"
 #define        SHAREDSECRET            "SharedSecret"
 #define SESSIONTIMER           "SessionTimer"
 #define SETS                   "Sets"
 #define SETUP                  "Setup"
 #define        SHAREDSECRET            "SharedSecret"
-#define SOCKSENABLE            "SOCKSEnable"
-#define SOCKSPORT              "SOCKSPort"
-#define SOCKSPROXY             "SOCKSProxy"
+#define SOCKS                  "SOCKS"
 #define SORTLIST               "SortList"
 #define SPEAKER                        "Speaker"
 #define SPEED                  "Speed"
 #define SORTLIST               "SortList"
 #define SPEAKER                        "Speaker"
 #define SPEED                  "Speed"
@@ -309,13 +309,19 @@ typedef enum {
 #define STRONGEST              "Strongest"
 #define SUBNETMASKS            "SubnetMasks"
 #define SUBTYPE                        "SubType"
 #define STRONGEST              "Strongest"
 #define SUBNETMASKS            "SubnetMasks"
 #define SUBTYPE                        "SubType"
+#define SUPPLEMENTAL           "Supplemental"
 #define SUPPORTSMODEMONHOLD    "SupportsModemOnHold"
 #define SYSTEM                 "System"
 #define SUPPORTSMODEMONHOLD    "SupportsModemOnHold"
 #define SYSTEM                 "System"
+#define TAG                    "Tag"
+#define TAGS                   "Tags"
 #define TERMINALSCRIPT         "TerminalScript"
 #define TERMINALSCRIPT         "TerminalScript"
+#define TIMEOUT                        "Timeout"
 #define TRANSMITACCM           "TransmitACCM"
 #define TRANSPORT              "Transport"
 #define TYPE                   "Type"
 #define UID                    "UID"
 #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"
 #define USERDEFINEDNAME                "UserDefinedName"
 #define USE                    "Use"
 #define USERS                  "Users"
@@ -329,391 +335,434 @@ struct {
     const char *               value;
     const char *               type;
 } names[] = {
     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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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, "", 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 },
 
     { 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 },
 };
 
     { END, NULL, NULL, NULL, NULL },
 };
 
@@ -733,6 +782,8 @@ setmax(int *max, char **maxstr, char *str)
 
 enum {
     gen_header_e,
 
 enum {
     gen_header_e,
+    gen_comments_e,
+    gen_headerdoc_e,
     gen_hfile_e,
     gen_cfile_e,
 };
     gen_hfile_e,
     gen_cfile_e,
 };
@@ -752,195 +803,205 @@ dump_names(int type)
                goto done;
                break;
            }
                goto done;
                break;
            }
+
            case COMMENT: {
                switch (type) {
            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;
            }
                }
                break;
            }
-           case DEFINE: {
-               char kbuf[256];
-               char vbuf[256];
 
 
+           case GROUP: {
                switch (type) {
                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;
            }
                }
                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) {
                char kbuf[256];
                char vbuf[256];
 
                switch (type) {
-               case gen_hfile_e:
-                   if (nObsolete++ == 0) {
-                       printf("#ifndef  SCSTR\n");
-                       printf("#include <CoreFoundation/CFString.h>\n");
-                       printf("#define  SCSTR(s) CFSTR(s)\n");
-                       printf("#endif\n");
-                   }
-
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   if (names[i].value)
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].value);
-                   else
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].key);
-
-                   printf("#define %-40s %-40s /* %s */\n",
-                          kbuf,
-                          vbuf,
-                          names[i].type ? names[i].type : "");
-                   break;
-               default:
-                   break;
-               }
-               break;
-           }
-           case FUTURE: {
-               char kbuf[256];
-
-               switch (type) {
-               case gen_header_e:
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   printf("// #define %-37s %-40s /* %s */\n",
-                          kbuf,
-                          "SCSTR(\"???\") */",
-                          "RESERVED FOR FUTURE USE");
-                   break;
-               case gen_hfile_e:
-                   snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
-                            names[i].prefix, names[i].key);
-                   setmax(&maxkbuf, &maxkstr, kbuf);
-
-                   printf("// SC_SCHEMA_DECLARATION%-39s /* %s */\n",
-                          kbuf, "RESERVED FOR FUTURE USE");
-                   break;
-               default:
-                   break;
+                   case gen_header_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+
+                       if (names[i].value)
+                           snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
+                                    names[i].value);
+                       else
+                           snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
+                                    names[i].key);
+
+                       printf("#define %-50s %s\n",
+                              kbuf, vbuf);
+                       break;
+                   case gen_comments_e:
+                       switch (names[i].control) {
+                           case SC_10_1_10_3:
+                               // don't report deprecated keys
+                               break;
+                           default:
+                               snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                        names[i].prefix, names[i].key);
+
+                               snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+                                        names[i].value ? names[i].value : names[i].key);
+
+                               if (names[i].type)
+                                   printf(" *   %-50s %-30s %s\n",
+                                          kbuf, vbuf, names[i].type);
+                               else
+                                   printf(" *   %-50s %s\n",
+                                          kbuf, vbuf);
+                               break;
+                       }
+                       break;
+                   case gen_headerdoc_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+                       setmax(&maxkbuf, &maxkstr, kbuf);
+
+                       snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+                                names[i].value ? names[i].value : names[i].key);
+                       setmax(&maxvbuf, &maxvstr, vbuf);
+
+                       printf("\n");
+
+                       printf("/*!\n");
+                       printf("  @const %s\n", kbuf);
+                       switch (names[i].control) {
+                           case SC_10_1:
+                               printf("  @availability Introduced in Mac OS X 10.1.\n");
+                               break;
+                           case SC_10_2:
+                               printf("  @availability Introduced in Mac OS X 10.2.\n");
+                               break;
+                           case SC_10_1_10_3:
+                               printf("  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.\n");
+                               break;
+                           case SC_10_3:
+                               printf("  @availability Introduced in Mac OS X 10.3.\n");
+                               break;
+                           case SC_10_4:
+                               printf("  @availability Introduced in Mac OS X 10.4.\n");
+                               break;
+                       }
+                       printf(" */\n");
+                       printf("extern const CFStringRef %s;\n", kbuf);
+
+                       break;
+                   case gen_hfile_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+                       setmax(&maxkbuf, &maxkstr, kbuf);
+
+                       snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+                                names[i].value ? names[i].value : names[i].key);
+                       setmax(&maxvbuf, &maxvstr, vbuf);
+
+                       printf("\n");
+
+                       switch (names[i].control) {
+                           case SC_10_2:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2\n");
+                               break;
+                           case SC_10_1_10_3:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \\\n");
+                               printf("    MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3\n");
+                               break;
+                           case SC_10_3:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3\n");
+                               break;
+                           case SC_10_4:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4\n");
+                               break;
+                       }
+
+                       printf("#define %-48s              \\\n",
+                              kbuf);
+                       printf("\tSC_SCHEMA_KV(%-48s \\\n",
+                              kbuf);
+                       printf("\t            ,%-48s \\\n",
+                              vbuf);
+                       printf("\t            ,%-48s )\n",
+                              names[i].type ? names[i].type : "");
+
+                       switch (names[i].control) {
+                           case SC_10_2:
+                           case SC_10_3:
+                           case SC_10_1_10_3:
+                           case SC_10_4:
+                               printf("#endif\n");
+                               break;
+                       }
+
+                       switch (names[i].control) {
+                           case SC_10_2:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);\n", kbuf);
+                               break;
+                           case SC_10_3:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);\n", kbuf);
+                               break;
+                           case SC_10_1_10_3:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);\n", kbuf);
+                               break;
+                           case SC_10_4:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);\n", kbuf);
+                               break;
+                           default:
+                               printf("\tSC_SCHEMA_DECLARATION(%s,);\n", kbuf);
+                               break;
+                       }
+
+                       break;
+                   case gen_cfile_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+
+                       if (names[i].value)
+                           printf("const CFStringRef %-48s = CFSTR(\"%s\");\n",
+                                  kbuf, names[i].value);
+                       else
+                           printf("const CFStringRef %-48s = CFSTR(\"%s\");\n",
+                                  kbuf, names[i].key);
+                       break;
+                   default:
+                       break;
                }
                break;
            }
                }
                break;
            }
-           default: {
-               break;
-           }
        }
     }
  done:
     switch (type) {
        }
     }
  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;
 }
     }
     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 _SCSCHEMADEFINITIONS_10_1_H\n#define _SCSCHEMADEFINITIONS_10_1_H\n\n");
 
-       printf("#ifndef  SCSTR\n");
-       printf("#include <CoreFoundation/CFString.h>\n");
-       printf("#define  SCSTR(s) CFSTR(s)\n");
-       printf("#endif\n");
+       printf("#warning USE OF THIS HEADER HAS BEEN DEPRECATED\n");
+
+       printf("#ifndef _SCSCHEMADEFINITIONS_H\n");
+       printf("#warning Please #include <SystemConfiguration/SystemConfiguration.h> instead\n");
+       printf("#warning of including this file directly.\n");
+       printf("#include <SystemConfiguration/SCSchemaDefinitions.h>\n");
+       printf("#endif\n\n");
+
+//     printf("#ifndef  SCSTR\n");
+//     printf("#include <CoreFoundation/CFString.h>\n");
+//     printf("#define  SCSTR(s) CFSTR(s)\n");
+//     printf("#endif\n\n");
+//
+//     dump_names(gen_header_e);
+//     printf("\n");
 
 
-       printf("\n");
-       dump_names(gen_header_e);
        printf("#endif /* _SCSCHEMADEFINITIONS_10_1_H */\n");
     }
     else if (strcmp(type, "header") == 0) {
        printf("#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("/*\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(" *\n");
-       printf(" *       #define " SC_SCHEMA_DECLARATION "(x)\t\textern NSString * x\n");
+       printf(" *       #define " SC_SCHEMA_DECLARATION "(k,q)\textern NSString * k\n");
        printf(" *       #import <SystemConfiguration/SystemConfiguration.h>\n");
        printf(" */\n\n");
 
        printf(" *       #import <SystemConfiguration/SystemConfiguration.h>\n");
        printf(" */\n\n");
 
+       printf("/*\n");
+       printf(" * Note: For CFM applications using these schema keys you may want to\n");
+       printf(" *       consider the following :\n");
+       printf(" *\n");
+       printf(" *       #define SC_SCHEMA_KV(k,v,t)\tlookup_SC_key( CFSTR( #k ) )\n");
+       printf(" *       #define SC_SCHEMA_DECLARATION(k,q)\n");
+       printf(" *       #include <SystemConfiguration/SystemConfiguration.h>\n");
+       printf(" *\n");
+       printf(" *       CFStringRef lookup_SC_key(CFStringRef key)\n");
+       printf(" *       {\n");
+       printf(" *         // this function should [dynamically, on-demand] load the\n");
+       printf(" *         // SystemConfiguration.framework, look up the provided key,\n");
+       printf(" *         // and return the associated value.\n");
+       printf(" *       }\n");
+       printf(" */\n\n");
+
+       printf("/*\n");
+       printf(" * Note: Earlier versions of this header file defined a \"SCSTR\" macro\n");
+       printf(" *       which helped to facilitate Obj-C development. Use of this macro\n");
+       printf(" *       has been deprecated (in Mac OS X 10.4) in favor of the newer\n");
+       printf(" *       \"SC_SCHEMA_KV\" and \"SC_SCHEMA_DECLARATION\" macros\n");
+       printf(" */\n\n\n");
+
        printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n");
 
        printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n");
 
-       printf("#ifndef SC_SCHEMA_DECLARATION\n");
-       printf("#ifndef SCSTR\n");
-       printf("#include <CoreFoundation/CFString.h>\n");
-       printf("#define " SC_SCHEMA_DECLARATION "(x)\textern const CFStringRef x\n");
-       printf("#else\n");
-       printf("#import <Foundation/NSString.h>\n");
-       printf("#define " SC_SCHEMA_DECLARATION "(x)\textern NSString * x\n");
-       printf("#endif\n");
-       printf("#endif\n");
+       printf("/* -------------------- Macro declarations -------------------- */\n\n");
 
 
-       printf("\n");
-       dump_names(gen_hfile_e);
+       printf("#include <AvailabilityMacros.h>\n\n");
+
+       printf("/*\n");
+       printf(" * let's \"do the right thing\" for those wishing to build for\n");
+       printf(" * Mac OS X 10.1 and 10.2\n");
+       printf(" */\n");
 
 
-       printf("#include <AvailabilityMacros.h>\n");
        printf("#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED\n");
        printf("  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
        printf("#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED\n");
        printf("  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
-       printf("    #include <SystemConfiguration/SCSchemaDefinitions_10_1.h>\n");
+       printf("    #ifndef SCSTR\n");
+       printf("      #include <CoreFoundation/CFString.h>\n");
+       printf("      #define SCSTR(s) CFSTR(s)\n");
+       printf("    #endif\n");
+       printf("    #ifndef SC_SCHEMA_KV\n");
+       printf("      #define SC_SCHEMA_KV(k,v,t)\tSCSTR( v )\n");
+       printf("    #endif\n");
+       printf("    #ifndef SC_SCHEMA_DECLARATION\n");
+       printf("      #define SC_SCHEMA_DECLARATION(k,q)\n");
+       printf("    #endif\n");
        printf("  #endif\n");
        printf("#endif\n\n");
 
        printf("  #endif\n");
        printf("#endif\n\n");
 
+       printf("/*\n");
+       printf(" * Define a schema key/value/type tuple\n");
+       printf(" */\n");
+       printf("#ifndef SC_SCHEMA_KV\n");
+       printf("  #define " SC_SCHEMA_KV "(k,v,t)\tk\n");
+       printf("#endif\n\n");
+
+       printf("/*\n");
+       printf(" * Provide an \"extern\" for the key/value\n");
+       printf(" */\n");
+       printf("#ifndef SC_SCHEMA_DECLARATION\n");
+       printf("  #ifndef SCSTR\n");
+       printf("    #include <CoreFoundation/CFString.h>\n");
+       printf("    #define " SC_SCHEMA_DECLARATION "(k,q)\textern const CFStringRef k q\n");
+       printf("  #else\n");
+       printf("    #import <Foundation/NSString.h>\n");
+       printf("    #define " SC_SCHEMA_DECLARATION "(k,q)\textern NSString * k q\n");
+       printf("  #endif\n");
+       printf("#endif\n");
+
+       // The SCSTR() macro should be availble for 10.1 ... 10.4
+       printf("#if MAC_OS_X_VERSION_10_4 >= MAC_OS_X_VERSION_MIN_REQUIRED\n");
+       printf("  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
+       printf("    #ifndef SCSTR\n");
+       printf("      #include <CoreFoundation/CFString.h>\n");
+       printf("      #define SCSTR(s) CFSTR(s)\n");
+       printf("    #endif\n");
+       printf("  #endif\n");
+       printf("#endif\n\n\n");
+
+       printf("/* -------------------- HeaderDoc comments -------------------- */\n\n\n");
+       printf("#if\t0\n");
+       printf("/*!\n");
+       printf(" *\t@header SCSchemaDefinitions\n");
+       printf(" */\n");
+       dump_names(gen_headerdoc_e);
+       printf("\n");
+       printf("#endif\t/* 0 */\n\n\n");
+
+       printf("/* -------------------- Schema declarations -------------------- */\n\n");
+       dump_names(gen_hfile_e);
+       printf("\n");
+
        printf("#endif /* _SCSCHEMADEFINITIONS_H */\n");
     }
     else if (strcmp(type, "cfile") == 0) {
        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 (file)
index f3c1b04..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
diff --git a/SystemConfiguration.fproj/m.template b/SystemConfiguration.fproj/m.template
deleted file mode 100644 (file)
index 1216fe5..0000000
+++ /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 (file)
index 07b9ffc..0000000
+++ /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 <ajn@apple.com>
- * - use ServiceID *or* LinkID
- *
- * Oct 25, 2002                 Christophe Allie <callie@apple.com>
- * - use ServiceID instead of LinkID
- *
- * Feb 28, 2002                 Christophe Allie <callie@apple.com>
- * - socket API fixes
- *
- * Feb 10, 2001                 Allan Nathanson <ajn@apple.com>
- * - cleanup API
- *
- * Feb 2000                     Christophe Allie <callie@apple.com>
- * - initial revision
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <SystemConfiguration/SystemConfiguration.h>
-#include <SystemConfiguration/SCPrivate.h>
-
-#include <ppp/ppp_msg.h>
-#include "ppp.h"
-
-
-static int
-readn(int ref, void *data, int len)
-{
-       int     left    = len;
-       int     n;
-       void    *p      = data;
-
-       while (left > 0) {
-               if ((n = read(ref, p, left)) < 0) {
-                       if (errno != EINTR) {
-                               return -1;
-                       }
-                       n = 0;
-               } else if (n == 0) {
-                       break; /* EOF */
-               }
-
-               left -= n;
-               p += n;
-       }
-       return (len - left);
-}
-
-
-static int
-writen(int ref, void *data, int len)
-{
-       int     left    = len;
-       int     n;
-       void    *p      = data;
-
-       while (left > 0) {
-               if ((n = write(ref, p, left)) <= 0) {
-                       if (errno != EINTR) {
-                               return -1;
-                       }
-                       n = 0;
-               }
-               left -= n;
-               p += n;
-       }
-       return len;
-}
-
-
-__private_extern__
-int
-PPPInit(int *ref)
-{
-       int                     sock;
-       int                     status;
-       struct sockaddr_un      sun;
-
-       sock = socket(AF_LOCAL, SOCK_STREAM, 0);
-
-       bzero(&sun, sizeof(sun));
-       sun.sun_family = AF_LOCAL;
-       strncpy(sun.sun_path, PPP_PATH, sizeof(sun.sun_path));
-
-       status = connect(sock,  (struct sockaddr *)&sun, sizeof(sun));
-       if (status < 0) {
-               return errno;
-       }
-
-       *ref = sock;
-       return 0;
-}
-
-
-__private_extern__
-int
-PPPDispose(int ref)
-{
-       if (close(ref) < 0) {
-               return errno;
-       }
-       return 0;
-}
-
-
-static int
-PPPExec(int            ref,
-       CFStringRef     serviceID,
-       uint32_t        link,
-       uint32_t        cmd,
-       u_int16_t       flags,
-       void            *request,
-       uint32_t        requestLen,
-       void            **reply,
-       uint32_t        *replyLen)
-{
-       struct ppp_msg_hdr      msg;
-       char                    *buf            = NULL;
-       ssize_t                 n;
-       CFDataRef               sID             = NULL;
-
-       bzero(&msg, sizeof(msg));
-
-       // first send request, if necessary
-       if (cmd) {
-               msg.m_type = cmd;
-               msg.m_flags = flags;
-               if (serviceID) {
-                       sID = CFStringCreateExternalRepresentation(NULL,
-                                                                  serviceID,
-                                                                  kCFStringEncodingUTF8,
-                                                                  0);
-                       // serviceID is present, use it
-                       msg.m_flags |= USE_SERVICEID;
-                       msg.m_link = CFDataGetLength(sID);
-               } else {
-                       // no service ID, use the requested link
-                       msg.m_link = link;
-               }
-               msg.m_len  = ((request != NULL) && (requestLen > 0)) ? requestLen : 0;
-
-               //  send the command
-               if (writen(ref, &msg, sizeof(msg)) < 0) {
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
-                       if (sID) CFRelease(sID);
-                       return errno;
-               }
-
-               if (sID) {
-                       if (writen(ref, (void *)CFDataGetBytePtr(sID), msg.m_link) < 0) {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
-                               CFRelease(sID);
-                               return errno;
-                       }
-                       CFRelease(sID);
-               }
-
-               if ((request != NULL) && (requestLen > 0)) {
-                       if (writen(ref, request, requestLen) < 0) {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec write() failed: %s"), strerror(errno));
-                               return errno;
-                       }
-               }
-       }
-
-       // then read replies or incoming message
-       n = readn(ref, &msg, sizeof(msg));
-       if (n == -1) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
-               return errno;
-       } else if (n != sizeof(msg)) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n);
-               return -1;
-       }
-
-       if ((msg.m_flags & USE_SERVICEID) && msg.m_link) {
-               buf = CFAllocatorAllocate(NULL, msg.m_link, 0);
-               if (buf) {
-                       // read reply
-                       n = readn(ref, buf, msg.m_link);
-                       if (n == -1) {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
-                               CFAllocatorDeallocate(NULL, buf);
-                               return errno;
-                       } else if (n != (ssize_t)msg.m_link) {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
-                               CFAllocatorDeallocate(NULL, buf);
-                               return -1;
-                       }
-                       // buf contains the service id we passed in the request
-                       CFAllocatorDeallocate(NULL, buf);
-                       buf = NULL;
-               }
-       }
-
-       if (msg.m_len) {
-               buf = CFAllocatorAllocate(NULL, msg.m_len, 0);
-               if (buf) {
-                       // read reply
-                       n = readn(ref, buf, msg.m_len);
-                       if (n == -1) {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: error=%s"), strerror(errno));
-                               CFAllocatorDeallocate(NULL, buf);
-                               return errno;
-                       } else if (n != (ssize_t)msg.m_len) {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("PPPExec readn() failed: insufficent data, read=%d"), n);
-                               CFAllocatorDeallocate(NULL, buf);
-                               return -1;
-                       }
-               }
-       }
-
-       if (reply && replyLen) {
-               *reply    = buf;
-               *replyLen = msg.m_len;
-       } else if (buf) {
-               // if additional returned data is unwanted
-               CFAllocatorDeallocate(NULL, buf);
-       }
-
-       return msg.m_result;
-}
-
-
-__private_extern__
-int
-PPPGetLinkByInterface(int ref, char *if_name, uint32_t *link)
-{
-       void            *replyBuf       = NULL;
-       uint32_t        replyBufLen     = 0;
-       int             status;
-
-       status = PPPExec(ref,
-                        NULL,
-                        -1,
-                        PPP_GETLINKBYIFNAME,
-                        0,
-                        (void *)if_name,
-                        strlen(if_name),
-                        &replyBuf,
-                        &replyBufLen);
-       if (status != 0) {
-               return status;
-       }
-
-       if (replyBuf && (replyBufLen == sizeof(uint32_t))) {
-               *link = *(uint32_t *)replyBuf;
-       } else {
-               status = -2;    /* if not found */
-       }
-       if (replyBuf)   CFAllocatorDeallocate(NULL, replyBuf);
-
-       return status;
-}
-
-
-__private_extern__
-int
-PPPConnect(int ref, CFStringRef serviceID, uint32_t link, void *data, uint32_t dataLen, int linger)
-{
-       int     status;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_CONNECT,
-                        CONNECT_ARBITRATED_FLAG + (linger ? 0 : CONNECT_AUTOCLOSE_FLAG),
-                        data,
-                        dataLen,
-                        NULL,
-                        NULL);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPDisconnect(int ref, CFStringRef serviceID, uint32_t link, int force)
-{
-       int     status;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_DISCONNECT,
-                        force ? 0 : DISCONNECT_ARBITRATED_FLAG,
-                        NULL,
-                        0,
-                        NULL,
-                        NULL);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPSuspend(int ref, CFStringRef serviceID, uint32_t link)
-{
-       int     status;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_SUSPEND,
-                        0,
-                        NULL,
-                        0,
-                        NULL,
-                        NULL);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPResume(int ref, CFStringRef serviceID, uint32_t link)
-{
-       int     status;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_RESUME,
-                        0,
-                        NULL,
-                        0,
-                        NULL,
-                        NULL);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPGetOption(int ref, CFStringRef serviceID, uint32_t link, uint32_t option, void **data, uint32_t *dataLen)
-{
-       struct ppp_opt_hdr      opt;
-       void                    *replyBuf       = NULL;
-       uint32_t                replyBufLen     = 0;
-       int                     status;
-
-       *dataLen = 0;
-       *data = NULL;
-
-       bzero(&opt, sizeof(opt));
-       opt.o_type = option;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_GETOPTION,
-                        0,
-                        (void *)&opt,
-                        sizeof(opt),
-                        &replyBuf,
-                        &replyBufLen);
-       if (status != 0) {
-               return status;
-       }
-
-       if (replyBuf && (replyBufLen > sizeof(struct ppp_opt_hdr))) {
-               *dataLen = replyBufLen - sizeof(struct ppp_opt_hdr);
-               *data    = CFAllocatorAllocate(NULL, *dataLen, 0);
-               bcopy(((struct ppp_opt *)replyBuf)->o_data, *data, *dataLen);
-       }
-       if (replyBuf)   CFAllocatorDeallocate(NULL, replyBuf);
-
-       return status;
-}
-
-
-__private_extern__
-int
-PPPSetOption(int ref, CFStringRef serviceID, uint32_t link, uint32_t option, void *data, uint32_t dataLen)
-{
-       void            *buf;
-       uint32_t        bufLen;
-       int             status;
-
-       bufLen = sizeof(struct ppp_opt_hdr) + dataLen;
-       buf    = CFAllocatorAllocate(NULL, bufLen, 0);
-
-       bzero((struct ppp_opt_hdr *)buf, sizeof(struct ppp_opt_hdr));
-       ((struct ppp_opt_hdr *)buf)->o_type = option;
-       bcopy(data, ((struct ppp_opt *)buf)->o_data, dataLen);
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_SETOPTION,
-                        0,
-                        buf,
-                        bufLen,
-                        NULL,
-                        NULL);
-
-       CFAllocatorDeallocate(NULL, buf);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPGetConnectData(int ref, CFStringRef serviceID, uint32_t link, void **data, uint32_t *dataLen)
-{
-       int     status;
-
-       *dataLen = 0;
-       *data = NULL;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_GETCONNECTDATA,
-                        0,
-                        NULL,
-                        0,
-                        data,
-                        dataLen);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPStatus(int ref, CFStringRef serviceID, uint32_t link, struct ppp_status **stat)
-{
-       void            *replyBuf       = NULL;
-       uint32_t        replyBufLen     = 0;
-       int             status;
-
-       *stat = NULL;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_STATUS,
-                        0,
-                        NULL,
-                        0,
-                        &replyBuf,
-                        &replyBufLen);
-       if (status != 0) {
-               return status;
-       }
-
-       if (replyBuf && (replyBufLen == sizeof(struct ppp_status))) {
-               *stat = (struct ppp_status *)replyBuf;
-       } else {
-               if (replyBuf)   CFAllocatorDeallocate(NULL, replyBuf);
-               status = -1;
-       }
-
-       return status;
-}
-
-
-__private_extern__
-int
-PPPExtendedStatus(int ref, CFStringRef serviceID, uint32_t link, void **data, uint32_t *dataLen)
-{
-       int     status;
-
-       *dataLen = 0;
-       *data = NULL;
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        PPP_EXTENDEDSTATUS,
-                        0,
-                        NULL,
-                        0,
-                        data,
-                        dataLen);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPEnableEvents(int ref, CFStringRef serviceID, uint32_t link, u_char enable)
-{
-       int             status;
-       uint32_t        lval    = 2;    // status notifications
-
-       status = PPPExec(ref,
-                        serviceID,
-                        link,
-                        enable ? PPP_ENABLE_EVENT : PPP_DISABLE_EVENT,
-                        0,
-                        &lval,
-                        sizeof(lval),
-                        NULL,
-                        NULL);
-       return status;
-}
-
-
-__private_extern__
-int
-PPPReadEvent(int ref, uint32_t *event)
-{
-
-       *event = PPPExec(ref, NULL, 0, 0, 0, NULL, 0, NULL, NULL);
-       return 0;
-}
-
-
-__private_extern__
-CFDataRef
-PPPSerialize(CFPropertyListRef obj, void **data, uint32_t *dataLen)
-{
-       CFDataRef               xml;
-
-       xml = CFPropertyListCreateXMLData(NULL, obj);
-       if (xml) {
-               *data = (void*)CFDataGetBytePtr(xml);
-               *dataLen = CFDataGetLength(xml);
-       }
-       return xml;
-}
-
-
-__private_extern__
-CFPropertyListRef
-PPPUnserialize(void *data, uint32_t dataLen)
-{
-       CFDataRef               xml;
-       CFStringRef             xmlError;
-       CFPropertyListRef       ref     = NULL;
-
-       xml = CFDataCreateWithBytesNoCopy(NULL, data, dataLen, kCFAllocatorNull);
-       if (xml) {
-               ref = CFPropertyListCreateFromXMLData(NULL,
-                                                     xml,
-                                                     kCFPropertyListImmutable,
-                                                     &xmlError);
-               if (!ref) {
-                       if (xmlError) {
-                               SCLog(TRUE,
-                                     LOG_ERR,
-                                     CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
-                                     xmlError);
-                               CFRelease(xmlError);
-                       }
-               }
-
-               CFRelease(xml);
-       }
-
-       return ref;
-}
diff --git a/SystemConfiguration.fproj/ppp.h b/SystemConfiguration.fproj/ppp.h
deleted file mode 100644 (file)
index c7135d5..0000000
+++ /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 <ajn@apple.com>
- * - use ServiceID *or* LinkID
- *
- * Feb 10, 2001                        Allan Nathanson <ajn@apple.com>
- * - cleanup API
- *
- * Feb 2000                    Christophe Allie <callie@apple.com>
- * - initial revision (as ppplib.h)
- */
-
-#ifndef _PPP_H
-#define _PPP_H
-
-#include <sys/cdefs.h>
-#include <ppp/ppp_msg.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-__BEGIN_DECLS
-
-int            PPPInit                 (int                    *ref);
-
-int            PPPDispose              (int                    ref);
-
-int            PPPGetLinkByInterface   (int                    ref,
-                                        char                   *if_name,
-                                        uint32_t               *link);
-
-int            PPPConnect              (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        void                   *data,
-                                        uint32_t               dataLen,
-                                        int                    linger);
-
-int            PPPDisconnect           (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        int                    force);
-
-int            PPPSuspend              (int                    ref,
-                                        CFStringRef            serviceID,
-                                        uint32_t               link);
-
-int            PPPResume               (int                    ref,
-                                        CFStringRef            serviceID,
-                                        uint32_t               link);
-
-int            PPPGetOption            (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        uint32_t               option,
-                                        void                   **data,
-                                        uint32_t               *dataLen);
-
-int            PPPSetOption            (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        uint32_t               option,
-                                        void                   *data,
-                                        uint32_t               dataLen);
-
-int            PPPGetConnectData       (int                    ref,
-                                        CFStringRef            serviceID,
-                                        uint32_t               link,
-                                        void                   **data,
-                                        uint32_t               *dataLen);
-
-int            PPPStatus               (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        struct ppp_status      **stat);
-
-int            PPPExtendedStatus       (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        void                   **data,
-                                        uint32_t               *dataLen);
-
-int            PPPEnableEvents         (int                    ref,
-                                        CFStringRef            serviceid,
-                                        uint32_t               link,
-                                        u_char                 enable);
-
-int            PPPReadEvent            (int                    ref,
-                                        uint32_t               *event);
-
-CFDataRef              PPPSerialize    (CFPropertyListRef      obj,
-                                        void                   **data,
-                                        uint32_t               *dataLen);
-
-CFPropertyListRef      PPPUnserialize  (void                   *data,
-                                        uint32_t               dataLen);
-
-__END_DECLS
-
-#endif /* _PPP_H */
diff --git a/SystemConfiguration.fproj/pppcontroller.defs b/SystemConfiguration.fproj/pppcontroller.defs
new file mode 100644 (file)
index 0000000..6c6985c
--- /dev/null
@@ -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 <ppp/pppcontroller.defs>
diff --git a/configd.tproj/Makefile b/configd.tproj/Makefile
deleted file mode 100644 (file)
index c6bcd09..0000000
+++ /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 (file)
index 0bd75f1..0000000
+++ /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 (file)
index ea74460..0000000
+++ /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: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
-AFTER_INSTALL = install_extra
-
-# Additional flags (for MiG generated files)
-ALL_MIGFLAGS = -F$(SYMROOT)
-OTHER_OFILES = configServer.o
-
diff --git a/configd.tproj/PB.project b/configd.tproj/PB.project
deleted file mode 100644 (file)
index 3ceaa3c..0000000
+++ /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"; 
-}
index a6a31dad1a7fdcae58b49787ab416f88df4ce678..061b514f8d4ec2806851894ff47d2a474e92d276 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  */
 
 
  */
 
 
+#include <unistd.h>
+
 #include "configd.h"
 #include "configd.h"
+#include "configd_server.h"
+#include "session.h"
 
 
 __private_extern__ CFMutableDictionaryRef      sessionData             = NULL;
 
 
 __private_extern__ CFMutableDictionaryRef      sessionData             = NULL;
@@ -133,7 +137,7 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        i = CFArrayGetFirstIndexOfValue(newWatchers,
                                        CFRangeMake(0, CFArrayGetCount(newWatchers)),
                                        sessionNum);
        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;
                /* 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);
 
        CFDictionarySetValue(storeData, watchedKey, newDict);
        CFRelease(newDict);
 
+#ifdef DEBUG
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _addWatcher: %@, %@"), sessionNum, watchedKey);
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _addWatcher: %@, %@"), sessionNum, watchedKey);
+#endif /* DEBUG */
 
        return;
 }
 
        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?) */
        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);
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey);
+#endif /* DEBUG */
                return;
        }
        newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
                return;
        }
        newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
@@ -209,8 +217,10 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        i = CFArrayGetFirstIndexOfValue(newWatchers,
                                        CFRangeMake(0, CFArrayGetCount(newWatchers)),
                                        sessionNum);
        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);
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _removeWatcher: %@, %@, session not watching"), sessionNum, watchedKey);
+#endif /* DEBUG */
                CFRelease(newDict);
                CFRelease(newWatchers);
                CFRelease(newWatcherRefs);
                CFRelease(newDict);
                CFRelease(newWatchers);
                CFRelease(newWatcherRefs);
@@ -251,7 +261,159 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        }
        CFRelease(newDict);
 
        }
        CFRelease(newDict);
 
+#ifdef DEBUG
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _removeWatcher: %@, %@"), sessionNum, watchedKey);
        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;
 }
 
        return;
 }
index 98cb81ef4938153ef8c509de83d035f8c9dbfabe..db03de87aeea28ddf3d88af9579cc8f17e60a543 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -27,7 +27,7 @@
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
- * June 2, 2000                Allan Nathanson <ajn@apple.com>
+ * June 2, 2000                        Allan Nathanson <ajn@apple.com>
  * - initial revision
  */
 
  * - initial revision
  */
 
@@ -119,12 +119,8 @@ __SCDynamicStoreCopyKeyList                (SCDynamicStoreRef      store,
 int
 __SCDynamicStoreAddValue               (SCDynamicStoreRef      store,
                                         CFStringRef            key,
 int
 __SCDynamicStoreAddValue               (SCDynamicStoreRef      store,
                                         CFStringRef            key,
-                                        CFDataRef              value);
-
-int
-__SCDynamicStoreAddTemporaryValue      (SCDynamicStoreRef      store,
-                                        CFStringRef            key,
-                                        CFDataRef              value);
+                                        CFDataRef              value,
+                                        Boolean                internal);
 
 int
 __SCDynamicStoreCopyValue              (SCDynamicStoreRef      store,
 
 int
 __SCDynamicStoreCopyValue              (SCDynamicStoreRef      store,
@@ -217,6 +213,9 @@ void
 _removeWatcher                         (CFNumberRef            sessionNum,
                                         CFStringRef            watchedKey);
 
 _removeWatcher                         (CFNumberRef            sessionNum,
                                         CFStringRef            watchedKey);
 
+void
+pushNotifications                      ();
+
 __END_DECLS
 
 #endif /* !_S_SCD_H */
 __END_DECLS
 
 #endif /* !_S_SCD_H */
index 5e0d5015d3076d92e22f9ac84500e51e7b43c49b..792e57a0e0e9281cf4eecfba9e8deef2925729d5 100644 (file)
 
 __private_extern__
 int
 
 __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;
 
 {
        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) {
        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 :
                        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;
        }
 
                        goto done;
        }
 
@@ -96,7 +93,9 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
        /*
         * 4. Release our lock.
         */
        /*
         * 4. Release our lock.
         */
+
     done:
     done:
+
        __SCDynamicStoreUnlock(store, TRUE);
 
        return sc_status;
        __SCDynamicStoreUnlock(store, TRUE);
 
        return sc_status;
@@ -114,44 +113,102 @@ _configadd(mach_port_t                   server,
           int                          *sc_status
 )
 {
           int                          *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-       CFDataRef               data;           /* data (un-serialized) */
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       CFDataRef               data            = NULL;         /* data (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
+
+       /* un-serialize the key */
+       if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
+               *sc_status = kSCStatusFailed;
+               goto done;
+       }
+
+       if (!isA_CFString(key)) {
+               *sc_status = kSCStatusInvalidArgument;
+               goto done;
+       }
+
+       /* un-serialize the data */
+       if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
+               *sc_status = kSCStatusFailed;
+               goto done;
+       }
 
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Add key to configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
+       if (!mySession) {
+               *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
+               goto done;
        }
 
        }
 
-       *sc_status = kSCStatusOK;
+       *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+       if (*sc_status == kSCStatusOK) {
+               *newInstance = 0;
+       }
+
+    done :
+
+       if (key)        CFRelease(key);
+       if (data)       CFRelease(data);
+
+       return KERN_SUCCESS;
+}
+
+
+__private_extern__
+kern_return_t
+_configadd_s(mach_port_t               server,
+            xmlData_t                  keyRef,         /* raw XML bytes */
+            mach_msg_type_number_t     keyLen,
+            xmlData_t                  dataRef,        /* raw XML bytes */
+            mach_msg_type_number_t     dataLen,
+            int                        *newInstance,
+            int                        *sc_status
+)
+{
+       CFDataRef                       data            = NULL;         /* data (un-serialized) */
+       CFStringRef                     key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef                mySession       = getSession(server);
+       SCDynamicStorePrivateRef        storePrivate;
+       Boolean                         useSessionKeys;
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
 
        /* 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;
                *sc_status = kSCStatusInvalidArgument;
+               goto done;
        }
 
        /* un-serialize the data */
        if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
                *sc_status = kSCStatusFailed;
        }
 
        /* 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 (!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;
 }
 
        return KERN_SUCCESS;
 }
diff --git a/configd.tproj/_configadd_s.c b/configd.tproj/_configadd_s.c
deleted file mode 100644 (file)
index 7a690d7..0000000
+++ /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 <ajn@apple.com>
- * - public API conversion
- *
- * October 17, 2000            Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include "configd.h"
-#include "session.h"
-
-__private_extern__
-int
-__SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value)
-{
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
-       int                             sc_status = kSCStatusOK;
-       CFStringRef                     sessionKey;
-       CFDictionaryRef                 dict;
-       CFMutableDictionaryRef          newDict;
-       CFArrayRef                      keys;
-       CFMutableArrayRef               newKeys;
-
-       if (_configd_verbose) {
-               CFPropertyListRef       val;
-
-               (void) _SCUnserialize(&val, value, NULL, NULL);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddTemporaryValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), val);
-               CFRelease(val);
-       }
-
-       if (!store || (storePrivate->server == MACH_PORT_NULL)) {
-               return kSCStatusNoStoreSession; /* you must have an open session to play */
-       }
-
-       /*
-        * 1. Add the key
-        */
-       sc_status = __SCDynamicStoreAddValue(store, key, value);
-       if (sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreAddValue(): %s"), SCErrorString(sc_status));
-               return sc_status;
-       }
-
-       /*
-        * 2. Create the session key
-        */
-       sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
-
-       /*
-        * 3. Add this key to my list of per-session keys
-        */
-       dict = CFDictionaryGetValue(sessionData, sessionKey);
-       keys = CFDictionaryGetValue(dict, kSCDSessionKeys);
-       if ((keys == NULL) ||
-           (CFArrayGetFirstIndexOfValue(keys,
-                                        CFRangeMake(0, CFArrayGetCount(keys)),
-                                        key) == -1)) {
-               /*
-                * if no session keys defined "or" keys defined but not
-                * this one...
-                */
-               if (keys) {
-                       /* this is a new session key */
-                       newKeys = CFArrayCreateMutableCopy(NULL, 0, keys);
-               } else {
-                       /* this is an additional session key */
-                       newKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-               }
-               CFArrayAppendValue(newKeys, key);
-
-               /* update session dictionary */
-               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
-               CFDictionarySetValue(newDict, kSCDSessionKeys, newKeys);
-               CFRelease(newKeys);
-               CFDictionarySetValue(sessionData, sessionKey, newDict);
-               CFRelease(newDict);
-       }
-
-       /*
-        * 4. Mark the key as a "session" key and track the creator.
-        */
-       dict    = CFDictionaryGetValue(storeData, key);
-       newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
-       CFDictionarySetValue(newDict, kSCDSession, sessionKey);
-       CFDictionarySetValue(storeData, key, newDict);
-       CFRelease(newDict);
-
-       CFRelease(sessionKey);
-       return sc_status;
-}
-
-
-__private_extern__
-kern_return_t
-_configadd_s(mach_port_t               server,
-            xmlData_t                  keyRef,         /* raw XML bytes */
-            mach_msg_type_number_t     keyLen,
-            xmlData_t                  dataRef,        /* raw XML bytes */
-            mach_msg_type_number_t     dataLen,
-            int                        *newInstance,
-            int                        *sc_status
-)
-{
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-       CFDataRef               data;           /* data (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Add (session) key to configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
-       *sc_status = kSCStatusOK;
-
-       /* un-serialize the key */
-       if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
-               *sc_status = kSCStatusFailed;
-       } else if (!isA_CFString(key)) {
-               *sc_status = kSCStatusInvalidArgument;
-       }
-
-       /* un-serialize the data */
-       if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
-               *sc_status = kSCStatusFailed;
-       }
-
-       if (!mySession) {
-               *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-       }
-
-       if (*sc_status != kSCStatusOK) {
-               if (key)        CFRelease(key);
-               if (data)       CFRelease(data);
-               return KERN_SUCCESS;
-       }
-
-       *sc_status = __SCDynamicStoreAddTemporaryValue(mySession->store, key, data);
-       if (*sc_status == kSCStatusOK) {
-               *newInstance = 1;
-       }
-       CFRelease(key);
-       CFRelease(data);
-
-       return KERN_SUCCESS;
-}
index 6b3c72d34d725263ceef4e3c1f551d2ee46872e6..fbd48ab178500b7d09f14c40f853613bd70141a7 100644 (file)
@@ -102,14 +102,12 @@ __private_extern__
 int
 __SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal)
 {
 int
 __SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal)
 {
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)*store;
-       CFIndex                         keyCnt;
-       CFStringRef                     sessionKey;
        CFDictionaryRef                 dict;
        CFArrayRef                      keys;
        CFDictionaryRef                 dict;
        CFArrayRef                      keys;
+       CFIndex                         keyCnt;
        serverSessionRef                mySession;
        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 */
 
        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) {
         */
        mySession = getSession(storePrivate->server);
        if (mySession->serverRunLoopSource) {
-               CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
-                                     mySession->serverRunLoopSource,
-                                     kCFRunLoopDefaultMode);
+               CFRunLoopSourceInvalidate(mySession->serverRunLoopSource);
                CFRelease(mySession->serverRunLoopSource);
        }
        CFMachPortInvalidate(mySession->serverPort);
                CFRelease(mySession->serverRunLoopSource);
        }
        CFMachPortInvalidate(mySession->serverPort);
@@ -204,11 +200,6 @@ _configclose(mach_port_t server, int *sc_status)
 {
        serverSessionRef        mySession = getSession(server);
 
 {
        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;
        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) {
         */
        *sc_status = __SCDynamicStoreClose(&mySession->store, FALSE);
        if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreClose(): %s"), SCErrorString(*sc_status));
                return KERN_SUCCESS;
        }
 
                return KERN_SUCCESS;
        }
 
index fa889fe3f32635faf73b9b5909e50f7f3004089b..caeae329395d1ba1ed5596adf356a457503c4e49 100644 (file)
@@ -41,11 +41,6 @@ __SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *v
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        CFDictionaryRef                 dict;
 
        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 */
        }
        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));
 
        /* 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;
 }
 
        return kSCStatusOK;
 }
 
@@ -89,41 +76,33 @@ _configget(mach_port_t                      server,
           int                          *sc_status
 )
 {
           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;
 
        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;
        *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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value, FALSE);
-       CFRelease(key);
        if (*sc_status != kSCStatusOK) {
        if (*sc_status != kSCStatusOK) {
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /* serialize the data */
        }
 
        /* serialize the data */
@@ -131,7 +110,7 @@ _configget(mach_port_t                      server,
        CFRelease(value);
        if (!ok) {
                *sc_status = kSCStatusFailed;
        CFRelease(value);
        if (!ok) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /*
        }
 
        /*
@@ -139,6 +118,9 @@ _configget(mach_port_t                      server,
         */
        *newInstance = 1;
 
         */
        *newInstance = 1;
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
 
        return KERN_SUCCESS;
 }
 
@@ -202,12 +184,6 @@ __SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRe
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        addSpecific                     myContext;
 
        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 */
        }
        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;
 
        /* 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;
 }
 
        return kSCStatusOK;
 }
 
@@ -271,23 +239,19 @@ _configget_m(mach_port_t          server,
        Boolean                 ok;
        CFArrayRef              patterns        = NULL; /* patterns (un-serialized) */
 
        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;
        *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;
 
        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;
                }
 
                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;
                /* un-serialize the patterns */
                if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) {
                        *sc_status = kSCStatusFailed;
+                       goto done;
                }
 
                if (!isA_CFArray(patterns)) {
                        *sc_status = kSCStatusInvalidArgument;
                }
 
                if (!isA_CFArray(patterns)) {
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                }
        }
 
        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);
        *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;
 
        /* 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;
 }
        return KERN_SUCCESS;
 }
index a43e889b6b146e93aeafda75cf073ea0b08d8973..6591a9972f5c5aa8ce4da94d87404f676d1a8282 100644 (file)
@@ -48,31 +48,22 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
        CFStringRef                     storeStr;
        CFDictionaryRef                 storeValue;
 
        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 */
        }
 
        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)) {
        if (isRegex) {
                CFStringRef     reErrStr;
 
                if (!patternCompile(key, &preg, &reErrStr)) {
-                       CFArrayAppendValue(keyArray, reErrStr);
+                       *subKeys = CFArrayCreate(NULL, (const void **)&reErrStr, 1, &kCFTypeArrayCallBacks);
                        CFRelease(reErrStr);
                        CFRelease(reErrStr);
-                       *subKeys = CFArrayCreateCopy(NULL, keyArray);
-                       CFRelease(keyArray);
                        return kSCStatusFailed;
                }
        }
 
                        return kSCStatusFailed;
                }
        }
 
+       storeCnt = CFDictionaryGetCount(storeData);
+       keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
        if (storeCnt > 0) {
                int             i;
                const void *    storeKeys_q[N_QUICK];
        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) {
                                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;
                                }
                                        if (storeKey != storeKey_q) CFAllocatorDeallocate(NULL, storeKey);
                                        continue;
                                }
@@ -126,7 +117,7 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
                                                                       &preg,
                                                                       reErrBuf,
                                                                       sizeof(reErrBuf));
                                                                       &preg,
                                                                       reErrBuf,
                                                                       sizeof(reErrBuf));
-                                               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+                                               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList regexec() failed: %s"), reErrBuf);
                                                break;
                                        }
                                }
                                                break;
                                        }
                                }
@@ -153,8 +144,8 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
                regfree(&preg);
        }
 
                regfree(&preg);
        }
 
-       *subKeys = keyArray;
-
+       *subKeys = CFArrayCreateCopy(NULL, keyArray);
+       CFRelease(keyArray);
        return kSCStatusOK;
 }
 
        return kSCStatusOK;
 }
 
@@ -170,15 +161,10 @@ _configlist(mach_port_t                   server,
            int                         *sc_status
 )
 {
            int                         *sc_status
 )
 {
-       CFStringRef             key;            /* key  (un-serialized) */
-       serverSessionRef        mySession = getSession(server);
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
        Boolean                 ok;
        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;
 
        *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;
        /* 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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys);
-       CFRelease(key);
        if (*sc_status != kSCStatusOK) {
        if (*sc_status != kSCStatusOK) {
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /* serialize the list of keys */
        }
 
        /* serialize the list of keys */
@@ -212,8 +195,11 @@ _configlist(mach_port_t                    server,
        CFRelease(subKeys);
        if (!ok) {
                *sc_status = kSCStatusFailed;
        CFRelease(subKeys);
        if (!ok) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        }
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
        return KERN_SUCCESS;
 }
index 02ecc715d21e2005ed50db31b8382be7432b68d5..c383da6ba5f987de63121471fbce93476c402278 100644 (file)
@@ -40,10 +40,8 @@ __private_extern__
 int
 __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive)
 {
 int
 __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive)
 {
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        serverSessionRef                mySession;
        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 */
 
        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);
 
 {
        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;
        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) {
 
        *sc_status = __SCDynamicStoreLock(mySession->store, FALSE);
        if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  SCDynamicStoreLock(): %s"), SCErrorString(*sc_status));
                return KERN_SUCCESS;
        }
 
                return KERN_SUCCESS;
        }
 
index 892d5426adf7cebe6c657f2fd250cbf94794a0c8..e4e0dea332ffb3f5d566ae05264a608dd17335c9 100644 (file)
@@ -41,11 +41,6 @@ __SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key, Boolean in
        Boolean                         newValue        = FALSE;
        CFDataRef                       value;
 
        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 */
        }
        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
 )
 {
              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;
 
        /* 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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreNotifyValue(mySession->store, key, FALSE);
-       CFRelease(key);
 
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
        return KERN_SUCCESS;
 }
index 82630c9f77247217070c01e15bf02a63d84fc9cb..facaf7e27372a4ab6e9660872f168070e370c48a 100644 (file)
@@ -39,11 +39,6 @@ __private_extern__
 int
 __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
 {
 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
         */
        /*
         * 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,
 _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)
 {
            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;
 
        /* un-serialize the name */
        if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(name)) {
        }
 
        if (!isA_CFString(name)) {
-               CFRelease(name);
                *sc_status = kSCStatusInvalidArgument;
                *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) {
        }
 
        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 */
                *sc_status = kSCStatusFailed;   /* you can't re-open an "open" session */
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /* Create the server port for this session */
        }
 
        /* Create the server port for this session */
@@ -150,11 +170,19 @@ _configopen(mach_port_t                   server,
        }
 
        *sc_status = __SCDynamicStoreOpen(&newSession->store, name);
        }
 
        *sc_status = __SCDynamicStoreOpen(&newSession->store, name);
+       storePrivate = (SCDynamicStorePrivateRef)newSession->store;
 
        /*
         * Make the server port accessible to the framework routines.
         */
 
        /*
         * 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(),
 
        /* 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) {
                                                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;
                cleanupSession(*newServer);
                *newServer = MACH_PORT_NULL;
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
        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.
 
        /*
         * 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);
                                                    &kCFTypeDictionaryValueCallBacks);
        }
        CFDictionarySetValue(newInfo, kSCDName, name);
-       CFRelease(name);
        CFDictionarySetValue(sessionData, sessionKey, newInfo);
        CFRelease(newInfo);
        CFRelease(sessionKey);
 
        CFDictionarySetValue(sessionData, sessionKey, newInfo);
        CFRelease(newInfo);
        CFRelease(sessionKey);
 
+    done :
+
+       if (name)       CFRelease(name);
+       if (options)    CFRelease(options);
        return KERN_SUCCESS;
 }
        return KERN_SUCCESS;
 }
index 0b0ad14c585c71c369c9211b132f567ffae09be6..d3bcb0034b7065d081c19bdb999a7272325a1b6d 100644 (file)
@@ -44,11 +44,6 @@ __SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key, Boolean in
        CFMutableDictionaryRef          newDict;
        CFStringRef                     sessionKey;
 
        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 */
        }
        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
 )
 {
              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;
 
        /* 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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key, FALSE);
-       CFRelease(key);
+
+    done :
+
+       if (key)        CFRelease(key);
 
        return KERN_SUCCESS;
 }
 
        return KERN_SUCCESS;
 }
index 08747c313418daef826671a90ad06ade3ba4ae5a..2cd2ce5acb1d3b55aa1b61909dfec84c01655419 100644 (file)
@@ -49,24 +49,15 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
        CFStringRef                     sessionKey;
        CFStringRef                     storeSessionKey;
 
        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,
        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);
        }
                        storePrivate->server,
                        key);
        }
@@ -101,24 +92,91 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
        newEntry = !CFDictionaryContainsKey(newDict, kSCDData);
        CFDictionarySetValue(newDict, kSCDData, value);
 
        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);
        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);
 
        /*
        CFRelease(sessionKey);
 
        /*
@@ -152,6 +210,8 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
         */
        CFSetAddValue(changedKeys, key);
 
         */
        CFSetAddValue(changedKeys, key);
 
+    done :
+
        /*
         * 8. Release our lock.
         */
        /*
         * 8. Release our lock.
         */
@@ -172,45 +232,39 @@ _configset(mach_port_t                    server,
           int                          *sc_status
 )
 {
           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;
 
        /* 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;
                *sc_status = kSCStatusInvalidArgument;
+               goto done;
        }
 
        /* un-serialize the data */
        if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
                *sc_status = kSCStatusFailed;
        }
 
        /* 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 (!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;
 
        }
 
        *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;
 }
 
        return KERN_SUCCESS;
 }
 
@@ -271,17 +325,6 @@ __SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet,
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
        int                             sc_status       = kSCStatusOK;
 
        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 */
        }
        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)
 {
             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;
 
        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;
                        *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;
                /* 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;
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
                }
        }
 
@@ -383,17 +427,18 @@ _configset_m(mach_port_t          server,
                /* un-serialize the keys to notify */
                if (!_SCUnserialize((CFPropertyListRef *)&notify, NULL, (void *)notifyRef, notifyLen)) {
                        *sc_status = kSCStatusFailed;
                /* un-serialize the keys to notify */
                if (!_SCUnserialize((CFPropertyListRef *)&notify, NULL, (void *)notifyRef, notifyLen)) {
                        *sc_status = kSCStatusFailed;
-               } else if (!isA_CFArray(notify)) {
+                       goto done;
+               }
+
+               if (!isA_CFArray(notify)) {
                        *sc_status = kSCStatusInvalidArgument;
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
        if (!mySession) {
                /* you must have an open session to play */
                *sc_status = kSCStatusNoStoreSession;
                }
        }
 
        if (!mySession) {
                /* you must have an open session to play */
                *sc_status = kSCStatusNoStoreSession;
-       }
-
-       if (*sc_status != kSCStatusOK) {
                goto done;
        }
 
                goto done;
        }
 
index 8c62cf447a663f5d94edb02a3b842a8057d1db95..d35842085189f1f1599e436ab3aab156bace4a7a 100644 (file)
@@ -42,11 +42,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
        int                             sc_status;
        CFDataRef                       value;
 
        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 */
        }
        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());
                        /* 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;
                        (void) _SCSerialize(now, &value, NULL, NULL);
                        CFRelease(now);
                        break;
@@ -85,13 +79,12 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
 
                        /* store entry exists */
 
 
                        /* 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());
                        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);
                                (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 :
                        break;
                }
                default :
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
                        goto done;
        }
 
                        goto done;
        }
 
@@ -125,34 +117,29 @@ _configtouch(mach_port_t          server,
             int                        *sc_status
 )
 {
             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;
 
        /* 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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreTouchValue(mySession->store, key);
-       CFRelease(key);
 
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
        return KERN_SUCCESS;
 }
index c00fa5d445c162ff7398c384b9bb5e8bed588221..21d08158125c61831d26a02e7227cfa9ba0f1d3e 100644 (file)
@@ -218,7 +218,7 @@ _cleanupRemovedSessionKeys(const void *value, void *context)
        i = CFArrayGetFirstIndexOfValue(sessionKeys,
                                        CFRangeMake(0, CFArrayGetCount(sessionKeys)),
                                        key);
        i = CFArrayGetFirstIndexOfValue(sessionKeys,
                                        CFRangeMake(0, CFArrayGetCount(sessionKeys)),
                                        key);
-       if (i == -1) {
+       if (i == kCFNotFound) {
                /* if this session key has already been removed */
                goto done;
        }
                /* if this session key has already been removed */
                goto done;
        }
@@ -252,10 +252,8 @@ __private_extern__
 int
 __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
 {
 int
 __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
 {
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        serverSessionRef                mySession;
        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 */
 
        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);
 
        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.
        /*
         * 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);
 
        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"));
        /* 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);
 
 {
        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;
        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) {
 
        *sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE);
        if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreUnlock(): %s"), SCErrorString(*sc_status));
                return KERN_SUCCESS;
        }
 
                return KERN_SUCCESS;
        }
 
index 55a6ec2b46234b0305aedb03694bcb9b9e2ff30c..27c6a88db1164ebd4e48c8a2c27540bc5ab795c0 100644 (file)
@@ -60,12 +60,6 @@ __SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean
        CFNumberRef                     sessionNum      = NULL;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
        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 */
        }
        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
 )
 {
           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;
 
        /* 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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex != 0, FALSE);
-       CFRelease(key);
 
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
 
        return KERN_SUCCESS;
 }
 
@@ -231,12 +220,6 @@ __SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CF
        updateKeysContext               myContext;
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
        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 */
        }
        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
 )
 {
           int                          *sc_status
 )
 {
-       serverSessionRef        mySession       = getSession(server);
        CFArrayRef              keys            = NULL; /* key (un-serialized) */
        CFArrayRef              keys            = NULL; /* key (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
        CFArrayRef              patterns        = NULL; /* patterns (un-serialized) */
 
        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)) {
        *sc_status = kSCStatusOK;
 
        if (keysRef && (keysLen > 0)) {
index 66673a38a131b4e60be7ed198c4bc1f2495df4c4..06194ed8eebcbef7936c698db2e46338ffca8cb6 100644 (file)
@@ -43,12 +43,6 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
 {
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)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.
         */
        /*
         * cleanup any mach port based notifications.
         */
@@ -61,7 +55,7 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
         * cleanup any file based notifications.
         */
        if (storePrivate->notifyFile >= 0) {
         * 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;
        }
                (void) close(storePrivate->notifyFile);
                storePrivate->notifyFile = -1;
        }
@@ -103,20 +97,11 @@ _notifycancel(mach_port_t  server,
 {
        serverSessionRef        mySession = getSession(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 (!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;
 }
        return KERN_SUCCESS;
 }
index 80be21354f860747ee7d750f2e5761d328720fbd..9b2c902be2b66dcbf612ea322b51f7d426bf967a 100644 (file)
@@ -43,8 +43,6 @@ __SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store, CFArrayRef *notifierKe
        CFDictionaryRef                 info;
        CFMutableDictionaryRef          newInfo;
 
        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 */
        }
        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;
 
        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;
 
        *listRef = NULL;
        *listLen = 0;
 
index 9463d395a89af5d6f2c511ca7d9d2c4c41e93b3d..adc4676200bc8fae2539d84d934a904eeac54f54 100644 (file)
@@ -44,12 +44,6 @@ __SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boole
        CFNumberRef                     sessionNum;
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
        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 */
        }
        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
 )
 {
              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;
 
        /* 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;
        }
 
        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 */
        }
 
        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);
        }
 
        *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store,
                                                      key,
                                                      isRegex != 0,
                                                      FALSE);
-       CFRelease(key);
 
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
 
        return KERN_SUCCESS;
 }
 
index 4f6b317899bfba2512a5dd7c7cf41a239d393754..6a11e21649784d6f20df0cc1e5e25058e7a775fb 100644 (file)
@@ -52,8 +52,6 @@ __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef        store,
        CFStringRef                     sessionKey;
        CFDictionaryRef                 info;
 
        CFStringRef                     sessionKey;
        CFDictionaryRef                 info;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyFileDescriptor:"));
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
        if (!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) {
        }
 
        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;
        }
 
                return kSCStatusFailed;
        }
 
@@ -100,31 +98,27 @@ _notifyviafd(mach_port_t           server,
             int                        *sc_status
 )
 {
             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)) {
 
        /*
         * 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);
                status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
                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 */
                }
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
                *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);
        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) {
        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 */
        }
                /* non-fatal???, proceed */
        }
+#endif /* DEBUG */
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
 
        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) {
 
        /* 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;
                (void) close(sock);
                storePrivate->notifyStatus = NotifierNotRegistered;
                storePrivate->notifyFile   = -1;
@@ -162,18 +158,19 @@ _notifyviafd(mach_port_t          server,
                return KERN_SUCCESS;
        }
 
                return KERN_SUCCESS;
        }
 
-       SCLog(_configd_verbose, LOG_NOTICE, CFSTR("  fd     = %d"), sock);
        (void) unlink(un.sun_path);
 
        (void) unlink(un.sun_path);
 
+       bufSiz = sizeof(storePrivate->notifyFileIdentifier);
        if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufSiz, sizeof(bufSiz)) < 0) {
        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;
        }
 
                (void) close(sock);
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
 
+       nbioYes = 1;
        if (ioctl(sock, FIONBIO, &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;
                (void) close(sock);
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
index a0d1f7b99aaf78eb1f94fff2e5d409030ea1e3e1..4b7df81d3a0b23143296d902fb72c566a5affb9b 100644 (file)
@@ -44,8 +44,6 @@ __SCDynamicStoreNotifyMachPort(SCDynamicStoreRef      store,
        CFStringRef                     sessionKey;
        CFDictionaryRef                 info;
 
        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 */
        }
        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;
 
        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) {
        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);
        }
 
                (void) mach_port_destroy(mach_task_self(), storePrivate->notifyPort);
        }
 
index 7bd555345c07e2935f820b8299e89ae8702cd4ee..28aea5a3966a627701334e413bd27ee75bb53c78 100644 (file)
@@ -31,6 +31,9 @@
  * - initial revision
  */
 
  * - initial revision
  */
 
+#include <unistd.h>
+#include <sys/types.h>
+
 #include "configd.h"
 #include "configd_server.h"
 #include "session.h"
 #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;
 
        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 */
        }
        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 */
 
        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 */
        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) {
                                                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;
        }
 
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
 
+#ifdef NOTYET_DEBUG
        if (oldNotify != MACH_PORT_NULL) {
        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) {
        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;
        }
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
index 60869d57891da4f05a4f07cd179d4433fd219d64..22b23261e91b0742a73c8e5e15ed70a8a4d6c758 100644 (file)
@@ -78,7 +78,7 @@ _expandStore(CFDictionaryRef storeData)
                        if (data) {
                                CFPropertyListRef       plist;
 
                        if (data) {
                                CFPropertyListRef       plist;
 
-                               if (!_SCUnserialize(&plist, data, NULL, NULL)) {
+                               if (!_SCUnserialize(&plist, data, NULL, 0)) {
                                        goto done;
                                }
 
                                        goto done;
                                }
 
@@ -130,8 +130,6 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        CFDataRef                       xmlData;
 
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        CFDataRef                       xmlData;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSnapshot:"));
-
        /* check credentials */
 
        mySession = getSession(storePrivate->server);
        /* check credentials */
 
        mySession = getSession(storePrivate->server);
@@ -151,7 +149,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        xmlData = CFPropertyListCreateXMLData(NULL, expandedStoreData);
        CFRelease(expandedStoreData);
        if (!xmlData) {
        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;
        }
                close(fd);
                return kSCStatusFailed;
        }
@@ -169,7 +167,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
 
        xmlData = CFPropertyListCreateXMLData(NULL, patternData);
        if (!xmlData) {
 
        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;
        }
                close(fd);
                return kSCStatusFailed;
        }
@@ -187,7 +185,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
 
        xmlData = CFPropertyListCreateXMLData(NULL, sessionData);
        if (!xmlData) {
 
        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;
        }
                close(fd);
                return kSCStatusFailed;
        }
@@ -205,17 +203,11 @@ _snapshot(mach_port_t server, int *sc_status)
 {
        serverSessionRef        mySession = getSession(server);
 
 {
        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 (!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;
 }
        return KERN_SUCCESS;
 }
diff --git a/configd.tproj/config.defs b/configd.tproj/config.defs
deleted file mode 100644 (file)
index 3b28e89..0000000
+++ /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 <SystemConfiguration/config.defs>
diff --git a/configd.tproj/configd.8 b/configd.tproj/configd.8
new file mode 100644 (file)
index 0000000..744dfe7
--- /dev/null
@@ -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.
index af823c4218d761c547fb38ee04bae92dee729aba..cc059168d9fe4857e46af571d8ff7db84992fc9e 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * October 30, 2003            Allan Nathanson <ajn@apple.com>
+ * - add plugin "stop()" function support
+ *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
@@ -46,6 +49,7 @@
 #include "configd_server.h"
 #include "plugin_support.h"
 
 #include "configd_server.h"
 #include "plugin_support.h"
 
+__private_extern__
 Boolean        _configd_verbose                = FALSE;        /* TRUE if verbose logging enabled */
 
 __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 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' },
 //     { "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)
 {
 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"));
        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 :
 {
        switch (signum) {
                case SIGTERM :
-                       if (termRequested) {
+                       if (termRequested != NULL) {
                                mach_msg_empty_send_t   msg;
                                mach_msg_option_t       options;
                                kern_return_t           status;
                                mach_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 */
                                                            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;
        }
                        }
                        break;
        }
@@ -126,7 +135,17 @@ catcher(int signum)
 static void
 term(CFMachPortRef port, void *msg, CFIndex size, void *info)
 {
 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;
 {
        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];
        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;
        mach_port_t             service_port    = MACH_PORT_NULL;
+       kern_return_t           status;
        CFStringRef             str;
        const char              *testBundle     = NULL;
 
        CFStringRef             str;
        const char              *testBundle     = NULL;
 
@@ -375,40 +397,33 @@ main(int argc, char * const argv[])
                       strerror(errno));
        }
 
                       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);
 
                /* initialize primary (store management) thread */
                server_init(service_port, enableRestart);
 
index a55f4001d94ca084399dafb217e36ce4dec8eb64..adfe9a55cbb55875f1bfcf9503ab8813a521c564 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * March 9, 2004               Allan Nathanson <ajn@apple.com>
+ * - add DNS configuration server
+ *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
  * - initial revision
  */
 
  * - initial revision
  */
 
-#include <servers/bootstrap.h>
 #include <sysexits.h>
 #include <sysexits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <servers/bootstrap.h>
 
 #include "configd.h"
 #include "configd_server.h"
 #include "notify_server.h"
 #include "session.h"
 
 #include "configd.h"
 #include "configd_server.h"
 #include "notify_server.h"
 #include "session.h"
-#include "notify.h"
 
 /* MiG generated externals and functions */
 
 /* 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 *);
 
 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;
 
 /* 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];
                    (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) {
                } 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;
                                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);
         */
        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;
        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;
 
        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);
                              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);
        }
 
                bufReply = CFAllocatorAllocate(NULL, _config_subsystem.maxsize, 0);
        }
 
@@ -206,7 +234,6 @@ __private_extern__
 boolean_t
 server_active(mach_port_t *restart_service_port)
 {
 boolean_t
 server_active(mach_port_t *restart_service_port)
 {
-       mach_port_t             bootstrap_port;
        char                    *service_name;
        kern_return_t           status;
 
        char                    *service_name;
        kern_return_t           status;
 
@@ -215,14 +242,6 @@ server_active(mach_port_t *restart_service_port)
                service_name = SCD_SERVER;
        }
 
                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) {
        /* 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)
 {
 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;
        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;
        }
 
 
        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;
 
        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) {
                                                                         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 {
                                                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) {
 
                                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) {
                                        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;
                                        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("'%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... */
                                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) {
        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);
        }
 
                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) {
        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);
        }
                        mach_error_string(status));
                exit (EX_UNAVAILABLE);
        }
@@ -361,7 +373,7 @@ server_init(mach_port_t     restart_service_port, Boolean enableRestart)
 
 
 __private_extern__
 
 
 __private_extern__
-void
+int
 server_shutdown()
 {
        char            *service_name;
 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)) {
         *       logging thread lock is held.
         */
        if ((priv_bootstrap_port == MACH_PORT_NULL) || (configd_port == NULL)) {
-               return;
+               return EX_OK;
        }
 
        service_name = getenv("SCD_SERVER");
        }
 
        service_name = getenv("SCD_SERVER");
@@ -401,10 +413,10 @@ server_shutdown()
                                fprintf(stderr,  "bootstrap_register() failed: status=%d\n", status);
                                fflush (stderr);
                        }
                                fprintf(stderr,  "bootstrap_register() failed: status=%d\n", status);
                                fflush (stderr);
                        }
-                       exit (EX_UNAVAILABLE);
+                       return EX_UNAVAILABLE;
        }
 
        }
 
-       exit(EX_OK);
+       return EX_OK;
 }
 
 
 }
 
 
index af388a11764e0a3a7e21806f7fb18c4078ec5934..4784de975035c544f103ec29a2635f7b65bd188d 100644 (file)
@@ -36,9 +36,7 @@
 
 #include <sys/cdefs.h>
 #include <mach/mach.h>
 
 #include <sys/cdefs.h>
 #include <mach/mach.h>
-
-#include <CoreFoundation/CFRunLoop.h>
-#include <CoreFoundation/CFMachPort.h>
+#include <CoreFoundation/CoreFoundation.h>
 
 __BEGIN_DECLS
 
 
 __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_init     (mach_port_t            service_port,
                                 Boolean                enableRestart);
 
-void           server_shutdown ();
+int            server_shutdown ();
 
 void           server_loop     ();
 
 
 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,
 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);
 
                                 mach_port_t            *newServer,
                                 int                    *sc_status);
 
diff --git a/configd.tproj/h.template b/configd.tproj/h.template
deleted file mode 100644 (file)
index f3c1b04..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
diff --git a/configd.tproj/m.template b/configd.tproj/m.template
deleted file mode 100644 (file)
index 1216fe5..0000000
+++ /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 (file)
index 7ebc7ab..0000000
+++ /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 <ajn@apple.com>
- * - public API conversion
- *
- * March 31, 2000              Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-
-#include <unistd.h>
-
-#include "configd.h"
-#include "configd_server.h"
-#include "session.h"
-
-
-__private_extern__
-void
-pushNotifications()
-{
-       const void                      **sessionsToNotify;
-       CFIndex                         notifyCnt;
-       int                             server;
-       serverSessionRef                theSession;
-       SCDynamicStorePrivateRef        storePrivate;
-
-       if (needsNotification == NULL)
-               return;         /* if no sessions need to be kicked */
-
-       notifyCnt = CFSetGetCount(needsNotification);
-       sessionsToNotify = malloc(notifyCnt * sizeof(CFNumberRef));
-       CFSetGetValues(needsNotification, sessionsToNotify);
-       while (--notifyCnt >= 0) {
-               (void) CFNumberGetValue(sessionsToNotify[notifyCnt],
-                                       kCFNumberIntType,
-                                       &server);
-               theSession = getSession(server);
-               storePrivate = (SCDynamicStorePrivateRef)theSession->store;
-
-               /*
-                * deliver notifications to client sessions
-                */
-               if ((storePrivate->notifyStatus == Using_NotifierInformViaMachPort) &&
-                   (storePrivate->notifyPort != MACH_PORT_NULL)) {
-                       mach_msg_empty_send_t   msg;
-                       mach_msg_option_t       options;
-                       kern_return_t           status;
-                       /*
-                        * Post notification as mach message
-                        */
-                       if (_configd_verbose) {
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("sending mach message notification."));
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("  port  = %d"), storePrivate->notifyPort);
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("  msgid = %d"), storePrivate->notifyPortIdentifier);
-                       }
-                       msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
-                       msg.header.msgh_size = sizeof(msg);
-                       msg.header.msgh_remote_port = storePrivate->notifyPort;
-                       msg.header.msgh_local_port = MACH_PORT_NULL;
-                       msg.header.msgh_id = storePrivate->notifyPortIdentifier;
-                       options = MACH_SEND_TIMEOUT;
-                       status = mach_msg(&msg.header,                  /* msg */
-                                         MACH_SEND_MSG|options,        /* options */
-                                         msg.header.msgh_size,         /* send_size */
-                                         0,                            /* rcv_size */
-                                         MACH_PORT_NULL,               /* rcv_name */
-                                         0,                            /* timeout */
-                                         MACH_PORT_NULL);              /* notify */
-               }
-
-               if ((storePrivate->notifyStatus == Using_NotifierInformViaFD) &&
-                   (storePrivate->notifyFile >= 0)) {
-                       ssize_t         written;
-
-                       if (_configd_verbose) {
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification"));
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("  fd    = %d"), storePrivate->notifyFile);
-                               SCLog(TRUE, LOG_DEBUG, CFSTR("  msgid = %d"), storePrivate->notifyFileIdentifier);
-                       }
-
-                       written = write(storePrivate->notifyFile,
-                                       &storePrivate->notifyFileIdentifier,
-                                       sizeof(storePrivate->notifyFileIdentifier));
-                       if (written == -1) {
-                               if (errno == EWOULDBLOCK) {
-                                       SCLog(_configd_verbose, LOG_DEBUG,
-                                              CFSTR("sorry, only one outstanding notification per session."));
-                               } else {
-                                       SCLog(_configd_verbose, LOG_DEBUG,
-                                              CFSTR("could not send notification, write() failed: %s"),
-                                              strerror(errno));
-                                       storePrivate->notifyFile = -1;
-                               }
-                       } else if (written != sizeof(storePrivate->notifyFileIdentifier)) {
-                               SCLog(_configd_verbose, LOG_DEBUG,
-                                      CFSTR("could not send notification, incomplete write()"));
-                               storePrivate->notifyFile = -1;
-                       }
-               }
-
-               if ((storePrivate->notifyStatus == Using_NotifierInformViaSignal) &&
-                   (storePrivate->notifySignal > 0)) {
-                       kern_return_t   status;
-                       pid_t           pid;
-                       /*
-                        * Post notification as signal
-                        */
-                       status = pid_for_task(storePrivate->notifySignalTask, &pid);
-                       if (status == KERN_SUCCESS) {
-                               if (_configd_verbose) {
-                                       SCLog(TRUE, LOG_DEBUG, CFSTR("sending signal notification"));
-                                       SCLog(TRUE, LOG_DEBUG, CFSTR("  pid    = %d"), pid);
-                                       SCLog(TRUE, LOG_DEBUG, CFSTR("  signal = %d"), storePrivate->notifySignal);
-                               }
-                               if (kill(pid, storePrivate->notifySignal) != 0) {
-                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno));
-                                       status = KERN_FAILURE;
-                               }
-                       } else {
-                               mach_port_type_t        pt;
-
-                               if ((mach_port_type(mach_task_self(), storePrivate->notifySignalTask, &pt) == KERN_SUCCESS) &&
-                                   (pt & MACH_PORT_TYPE_DEAD_NAME)) {
-                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal, process died"));
-                               } else {
-                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status));
-                               }
-                       }
-
-                       if (status != KERN_SUCCESS) {
-                               /* don't bother with any more attempts */
-                               (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask);
-                               storePrivate->notifySignal     = 0;
-                               storePrivate->notifySignalTask = TASK_NULL;
-                       }
-              }
-       }
-       free(sessionsToNotify);
-
-       /*
-        * this list of notifications have been posted, wait for some more.
-        */
-       CFRelease(needsNotification);
-       needsNotification = NULL;
-
-       return;
-}
diff --git a/configd.tproj/notify.h b/configd.tproj/notify.h
deleted file mode 100644 (file)
index 014da25..0000000
+++ /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 <ajn@apple.com>
- * - initial revision
- */
-
-#ifndef _S_NOTIFY_H
-#define _S_NOTIFY_H
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-void           pushNotifications       ();
-
-__END_DECLS
-
-#endif /* !_S_NOTIFY_H */
index b914891db5f92a900d27724f83c78424e0a7b5c8..1d490d81da512cc70e532488f9e475f4ac0d8a2f 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -30,7 +30,6 @@
 
 #include "configd.h"
 #include "session.h"
 
 #include "configd.h"
 #include "session.h"
-#include "notify.h"
 
 __private_extern__
 boolean_t
 
 __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"),
        }
 
        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;
 
        Reply->NDR     = NDR_record;
        Reply->RetCode = MIG_BAD_ID;
index fa3bf864fa0f276ba0bb1af9e4c53d8eb9cdf24b..72446273e5884e16a1ff0cd293e45ef6c9d7be6f 100644 (file)
@@ -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) {
        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;
        }
 
                goto done;
        }
 
@@ -108,7 +108,7 @@ identifyKeyForPattern(const void *key, void *val, void *context)
                        char    reErrBuf[256];
 
                        (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
                        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;
                }
        }
                        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);
 
                        (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"));
                        ok = FALSE;
                }
        } else {
                *error = CFRetain(CFSTR("could not convert pattern to regex string"));
+#ifdef DEBUG
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error);
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error);
+#endif /* DEBUG */
        }
 
        if (str != str_q)       CFAllocatorDeallocate(NULL, str);
        }
 
        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) {
        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;
        }
 
                goto done;
        }
 
@@ -389,7 +393,7 @@ addKeyForPattern(const void *key, void *val, void *context)
                        char    reErrBuf[256];
 
                        (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
                        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;
                }
        }
                        break;
                }
        }
@@ -432,7 +436,7 @@ removeKeyFromPattern(const void *key, void *val, void *context)
        }
 
        i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey);
        }
 
        i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey);
-       if (i == -1) {
+       if (i == kCFNotFound) {
                /* if this key wasn't matched by this pattern */
                return;
        }
                /* if this key wasn't matched by this pattern */
                return;
        }
index 80e5b85ad29770d8226fe92e409df3dc35565f52..266220f71be31e63388d5efb7b13ae57971309c4 100644 (file)
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * October 30, 2003            Allan Nathanson <ajn@apple.com>
+ * - add plugin "stop()" function support
+ *
  * June 11, 2001               Allan Nathanson <ajn@apple.com>
  * - start using CFBundle code
  *
  * June 11, 2001               Allan Nathanson <ajn@apple.com>
  * - start using CFBundle code
  *
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <dirent.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <dirent.h>
+#include <sysexits.h>
 #include <unistd.h>
 #include <NSSystemDirectories.h>
 
 #include "configd.h"
 #include <unistd.h>
 #include <NSSystemDirectories.h>
 
 #include "configd.h"
+#include "configd_server.h"
 #include <SystemConfiguration/SCDPlugin.h>
 void   _SCDPluginExecInit();
 
 #include <SystemConfiguration/SCDPlugin.h>
 void   _SCDPluginExecInit();
 
@@ -54,128 +59,149 @@ void      _SCDPluginExecInit();
 #define        BUNDLE_DIR_EXTENSION    ".bundle"
 
 
 #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)
 {
 }
 
 
 static CFStringRef
 shortBundleIdentifier(CFStringRef bundleID)
 {
-       CFIndex         len     = CFStringGetLength(bundleID);
-       CFRange         range;
+       CFIndex         len     = CFStringGetLength(bundleID);
+       CFRange         range;
        CFStringRef     shortID = NULL;
 
        if (CFStringFindWithOptions(bundleID,
        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;
        }
 
                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;
 }
 
 
        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;
        }
 
                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;
        }
 
                return;
        }
 
-       dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle));
-       if (!dict) {
+       if (bundleInfo->start == NULL) {
+               // if no start() function
                return;
        }
 
                return;
        }
 
-       bundleURL = CFBundleCopyBundleURL(bundle);
-       if (!bundleURL) {
+       bundleURL = CFBundleCopyBundleURL(bundleInfo->bundle);
+       if (bundleURL == NULL) {
                return;
        }
 
                return;
        }
 
@@ -359,30 +402,209 @@ startBundle(const void *value, void *context) {
        bundleName[0] = '\0';
        (void) strncat(bundleName, cp, len);
 
        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
        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;
        }
 
                return;
        }
 
-       prime = CFBundleGetFunctionPointerForName(bundle, CFSTR("prime"));
-       if (!prime) {
+       if (bundleInfo->stop == NULL) {
+               // if no stop() function
                return;
        }
 
                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;
 }
 
 
        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
 #ifdef DEBUG
 
 static void
@@ -400,30 +622,30 @@ timerCallback(CFRunLoopTimerRef timer, void *info)
 static void
 sortBundles(CFMutableArrayRef orig)
 {
 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++) {
        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;
 
                        int             count;
                        CFDictionaryRef dict;
                        int             j;
                        int             nRequires;
                        CFArrayRef      requires  = NULL;
 
-                       dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle1));
+                       dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundleInfo1->bundle));
                        if (dict) {
                        if (dict) {
-                               requires = CFDictionaryGetValue(dict, kSCBundleRequires);
+                               requires = CFDictionaryGetValue(dict, kSCBundleRequiresKey);
                                requires = isA_CFArray(requires);
                        }
                        if (bundleID1 == NULL || requires == NULL) {
                                requires = isA_CFArray(requires);
                        }
                        if (bundleID1 == NULL || requires == NULL) {
-                               CFArrayInsertValueAtIndex(new, 0, bundle1);
+                               CFArrayInsertValueAtIndex(new, 0, bundleInfo1);
                                CFArrayRemoveValueAtIndex(orig, i);
                                inserted = TRUE;
                                break;
                                CFArrayRemoveValueAtIndex(orig, i);
                                inserted = TRUE;
                                break;
@@ -436,8 +658,8 @@ sortBundles(CFMutableArrayRef orig)
 
                                nNew = CFArrayGetCount(new);
                                for (k = 0; k < nNew; k++) {
 
                                nNew = CFArrayGetCount(new);
                                for (k = 0; k < nNew; k++) {
-                                       CFBundleRef     bundle2   = (CFBundleRef)CFArrayGetValueAtIndex(new, k);
-                                       CFStringRef     bundleID2 = CFBundleGetIdentifier(bundle2);
+                                       bundleInfoRef   bundleInfo2     = (bundleInfoRef)CFArrayGetValueAtIndex(new, k);
+                                       CFStringRef     bundleID2       = CFBundleGetIdentifier(bundleInfo2->bundle);
 
                                        if (bundleID2 && CFEqual(bundleID2, r)) {
                                                count--;
 
                                        if (bundleID2 && CFEqual(bundleID2, r)) {
                                                count--;
@@ -446,7 +668,7 @@ sortBundles(CFMutableArrayRef orig)
                        }
                        if (count == 0) {
                                /* all dependencies are met, append */
                        }
                        if (count == 0) {
                                /* all dependencies are met, append */
-                               CFArrayAppendValue(new, bundle1);
+                               CFArrayAppendValue(new, bundleInfo1);
                                CFArrayRemoveValueAtIndex(orig, i);
                                inserted = TRUE;
                                break;
                                CFArrayRemoveValueAtIndex(orig, i);
                                inserted = TRUE;
                                break;
@@ -477,10 +699,10 @@ __private_extern__
 void *
 plugin_exec(void *arg)
 {
 void *
 plugin_exec(void *arg)
 {
-       CFIndex                 nLoaded         = 0;
+       CFIndex         nLoaded         = 0;
 
        /* keep track of bundles */
 
        /* keep track of bundles */
-       allBundles = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       allBundles = CFArrayCreateMutable(NULL, 0, NULL);
 
        /* allow plug-ins to exec child/helper processes */
        _SCDPluginExecInit();
 
        /* 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,
                 * identify and load all bundles
                 */
                state = NSStartSearchPathEnumeration(NSLibraryDirectory,
-                                                    NSLocalDomainMask|NSSystemDomainMask);
+                                                    NSSystemDomainMask);
                while ((state = NSGetNextSearchPathEnumeration(state, path))) {
                        CFArrayRef      bundles;
                        CFURLRef        url;
                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);
 
                        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);
                        }
                }
                                CFRelease(bundles);
                        }
                }
@@ -529,17 +758,26 @@ plugin_exec(void *arg)
                                                              strlen((char *)arg),
                                                              TRUE);
                bundle = CFBundleCreate(NULL, url);
                                                              strlen((char *)arg),
                                                              TRUE);
                bundle = CFBundleCreate(NULL, url);
-               if (bundle) {
-                       CFArrayAppendValue(allBundles, bundle);
+               if (bundle != NULL) {
+                       addBundle(bundle);
                        CFRelease(bundle);
                }
                CFRelease(url);
        }
 
        /*
                        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
         *
         * 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)),
        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
 
        /*
         * 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)),
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle start() functions"));
        CFArrayApplyFunction(allBundles,
                             CFRangeMake(0, CFArrayGetCount(allBundles)),
-                            startBundle,
+                            callStartFunction,
                             NULL);
 
        /*
                             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)),
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle prime() functions"));
        CFArrayApplyFunction(allBundles,
                             CFRangeMake(0, CFArrayGetCount(allBundles)),
-                            primeBundle,
+                            callPrimeFunction,
                             NULL);
 
 #ifdef DEBUG
                             NULL);
 
 #ifdef DEBUG
@@ -608,8 +846,11 @@ plugin_exec(void *arg)
         * private thread.
         */
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("starting plugin CFRunLoop"));
         * private thread.
         */
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("starting plugin CFRunLoop"));
+       plugin_runLoop = CFRunLoopGetCurrent();
        CFRunLoopRun();
        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;
 }
 
        return NULL;
 }
 
index 0891ca68e426690396154bcfc6f90313062f67fa..63d515a55c2a8fa3a5c59c5b5d5981040cff64e7 100644 (file)
@@ -37,6 +37,7 @@ __BEGIN_DECLS
 
 void   plugin_init     ();
 void   plugin_exec     (void   *arg);
 
 void   plugin_init     ();
 void   plugin_exec     (void   *arg);
+Boolean        plugin_term     (int    *status);
 
 __END_DECLS
 
 
 __END_DECLS
 
index 6c299bbe3670dd4e985723ff341f2b86c88cb60b..94e421345bf1adad31fc8c04eb147804006b39ec 100644 (file)
@@ -47,7 +47,7 @@ getSession(mach_port_t server)
        int     i;
 
        if (server == MACH_PORT_NULL) {
        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;
        }
 
                return NULL;
        }
 
@@ -93,11 +93,11 @@ addSession(CFMachPortRef server)
                if (n < 0) {
                        /* no empty slots, add one to the list */
                        n = nSessions++;
                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;
        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 (file)
index 0000000..8ef21cc
--- /dev/null
@@ -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 = "<group>";
+               };
+               150607DE075A00A300B147BA = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCSchemaDefinitions.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15060818075A00A300B147BA = {
+                       fileRef = 150607BD075A00A200B147BA;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1506081A075A00A300B147BA = {
+                       fileRef = 150607DE075A00A300B147BA;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               1508E39F07552B6A0062B350 = {
+                       fileRef = 159D53C707528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1508E3A007552B6B0062B350 = {
+                       fileRef = 159D53C507528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1508E3A107552B720062B350 = {
+                       fileRef = 159D53CA07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1514D76D05C08A5F00757DC9 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = config_types.h;
+                       path = SystemConfiguration.fproj/config_types.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               1514D77D05C08AB700757DC9 = {
+                       children = (
+                               15CB690505C0722A0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = "Initial Preferences";
+                       path = "";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               151BDA2B05D9E28B00657BC7 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = SCPreferencesPathKey.h;
+                       path = SystemConfiguration.fproj/SCPreferencesPathKey.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               151BDA5D05D9E2ED00657BC7 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = SCPreferencesPathKey.c;
+                       path = SystemConfiguration.fproj/SCPreferencesPathKey.c;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               1521FC5C060F296A003B28F5 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = dnsinfo_create.c;
+                       path = dnsinfo/dnsinfo_create.c;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               1523F6EE075A36210066F0B2 = {
+                       fileRef = 15DAD6C807591A1A0084A6ED;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1523F6F1075A36F70066F0B2 = {
+                       fileRef = 15DAD6C807591A1A0084A6ED;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1523F6F2075A37050066F0B2 = {
+                       fileRef = 15DAD6C807591A1A0084A6ED;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1523F710075A371D0066F0B2 = {
+                       fileRef = 15DAD6C807591A1A0084A6ED;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1523F715075A376B0066F0B2 = {
+                       fileRef = 15DAD5EE075913CE0084A6ED;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1523F719075A37C70066F0B2 = {
+                       fileRef = 15DAD5EE075913CE0084A6ED;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               152CEED0070CF6640050F23C = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = "compiled.mach-o.dylib";
+                       name = libedit.dylib;
+                       path = /usr/lib/libedit.2.dylib;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               1532629006281C9D00B1C10C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dnsinfo_create.h;
+                       path = dnsinfo/dnsinfo_create.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               154361E00752C81800A8EC6C = {
+                       fileRef = 159D53AB07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1543636A0752D03C00A8EC6C = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = wrapper.framework;
+                       name = IOKit.framework;
+                       path = /System/Library/Frameworks/IOKit.framework;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               1543636B0752D03C00A8EC6C = {
+                       fileRef = 1543636A0752D03C00A8EC6C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15481BF7075A2B3900B32F56 = {
+                       buildPhases = (
+                               15481C14075A2B7300B32F56,
+                       );
+                       buildSettings = {
+                               INSTALLHDRS_SCRIPT_PHASE = YES;
+                               OTHER_CFLAGS = "";
+                               OTHER_LDFLAGS = "";
+                               PRODUCT_NAME = genSCPreferences;
+                               SECTORDER_FLAGS = "";
+                               WARNING_CFLAGS = "-Wall -Wno-four-char-constants -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXToolTarget;
+                       name = Schema;
+                       productInstallPath = /usr/local/bin;
+                       productName = Schema;
+                       productReference = 15481BF8075A2B3900B32F56;
+               };
+               15481BF8075A2B3900B32F56 = {
+                       explicitFileType = "compiled.mach-o.executable";
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = genSCPreferences;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15481C14075A2B7300B32F56 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               SystemConfiguration.fproj/genSCPreferences.c,
+                       );
+                       isa = PBXShellScriptBuildPhase;
+                       outputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h",
+                               "${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "cc -o ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} ${SRCROOT}/SystemConfiguration.fproj/genSCPreferences.c\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} header   > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.h\n${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME} cfile    > ${BUILT_PRODUCTS_DIR}/SCSchemaDefinitions.c\nexit 0";
+               };
+               154CF3F307E1EA4D00D8302E = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferencesGetSpecificPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               154CF3F407E1EA4D00D8302E = {
+                       fileRef = 154CF3F307E1EA4D00D8302E;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               155847430754FDCD0046C2E9 = {
+                       buildPhases = (
+                               155847460754FDCD0046C2E9,
+                               155847540754FDCD0046C2E9,
+                               155847620754FDCD0046C2E9,
+                               155847670754FDCD0046C2E9,
+                               155847680754FDCD0046C2E9,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               CURRENT_PROJECT_VERSION = 130;
+                               DEAD_CODE_STRIPPING = YES;
+                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/sbin;
+                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = scutil;
+                               STRIPFLAGS = "-S";
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = scutil;
+                       productInstallPath = /usr/sbin;
+                       productName = "scutil (Tool)";
+                       productReference = 1558476A0754FDCD0046C2E9;
+                       productType = "com.apple.product-type.tool";
+               };
+               155847460754FDCD0046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               155847470754FDCD0046C2E9,
+                               155847480754FDCD0046C2E9,
+                               155847490754FDCD0046C2E9,
+                               1558474A0754FDCD0046C2E9,
+                               1558474B0754FDCD0046C2E9,
+                               1558474C0754FDCD0046C2E9,
+                               1558474D0754FDCD0046C2E9,
+                               1558474E0754FDCD0046C2E9,
+                               1558474F0754FDCD0046C2E9,
+                               155847500754FDCD0046C2E9,
+                               155847510754FDCD0046C2E9,
+                               155847520754FDCD0046C2E9,
+                               155847530754FDCD0046C2E9,
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               155847470754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4305C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847480754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4505C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847490754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4705C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558474A0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4905C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558474B0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4B05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558474C0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4D05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558474D0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A4F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558474E0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5105C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558474F0754FDCD0046C2E9 = {
+                       fileRef = 15A509A406C2518F001F0AB7;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847500754FDCD0046C2E9 = {
+                       fileRef = 15DC34680711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847510754FDCD0046C2E9 = {
+                       fileRef = 15DC346A0711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847520754FDCD0046C2E9 = {
+                       fileRef = 15DC346C0711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847530754FDCD0046C2E9 = {
+                       fileRef = 15DC346E0711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847540754FDCD0046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               155847550754FDCD0046C2E9,
+                               155847560754FDCD0046C2E9,
+                               155847570754FDCD0046C2E9,
+                               155847580754FDCD0046C2E9,
+                               155847590754FDCD0046C2E9,
+                               1558475A0754FDCD0046C2E9,
+                               1558475B0754FDCD0046C2E9,
+                               1558475C0754FDCD0046C2E9,
+                               1558475D0754FDCD0046C2E9,
+                               1558475E0754FDCD0046C2E9,
+                               1558475F0754FDCD0046C2E9,
+                               155847600754FDCD0046C2E9,
+                               155847610754FDCD0046C2E9,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               155847550754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               155847560754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               155847570754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               155847580754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               155847590754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               1558475A0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A5E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               1558475B0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A6005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               1558475C0754FDCD0046C2E9 = {
+                       fileRef = 15CB6A6205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               1558475D0754FDCD0046C2E9 = {
+                       fileRef = 15A509A306C2518F001F0AB7;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558475E0754FDCD0046C2E9 = {
+                       fileRef = 15DC34670711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558475F0754FDCD0046C2E9 = {
+                       fileRef = 15DC34690711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847600754FDCD0046C2E9 = {
+                       fileRef = 15DC346B0711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847610754FDCD0046C2E9 = {
+                       fileRef = 15DC346D0711D49400A3311C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847620754FDCD0046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               155847640754FDCD0046C2E9,
+                               1523F710075A371D0066F0B2,
+                               1523F719075A37C70066F0B2,
+                               155847660754FDCD0046C2E9,
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               155847640754FDCD0046C2E9 = {
+                       fileRef = 15CB6A6F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847660754FDCD0046C2E9 = {
+                       fileRef = 152CEED0070CF6640050F23C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               155847670754FDCD0046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXRezBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               155847680754FDCD0046C2E9 = {
+                       buildActionMask = 2147483647;
+                       dstPath = /usr/share/man/man8;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               155847690754FDCD0046C2E9,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               155847690754FDCD0046C2E9 = {
+                       fileRef = 15CB6A6A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558476A0754FDCD0046C2E9 = {
+                       explicitFileType = "compiled.mach-o.executable";
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = scutil;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               155847FA07550D210046C2E9 = {
+                       buildPhases = (
+                       );
+                       buildSettings = {
+                               DEAD_CODE_STRIPPING = YES;
+                               PRODUCT_NAME = configd_executables;
+                               STRIPFLAGS = "-S";
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                               1558480607550D470046C2E9,
+                               1558480807550D470046C2E9,
+                               1558480A07550D470046C2E9,
+                       );
+                       isa = PBXAggregateTarget;
+                       name = configd_executables;
+                       productName = configd_executables;
+               };
+               1558480507550D470046C2E9 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D549F07529FFF004F8947;
+                       remoteInfo = configd;
+               };
+               1558480607550D470046C2E9 = {
+                       isa = PBXTargetDependency;
+                       target = 159D549F07529FFF004F8947;
+                       targetProxy = 1558480507550D470046C2E9;
+               };
+               1558480707550D470046C2E9 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15CB6A2705C0722B0099E85F;
+                       remoteInfo = scselect;
+               };
+               1558480807550D470046C2E9 = {
+                       isa = PBXTargetDependency;
+                       target = 1558481207550EC10046C2E9;
+                       targetProxy = 1558480707550D470046C2E9;
+               };
+               1558480907550D470046C2E9 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 155847430754FDCD0046C2E9;
+                       remoteInfo = scutil;
+               };
+               1558480A07550D470046C2E9 = {
+                       isa = PBXTargetDependency;
+                       target = 155847430754FDCD0046C2E9;
+                       targetProxy = 1558480907550D470046C2E9;
+               };
+               1558480E07550DD00046C2E9 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 155847FA07550D210046C2E9;
+                       remoteInfo = configd_executables;
+               };
+               1558480F07550DD00046C2E9 = {
+                       isa = PBXTargetDependency;
+                       target = 155847FA07550D210046C2E9;
+                       targetProxy = 1558480E07550DD00046C2E9;
+               };
+               1558481207550EC10046C2E9 = {
+                       buildPhases = (
+                               1558481407550EC10046C2E9,
+                               1558481507550EC10046C2E9,
+                               1558481707550EC10046C2E9,
+                               1558481A07550EC10046C2E9,
+                               1558481B07550EC10046C2E9,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               CURRENT_PROJECT_VERSION = 130;
+                               DEAD_CODE_STRIPPING = YES;
+                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INSTALL_MODE_FLAG = "a-w,a+rX,u+s";
+                               INSTALL_PATH = /usr/sbin;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = scselect;
+                               STRIPFLAGS = "-S";
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = scselect;
+                       productInstallPath = /usr/sbin;
+                       productName = "scselect (Tool)";
+                       productReference = 1558481D07550EC10046C2E9;
+                       productType = "com.apple.product-type.tool";
+               };
+               1558481407550EC10046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               1558481507550EC10046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               1558481607550EC10046C2E9,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               1558481607550EC10046C2E9 = {
+                       fileRef = 15CB6A2E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               1558481707550EC10046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               1558481907550EC10046C2E9,
+                               1523F6F2075A37050066F0B2,
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               1558481907550EC10046C2E9 = {
+                       fileRef = 15CB6A6F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558481A07550EC10046C2E9 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXRezBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               1558481B07550EC10046C2E9 = {
+                       buildActionMask = 2147483647;
+                       dstPath = /usr/share/man/man8;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               1558481C07550EC10046C2E9,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               1558481C07550EC10046C2E9 = {
+                       fileRef = 15CB6A3605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               1558481D07550EC10046C2E9 = {
+                       explicitFileType = "compiled.mach-o.executable";
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = scselect;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               156BD6BB07E0DFA9008698FF = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferencesSetSpecificPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               156BD6BC07E0DFA9008698FF = {
+                       fileRef = 156BD6BB07E0DFA9008698FF;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               1577252F06EFB96700D7B52B = {
+                       fileEncoding = 10;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.plist.strings;
+                       name = English;
+                       path = English.lproj/NetworkInterface.strings;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               1577253606EFBF3100D7B52B = {
+                       children = (
+                               1577252F06EFB96700D7B52B,
+                       );
+                       isa = PBXVariantGroup;
+                       name = NetworkInterface.strings;
+                       path = "";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               157BB8AE075924360025DA7A = {
+                       buildPhases = (
+                       );
+                       buildSettings = {
+                               PRODUCT_NAME = Frameworks;
+                               WARNING_CFLAGS = "-Wmost -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                               157BB8C2075924470025DA7A,
+                               157BB8C0075924460025DA7A,
+                       );
+                       isa = PBXAggregateTarget;
+                       name = configd_base;
+                       productName = Frameworks;
+               };
+               157BB8BF075924460025DA7A = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15DAD63F07591A1A0084A6ED;
+                       remoteInfo = SystemConfiguration.framework;
+               };
+               157BB8C0075924460025DA7A = {
+                       isa = PBXTargetDependency;
+                       target = 15DAD63F07591A1A0084A6ED;
+                       targetProxy = 157BB8BF075924460025DA7A;
+               };
+               157BB8C1075924470025DA7A = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15DAD5DF075913CE0084A6ED;
+                       remoteInfo = DNSConfiguration;
+               };
+               157BB8C2075924470025DA7A = {
+                       isa = PBXTargetDependency;
+                       target = 15DAD5DF075913CE0084A6ED;
+                       targetProxy = 157BB8C1075924470025DA7A;
+               };
+               157BB8C30759244B0025DA7A = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 157BB8AE075924360025DA7A;
+                       remoteInfo = Frameworks;
+               };
+               157BB8C40759244B0025DA7A = {
+                       isa = PBXTargetDependency;
+                       target = 157BB8AE075924360025DA7A;
+                       targetProxy = 157BB8C30759244B0025DA7A;
+               };
+               15828AE30753B5F900AD4710 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15828AE60753B5F900AD4710 = {
+                       buildPhases = (
+                               15828AE30753B5F900AD4710,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INFOPLIST_FILE = Plugins/KernelEventMonitor/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               LIBRARY_STYLE = BUNDLE;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = KernelEventMonitor;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = KernelEventMonitor.bundle;
+                       productName = KernelEventMonitor.bundle;
+                       productReference = 15828AE70753B5F900AD4710;
+                       productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleExecutable</key>
+       <string>KernelEventMonitor.bundle</string>
+       <key>CFBundleIdentifier</key>
+       <string>com.yourcompany.KernelEventMonitor_bundle</string>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleVersion</key>
+       <string>1.0</string>
+       <key>CSResourcesFileMapped</key>
+       <string>yes</string>
+</dict>
+</plist>
+";
+                       productType = "com.apple.product-type.bundle";
+               };
+               15828AE70753B5F900AD4710 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = KernelEventMonitor.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15828B060753B77E00AD4710 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15828AE60753B5F900AD4710;
+                       remoteInfo = KernelEventMonitor.bundle;
+               };
+               15828B070753B77E00AD4710 = {
+                       isa = PBXTargetDependency;
+                       target = 15828AE60753B5F900AD4710;
+                       targetProxy = 15828B060753B77E00AD4710;
+               };
+               1582B36B05FD1A4D009C2750 = {
+                       children = (
+                               1582B37205FD1A5B009C2750,
+                               1582B37905FD1A66009C2750,
+                       );
+                       isa = PBXGroup;
+                       name = DNSConfiguration;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               1582B37205FD1A5B009C2750 = {
+                       children = (
+                               15B73F0905FD1B670096477F,
+                               1532629006281C9D00B1C10C,
+                               15B73F0C05FD1B670096477F,
+                               15B73F0E05FD1B670096477F,
+                       );
+                       isa = PBXGroup;
+                       name = Headers;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               1582B37905FD1A66009C2750 = {
+                       children = (
+                               15B73F0B05FD1B670096477F,
+                               15B73F0805FD1B670096477F,
+                               1521FC5C060F296A003B28F5,
+                               15B73F0D05FD1B670096477F,
+                       );
+                       isa = PBXGroup;
+                       name = Sources;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158AD85B0754E38F00124717 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158AD8700754E3D400124717 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158AD8C00754E3EF00124717 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158AD9100754E40E00124717 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158AD9850754E72500124717 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15FD72A10754DA4C001CC321;
+                       remoteInfo = IPMonitor.bundle;
+               };
+               158AD9860754E72500124717 = {
+                       isa = PBXTargetDependency;
+                       target = 15FD72A10754DA4C001CC321;
+                       targetProxy = 158AD9850754E72500124717;
+               };
+               158AD9870754E72500124717 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15FD72930754DA2B001CC321;
+                       remoteInfo = InterfaceNamer.bundle;
+               };
+               158AD9880754E72500124717 = {
+                       isa = PBXTargetDependency;
+                       target = 15FD72930754DA2B001CC321;
+                       targetProxy = 158AD9870754E72500124717;
+               };
+               158AD9890754E72500124717 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15FD70FF0754D627001CC321;
+                       remoteInfo = Kicker.bundle;
+               };
+               158AD98A0754E72500124717 = {
+                       isa = PBXTargetDependency;
+                       target = 15FD70FF0754D627001CC321;
+                       targetProxy = 158AD9890754E72500124717;
+               };
+               158AD98B0754E72500124717 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15FD72B10754DA69001CC321;
+                       remoteInfo = LinkConfiguration.bundle;
+               };
+               158AD98C0754E72500124717 = {
+                       isa = PBXTargetDependency;
+                       target = 15FD72B10754DA69001CC321;
+                       targetProxy = 158AD98B0754E72500124717;
+               };
+               158AD98D0754E72500124717 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15FD72C50754DA7E001CC321;
+                       remoteInfo = PreferencesMonitor.bundle;
+               };
+               158AD98E0754E72500124717 = {
+                       isa = PBXTargetDependency;
+                       target = 15FD72C50754DA7E001CC321;
+                       targetProxy = 158AD98D0754E72500124717;
+               };
+               158AD9F80754EA2F00124717 = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = wrapper.framework;
+                       name = AppleTalk.framework;
+                       path = /System/Library/Frameworks/AppleTalk.framework;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               158ADA160754EA2F00124717 = {
+                       fileRef = 158AD9F80754EA2F00124717;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               158ADA3D0754EA5A00124717 = {
+                       fileRef = 15CB6A6F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               158ADABB0754EAAE00124717 = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = wrapper.framework;
+                       name = SystemConfiguration.framework;
+                       path = /System/Library/Frameworks/SystemConfiguration.framework;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               158ADBFD0754ECB100124717 = {
+                       children = (
+                               15FD73400754DBDA001CC321,
+                               15FD73220754DB9F001CC321,
+                               159D53EC07528C61004F8947,
+                               15FD72A50754DA4C001CC321,
+                               159D53E507528C4A004F8947,
+                               15FD72970754DA2B001CC321,
+                               159D53D407528BDA004F8947,
+                               15828AE70753B5F900AD4710,
+                               159D53DE07528C2E004F8947,
+                               15FD71090754D628001CC321,
+                               159D53F307528C79004F8947,
+                               15FD72B50754DA69001CC321,
+                               159D53FA07528C95004F8947,
+                               15FD72C90754DA7E001CC321,
+                       );
+                       isa = PBXGroup;
+                       name = Plugins;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158ADCA60754ECC800124717 = {
+                       children = (
+                               159D54D907529FFF004F8947,
+                       );
+                       isa = PBXGroup;
+                       name = "configd, scutil, scselect";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               158ADD0E0754F1A000124717 = {
+                       fileRef = 159D53A807528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               158ADD190754F1F100124717 = {
+                       fileRef = 159D53BC07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               158ADD1B0754F1F400124717 = {
+                       fileRef = 159D53BD07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D53A207528B06004F8947 = {
+                       children = (
+                               159D53C907528B36004F8947,
+                               159D53C407528B36004F8947,
+                               159D53A607528B36004F8947,
+                               159D53AC07528B36004F8947,
+                               159D53AF07528B36004F8947,
+                               159D53BB07528B36004F8947,
+                               159D53C007528B36004F8947,
+                               159D53C207528B36004F8947,
+                       );
+                       isa = PBXGroup;
+                       name = Plugins;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53A607528B36004F8947 = {
+                       children = (
+                               159D53A707528B36004F8947,
+                               159D53AA07528B36004F8947,
+                               159D53AB07528B36004F8947,
+                               159D53A807528B36004F8947,
+                               15FD743E0754DE7A001CC321,
+                       );
+                       isa = PBXGroup;
+                       name = IPMonitor;
+                       path = Plugins/IPMonitor;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53A707528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = ip_plugin.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53A807528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Resolvers.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53AA07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = "dns-configuration.c";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53AB07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = "set-hostname.c";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53AC07528B36004F8947 = {
+                       children = (
+                               159D53AE07528B36004F8947,
+                               15FD73EE0754DE62001CC321,
+                       );
+                       isa = PBXGroup;
+                       name = InterfaceNamer;
+                       path = Plugins/InterfaceNamer;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53AE07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = ifnamer.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53AF07528B36004F8947 = {
+                       children = (
+                               159D53B707528B36004F8947,
+                               159D53B607528B36004F8947,
+                               159D53B207528B36004F8947,
+                               159D53B807528B36004F8947,
+                               159D53BA07528B36004F8947,
+                               159D53B007528B36004F8947,
+                               159D53B907528B36004F8947,
+                               159D53B107528B36004F8947,
+                               159D53B307528B36004F8947,
+                               159D53B407528B36004F8947,
+                               158AD8700754E3D400124717,
+                       );
+                       isa = PBXGroup;
+                       name = KernelEventMonitor;
+                       path = Plugins/KernelEventMonitor;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B007528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = eventmon.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B107528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = ev_dlil.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B207528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = ev_dlil.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B307528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = ev_ipv4.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B407528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = ev_ipv6.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B607528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = ev_appletalk.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B707528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = eventmon.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B807528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = ev_ipv4.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53B907528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = ev_appletalk.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53BA07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = ev_ipv6.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53BB07528B36004F8947 = {
+                       children = (
+                               159D53BE07528B36004F8947,
+                               158AD85B0754E38F00124717,
+                               159D53BC07528B36004F8947,
+                               159D53BD07528B36004F8947,
+                       );
+                       isa = PBXGroup;
+                       name = Kicker;
+                       path = Plugins/Kicker;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53BC07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Kicker.xml;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53BD07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.script.sh;
+                       path = "enable-network";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53BE07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = kicker.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C007528B36004F8947 = {
+                       children = (
+                               159D53C107528B36004F8947,
+                               158AD8C00754E3EF00124717,
+                       );
+                       isa = PBXGroup;
+                       name = LinkConfiguration;
+                       path = Plugins/LinkConfiguration;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C107528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = linkconfig.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C207528B36004F8947 = {
+                       children = (
+                               159D53C307528B36004F8947,
+                               158AD9100754E40E00124717,
+                       );
+                       isa = PBXGroup;
+                       name = PreferencesMonitor;
+                       path = Plugins/PreferencesMonitor;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C307528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = prefsmon.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C407528B36004F8947 = {
+                       children = (
+                               159D53C507528B36004F8947,
+                               159D53C607528B36004F8947,
+                               159D53C707528B36004F8947,
+                               15FD73970754DE49001CC321,
+                       );
+                       isa = PBXGroup;
+                       name = ATconfig;
+                       path = Plugins/ATconfig;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C507528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = cfManager.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C607528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = cfManager.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C707528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = atconfig.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53C907528B36004F8947 = {
+                       children = (
+                               159D53CA07528B36004F8947,
+                               159D53CB07528B36004F8947,
+                       );
+                       isa = PBXGroup;
+                       name = common;
+                       path = Plugins/common;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53CA07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = cache.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53CB07528B36004F8947 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = cache.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               159D53D007528BDA004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D540A07528D3B004F8947,
+                               159D540C07528DAA004F8947,
+                               159D540E07528DAE004F8947,
+                               159D541007528DB1004F8947,
+                               159D541207528DB3004F8947,
+                               159D541407528DB5004F8947,
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53D107528BDA004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D540907528D3A004F8947,
+                               159D540B07528DA9004F8947,
+                               159D540D07528DAE004F8947,
+                               159D540F07528DB0004F8947,
+                               159D541107528DB2004F8947,
+                               159D541307528DB5004F8947,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53D207528BDA004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53D307528BDA004F8947 = {
+                       buildPhases = (
+                               159D53D007528BDA004F8947,
+                               159D53D107528BDA004F8947,
+                               159D53D207528BDA004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               HEADER_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = KernelEventMonitor;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = KernelEventMonitor;
+                       productName = KernelEventMonitor;
+                       productReference = 159D53D407528BDA004F8947;
+                       productType = "com.apple.product-type.library.static";
+               };
+               159D53D407528BDA004F8947 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libKernelEventMonitor.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               159D53DA07528C2E004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53DB07528C2E004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D541507528DDE004F8947,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53DC07528C2E004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53DD07528C2E004F8947 = {
+                       buildPhases = (
+                               159D53DA07528C2E004F8947,
+                               159D53DB07528C2E004F8947,
+                               159D53DC07528C2E004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = Kicker;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = Kicker;
+                       productName = Kicker;
+                       productReference = 159D53DE07528C2E004F8947;
+                       productType = "com.apple.product-type.library.static";
+               };
+               159D53DE07528C2E004F8947 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libKicker.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               159D53E107528C4A004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53E207528C4A004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D541607528DF1004F8947,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53E307528C4A004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53E407528C4A004F8947 = {
+                       buildPhases = (
+                               159D53E107528C4A004F8947,
+                               159D53E207528C4A004F8947,
+                               159D53E307528C4A004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = InterfaceNamer;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = InterfaceNamer;
+                       productName = InterfaceNamer;
+                       productReference = 159D53E507528C4A004F8947;
+                       productType = "com.apple.product-type.library.static";
+               };
+               159D53E507528C4A004F8947 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libInterfaceNamer.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               159D53E807528C61004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53E907528C61004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D541707528E05004F8947,
+                               159D541807528E09004F8947,
+                               154361E00752C81800A8EC6C,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53EA07528C61004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53EB07528C61004F8947 = {
+                       buildPhases = (
+                               159D53E807528C61004F8947,
+                               159D53E907528C61004F8947,
+                               159D53EA07528C61004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = IPMonitor;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = IPMonitor;
+                       productName = IPMonitor;
+                       productReference = 159D53EC07528C61004F8947;
+                       productType = "com.apple.product-type.library.static";
+               };
+               159D53EC07528C61004F8947 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libIPMonitor.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               159D53EF07528C79004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53F007528C79004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D541B07528E4A004F8947,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53F107528C79004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53F207528C79004F8947 = {
+                       buildPhases = (
+                               159D53EF07528C79004F8947,
+                               159D53F007528C79004F8947,
+                               159D53F107528C79004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = LinkConfiguration;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = LinkConfiguration;
+                       productName = LinkConfiguration;
+                       productReference = 159D53F307528C79004F8947;
+                       productType = "com.apple.product-type.library.static";
+               };
+               159D53F307528C79004F8947 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libLinkConfiguration.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               159D53F607528C95004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53F707528C95004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D541C07528E58004F8947,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53F807528C95004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D53F907528C95004F8947 = {
+                       buildPhases = (
+                               159D53F607528C95004F8947,
+                               159D53F707528C95004F8947,
+                               159D53F807528C95004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = PreferencesMonitor;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = PreferencesMonitor;
+                       productName = PreferencesMonitor;
+                       productReference = 159D53FA07528C95004F8947;
+                       productType = "com.apple.product-type.library.static";
+               };
+               159D53FA07528C95004F8947 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libPreferencesMonitor.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               159D540907528D3A004F8947 = {
+                       fileRef = 159D53CA07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D540A07528D3B004F8947 = {
+                       fileRef = 159D53CB07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D540B07528DA9004F8947 = {
+                       fileRef = 159D53B907528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D540C07528DAA004F8947 = {
+                       fileRef = 159D53B607528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D540D07528DAE004F8947 = {
+                       fileRef = 159D53B107528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D540E07528DAE004F8947 = {
+                       fileRef = 159D53B207528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D540F07528DB0004F8947 = {
+                       fileRef = 159D53B307528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541007528DB1004F8947 = {
+                       fileRef = 159D53B807528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541107528DB2004F8947 = {
+                       fileRef = 159D53B407528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541207528DB3004F8947 = {
+                       fileRef = 159D53BA07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541307528DB5004F8947 = {
+                       fileRef = 159D53B007528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541407528DB5004F8947 = {
+                       fileRef = 159D53B707528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541507528DDE004F8947 = {
+                       fileRef = 159D53BE07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541607528DF1004F8947 = {
+                       fileRef = 159D53AE07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541707528E05004F8947 = {
+                       fileRef = 159D53A707528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541807528E09004F8947 = {
+                       fileRef = 159D53AA07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541B07528E4A004F8947 = {
+                       fileRef = 159D53C107528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D541C07528E58004F8947 = {
+                       fileRef = 159D53C307528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D542007528E7C004F8947 = {
+                       buildPhases = (
+                       );
+                       buildSettings = {
+                               PRODUCT_NAME = Plugins;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                               15DAD5740759115F0084A6ED,
+                               159D542807528E85004F8947,
+                               158AD9860754E72500124717,
+                               159D542607528E85004F8947,
+                               158AD9880754E72500124717,
+                               15828B070753B77E00AD4710,
+                               159D542207528E85004F8947,
+                               159D542407528E85004F8947,
+                               158AD98A0754E72500124717,
+                               159D542A07528E85004F8947,
+                               158AD98C0754E72500124717,
+                               159D542C07528E85004F8947,
+                               158AD98E0754E72500124717,
+                       );
+                       isa = PBXAggregateTarget;
+                       name = configd_plugins;
+                       productName = Plugins;
+               };
+               159D542107528E85004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D53D307528BDA004F8947;
+                       remoteInfo = KernelEventMonitor;
+               };
+               159D542207528E85004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D53D307528BDA004F8947;
+                       targetProxy = 159D542107528E85004F8947;
+               };
+               159D542307528E85004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D53DD07528C2E004F8947;
+                       remoteInfo = Kicker;
+               };
+               159D542407528E85004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D53DD07528C2E004F8947;
+                       targetProxy = 159D542307528E85004F8947;
+               };
+               159D542507528E85004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D53E407528C4A004F8947;
+                       remoteInfo = InterfaceNamer;
+               };
+               159D542607528E85004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D53E407528C4A004F8947;
+                       targetProxy = 159D542507528E85004F8947;
+               };
+               159D542707528E85004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D53EB07528C61004F8947;
+                       remoteInfo = IPMonitor;
+               };
+               159D542807528E85004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D53EB07528C61004F8947;
+                       targetProxy = 159D542707528E85004F8947;
+               };
+               159D542907528E85004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D53F207528C79004F8947;
+                       remoteInfo = LinkConfiguration;
+               };
+               159D542A07528E85004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D53F207528C79004F8947;
+                       targetProxy = 159D542907528E85004F8947;
+               };
+               159D542B07528E85004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D53F907528C95004F8947;
+                       remoteInfo = PreferencesMonitor;
+               };
+               159D542C07528E85004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D53F907528C95004F8947;
+                       targetProxy = 159D542B07528E85004F8947;
+               };
+               159D542D07529008004F8947 = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 159D542007528E7C004F8947;
+                       remoteInfo = Plugins;
+               };
+               159D542E07529008004F8947 = {
+                       isa = PBXTargetDependency;
+                       target = 159D542007528E7C004F8947;
+                       targetProxy = 159D542D07529008004F8947;
+               };
+               159D549F07529FFF004F8947 = {
+                       buildPhases = (
+                               159D54A307529FFF004F8947,
+                               159D54AB07529FFF004F8947,
+                               159D54CA07529FFF004F8947,
+                               159D54D407529FFF004F8947,
+                               159D54D507529FFF004F8947,
+                               159D54D707529FFF004F8947,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               CURRENT_PROJECT_VERSION = 130;
+                               DEAD_CODE_STRIPPING = YES;
+                               FRAMEWORK_SEARCH_PATHS = "$(SYMROOT)";
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/sbin;
+                               LIBRARY_SEARCH_PATHS = "$(SYMROOT) /usr/local/lib/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               OTHER_LDFLAGS = "-prebind_all_twolevel_modules";
+                               PRODUCT_NAME = configd;
+                               STRIPFLAGS = "-S";
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = configd;
+                       productInstallPath = /usr/sbin;
+                       productName = "configd (Tool)";
+                       productReference = 159D54D907529FFF004F8947;
+                       productType = "com.apple.product-type.tool";
+               };
+               159D54A307529FFF004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D54A407529FFF004F8947,
+                               159D54A507529FFF004F8947,
+                               159D54A607529FFF004F8947,
+                               159D54A707529FFF004F8947,
+                               159D54A807529FFF004F8947,
+                               159D54A907529FFF004F8947,
+                               159D54AA07529FFF004F8947,
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D54A407529FFF004F8947 = {
+                       fileRef = 15CB69CF05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54A507529FFF004F8947 = {
+                       fileRef = 15CB69D105C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54A607529FFF004F8947 = {
+                       fileRef = 15CB69D305C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54A707529FFF004F8947 = {
+                       fileRef = 15CB69D505C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54A807529FFF004F8947 = {
+                       fileRef = 15CB69D705C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54A907529FFF004F8947 = {
+                       fileRef = 15CB69D905C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54AA07529FFF004F8947 = {
+                       fileRef = 15CB69DB05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54AB07529FFF004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D54AC07529FFF004F8947,
+                               159D54AD07529FFF004F8947,
+                               159D54AE07529FFF004F8947,
+                               159D54AF07529FFF004F8947,
+                               159D54B007529FFF004F8947,
+                               159D54B107529FFF004F8947,
+                               159D54B207529FFF004F8947,
+                               159D54B307529FFF004F8947,
+                               159D54B407529FFF004F8947,
+                               159D54B507529FFF004F8947,
+                               159D54B607529FFF004F8947,
+                               159D54B707529FFF004F8947,
+                               159D54B807529FFF004F8947,
+                               159D54B907529FFF004F8947,
+                               159D54BA07529FFF004F8947,
+                               159D54BB07529FFF004F8947,
+                               159D54BC07529FFF004F8947,
+                               159D54BD07529FFF004F8947,
+                               159D54BE07529FFF004F8947,
+                               159D54BF07529FFF004F8947,
+                               159D54C007529FFF004F8947,
+                               159D54C107529FFF004F8947,
+                               159D54C207529FFF004F8947,
+                               159D54C307529FFF004F8947,
+                               159D54C407529FFF004F8947,
+                               159D54C507529FFF004F8947,
+                               159D54C607529FFF004F8947,
+                               159D54C707529FFF004F8947,
+                               159D54C807529FFF004F8947,
+                               159D54C907529FFF004F8947,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D54AC07529FFF004F8947 = {
+                       fileRef = 15CB69E005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54AD07529FFF004F8947 = {
+                       fileRef = 15CB69E205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54AE07529FFF004F8947 = {
+                       fileRef = 15CB69E405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54AF07529FFF004F8947 = {
+                       fileRef = 15CB69E605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B007529FFF004F8947 = {
+                       fileRef = 15CB69E805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B107529FFF004F8947 = {
+                       fileRef = 15CB69EA05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B207529FFF004F8947 = {
+                       fileRef = 15CB69EC05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B307529FFF004F8947 = {
+                       fileRef = 15CB69F005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B407529FFF004F8947 = {
+                       fileRef = 15CB69F205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B507529FFF004F8947 = {
+                       fileRef = 15CB69F405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B607529FFF004F8947 = {
+                       fileRef = 15CB69F605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B707529FFF004F8947 = {
+                       fileRef = 15CB69F805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B807529FFF004F8947 = {
+                       fileRef = 15CB69FA05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54B907529FFF004F8947 = {
+                       fileRef = 15CB69FE05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54BA07529FFF004F8947 = {
+                       fileRef = 15CB6A0005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54BB07529FFF004F8947 = {
+                       fileRef = 15CB6A0205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54BC07529FFF004F8947 = {
+                       fileRef = 15CB6A0405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54BD07529FFF004F8947 = {
+                       fileRef = 15CB6A0605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54BE07529FFF004F8947 = {
+                       fileRef = 15CB6A0805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54BF07529FFF004F8947 = {
+                       fileRef = 15CB6A0A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C007529FFF004F8947 = {
+                       fileRef = 15CB6A0C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C107529FFF004F8947 = {
+                       fileRef = 15CB6A0E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C207529FFF004F8947 = {
+                       fileRef = 15CB6A1005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C307529FFF004F8947 = {
+                       fileRef = 15CB6A1205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C407529FFF004F8947 = {
+                       fileRef = 15CB6A1405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C507529FFF004F8947 = {
+                       fileRef = 15CB6A1605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               159D54C607529FFF004F8947 = {
+                       fileRef = 15CB69BE05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Server,
+                               );
+                       };
+               };
+               159D54C707529FFF004F8947 = {
+                       fileRef = 15B73F0B05FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54C807529FFF004F8947 = {
+                       fileRef = 15B73F0D05FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54C907529FFF004F8947 = {
+                       fileRef = 15FCAAD005FD0EBF00CB79E6;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Server,
+                               );
+                       };
+               };
+               159D54CA07529FFF004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               159D54CC07529FFF004F8947,
+                               1523F6F1075A36F70066F0B2,
+                               1543636B0752D03C00A8EC6C,
+                               159D54CD07529FFF004F8947,
+                               1523F715075A376B0066F0B2,
+                               159D54CE07529FFF004F8947,
+                               159D54CF07529FFF004F8947,
+                               159D54D007529FFF004F8947,
+                               159D54D107529FFF004F8947,
+                               159D54D207529FFF004F8947,
+                               159D54D307529FFF004F8947,
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D54CC07529FFF004F8947 = {
+                       fileRef = 15CB6A6F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54CD07529FFF004F8947 = {
+                       fileRef = 15CB6A7405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54CE07529FFF004F8947 = {
+                       fileRef = 159D53D407528BDA004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54CF07529FFF004F8947 = {
+                       fileRef = 159D53DE07528C2E004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D007529FFF004F8947 = {
+                       fileRef = 159D53E507528C4A004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D107529FFF004F8947 = {
+                       fileRef = 159D53EC07528C61004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D207529FFF004F8947 = {
+                       fileRef = 159D53F307528C79004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D307529FFF004F8947 = {
+                       fileRef = 159D53FA07528C95004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D407529FFF004F8947 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXRezBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D54D507529FFF004F8947 = {
+                       buildActionMask = 12;
+                       dstPath = /usr/share/man/man8;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               159D54D607529FFF004F8947,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D54D607529FFF004F8947 = {
+                       fileRef = 15CB6A2005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D707529FFF004F8947 = {
+                       buildActionMask = 2147483647;
+                       dstPath = /private/etc/mach_init.d;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               159D54D807529FFF004F8947,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               159D54D807529FFF004F8947 = {
+                       fileRef = 15CB6A1F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               159D54D907529FFF004F8947 = {
+                       explicitFileType = "compiled.mach-o.executable";
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = configd;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15A509A306C2518F001F0AB7 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = net.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15A509A406C2518F001F0AB7 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = net.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A380670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCNetworkConfiguration.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A390670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkConfigurationInternal.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A3A0670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCNetworkConfigurationInternal.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A3B0670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkInterface.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A3C0670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkProtocol.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A3D0670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkService.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15AD7A3E0670A85900BFE03C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkSet.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B6861D0678B61900FF4023 = {
+                       children = (
+                               15B686220678B65C00FF4023,
+                               1577253606EFBF3100D7B52B,
+                               15CFC229068B222F00123568,
+                       );
+                       isa = PBXGroup;
+                       name = "Supporting Files";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B686220678B65C00FF4023 = {
+                       explicitFileType = text.xml;
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       path = NetworkConfiguration.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B73F0805FD1B670096477F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = dnsinfo_copy.c;
+                       path = dnsinfo/dnsinfo_copy.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B73F0905FD1B670096477F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dnsinfo.h;
+                       path = dnsinfo/dnsinfo.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B73F0B05FD1B670096477F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = dnsinfo_private.c;
+                       path = dnsinfo/dnsinfo_private.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B73F0C05FD1B670096477F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dnsinfo_private.h;
+                       path = dnsinfo/dnsinfo_private.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B73F0D05FD1B670096477F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = dnsinfo_server.c;
+                       path = dnsinfo/dnsinfo_server.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15B73F0E05FD1B670096477F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dnsinfo_server.h;
+                       path = dnsinfo/dnsinfo_server.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB68FC05C072220099E85F = {
+                       children = (
+                               15CB6A8605C072500099E85F,
+                               15CB6A8305C072410099E85F,
+                               1582B36B05FD1A4D009C2750,
+                               15CB690705C0722A0099E85F,
+                               15CB69C205C0722B0099E85F,
+                               15CB6A2205C0722B0099E85F,
+                               15CB6A3705C0722B0099E85F,
+                               159D53A207528B06004F8947,
+                               1514D77D05C08AB700757DC9,
+                               15CB6A6E05C0722B0099E85F,
+                               15CB690F05C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = configd;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB68FE05C072220099E85F = {
+                       buildSettings = {
+                               COPY_PHASE_STRIP = NO;
+                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+                               MACOSX_DEPLOYMENT_TARGET = 10.4;
+                       };
+                       isa = PBXBuildStyle;
+                       name = Development;
+               };
+               15CB68FF05C072220099E85F = {
+                       buildSettings = {
+                               COPY_PHASE_STRIP = YES;
+                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+                               MACOSX_DEPLOYMENT_TARGET = 10.4;
+                       };
+                       isa = PBXBuildStyle;
+                       name = Deployment;
+               };
+               15CB690005C0722A0099E85F = {
+                       buildPhases = (
+                       );
+                       buildSettings = {
+                               PRODUCT_NAME = "configd (Aggregate)";
+                       };
+                       dependencies = (
+                               157BB8C40759244B0025DA7A,
+                               159D542E07529008004F8947,
+                               1558480F07550DD00046C2E9,
+                       );
+                       isa = PBXAggregateTarget;
+                       name = All;
+                       productName = "configd (Aggregate)";
+               };
+               15CB690505C0722A0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = preferences.xml;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB690705C0722A0099E85F = {
+                       children = (
+                               15CB691205C0722B0099E85F,
+                               15CB694F05C0722B0099E85F,
+                               15B6861D0678B61900FF4023,
+                       );
+                       isa = PBXGroup;
+                       name = SystemConfiguration;
+                       path = SystemConfiguration.fproj;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB690F05C0722B0099E85F = {
+                       children = (
+                               158ADBFD0754ECB100124717,
+                               158ADCA60754ECC800124717,
+                               1558476A0754FDCD0046C2E9,
+                               1558481D07550EC10046C2E9,
+                               15DAD5EE075913CE0084A6ED,
+                               15DAD6C807591A1A0084A6ED,
+                               15481BF8075A2B3900B32F56,
+                       );
+                       isa = PBXGroup;
+                       name = Products;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691205C0722B0099E85F = {
+                       children = (
+                               15CB691305C0722B0099E85F,
+                               15CB691705C0722B0099E85F,
+                               15CB691B05C0722B0099E85F,
+                               15CB691D05C0722B0099E85F,
+                               15CB691F05C0722B0099E85F,
+                               15CB692105C0722B0099E85F,
+                               15CB693F05C0722B0099E85F,
+                               15CB692305C0722B0099E85F,
+                               15CB692505C0722B0099E85F,
+                               15CB692705C0722B0099E85F,
+                               15CB692905C0722B0099E85F,
+                               15CB692B05C0722B0099E85F,
+                               15CB692D05C0722B0099E85F,
+                               15CB692F05C0722B0099E85F,
+                               151BDA2B05D9E28B00657BC7,
+                               154CF3F307E1EA4D00D8302E,
+                               15CB693105C0722B0099E85F,
+                               156BD6BB07E0DFA9008698FF,
+                               15CB691505C0722B0099E85F,
+                               15AD7A380670A85900BFE03C,
+                               15AD7A3A0670A85900BFE03C,
+                               15CB693305C0722B0099E85F,
+                               15CB693505C0722B0099E85F,
+                               15CB693705C0722B0099E85F,
+                               15CB693905C0722B0099E85F,
+                               9EE943F406AF409B00772EB5,
+                               9EE943F506AF409B00772EB5,
+                               15CB694505C0722B0099E85F,
+                               15CB693D05C0722B0099E85F,
+                               15CB694705C0722B0099E85F,
+                               15CB694B05C0722B0099E85F,
+                               15CB694D05C0722B0099E85F,
+                               15CB694905C0722B0099E85F,
+                               15CB694305C0722B0099E85F,
+                               15CB694105C0722B0099E85F,
+                               23C1E2BE062DD5DB00835B54,
+                       );
+                       isa = PBXGroup;
+                       name = Headers;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691305C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SystemConfiguration.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691505C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691705C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDPlugin.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691B05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStoreInternal.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691D05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStore.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB691F05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStorePrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692105C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStoreKey.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692305C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStoreCopySpecific.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692505C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStoreCopySpecificPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692705C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStoreSetSpecificPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692905C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferencesInternal.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692B05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferences.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692D05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferencesPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB692F05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferencesPath.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693105C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCPreferencesSetSpecific.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693305C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCNetwork.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693505C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCNetworkConnection.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693705C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCNetworkReachability.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693905C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCValidation.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693D05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = DHCPClientPreferences.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB693F05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = SCDynamicStoreCopyDHCPInfo.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694105C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = moh_msg.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694305C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = moh.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694505C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = DeviceOnHold.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694705C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = LinkConfiguration.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694905C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = dy_framework.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694B05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = VLANConfiguration.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694D05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = VLANConfigurationPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB694F05C0722B0099E85F = {
+                       children = (
+                               150607BD075A00A200B147BA,
+                               150607DE075A00A300B147BA,
+                               15CB695005C0722B0099E85F,
+                               15CB695205C0722B0099E85F,
+                               15CB695405C0722B0099E85F,
+                               15CB695605C0722B0099E85F,
+                               15CB695805C0722B0099E85F,
+                               15CB695A05C0722B0099E85F,
+                               15CB695C05C0722B0099E85F,
+                               15CB695E05C0722B0099E85F,
+                               15CB696005C0722B0099E85F,
+                               15CB696405C0722B0099E85F,
+                               15CB696605C0722B0099E85F,
+                               15CB696805C0722B0099E85F,
+                               15CB696A05C0722B0099E85F,
+                               15CB696C05C0722B0099E85F,
+                               15CB696E05C0722B0099E85F,
+                               15CB697005C0722B0099E85F,
+                               15CB697205C0722B0099E85F,
+                               15CB697405C0722B0099E85F,
+                               15CB697605C0722B0099E85F,
+                               15CB697805C0722B0099E85F,
+                               15CB697A05C0722B0099E85F,
+                               15CB697C05C0722B0099E85F,
+                               15CB697E05C0722B0099E85F,
+                               15CB698005C0722B0099E85F,
+                               15CB698205C0722B0099E85F,
+                               15CB698405C0722B0099E85F,
+                               15CB698605C0722B0099E85F,
+                               15CB698805C0722B0099E85F,
+                               15CB698A05C0722B0099E85F,
+                               15CB698C05C0722B0099E85F,
+                               15CB698E05C0722B0099E85F,
+                               15CB699005C0722B0099E85F,
+                               15CB699205C0722B0099E85F,
+                               15CB699405C0722B0099E85F,
+                               15CB699605C0722B0099E85F,
+                               15CB699805C0722B0099E85F,
+                               15CB699A05C0722B0099E85F,
+                               151BDA5D05D9E2ED00657BC7,
+                               15AD7A390670A85900BFE03C,
+                               15AD7A3B0670A85900BFE03C,
+                               15AD7A3C0670A85900BFE03C,
+                               15AD7A3D0670A85900BFE03C,
+                               15AD7A3E0670A85900BFE03C,
+                               15CB699C05C0722B0099E85F,
+                               15CB699E05C0722B0099E85F,
+                               15CB69A005C0722B0099E85F,
+                               15CB69A205C0722B0099E85F,
+                               15CB69A405C0722B0099E85F,
+                               15CB69A605C0722B0099E85F,
+                               15CB69A805C0722B0099E85F,
+                               15CB69AC05C0722B0099E85F,
+                               15CB69AE05C0722B0099E85F,
+                               15CB69B005C0722B0099E85F,
+                               15CB69B205C0722B0099E85F,
+                               15CB69B405C0722B0099E85F,
+                               9EE943F306AF409B00772EB5,
+                               15CB69B605C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = Sources;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCD.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDKeys.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDPrivate.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDPlugin.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDOpen.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDLock.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDUnlock.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB695E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDList.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDAdd.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDGet.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDSet.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDRemove.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDTouch.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotify.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB696E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierSetKeys.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierAdd.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierRemove.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierGetChanges.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierWait.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierInformViaCallback.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierInformViaMachPort.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierInformViaFD.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB697E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierInformViaSignal.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDNotifierCancel.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDSnapshot.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCP.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698605C0722B0099E85F = {
+                       indentWidth = 8;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPOpen.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+                       tabWidth = 8;
+               };
+               15CB698805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPLock.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPUnlock.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPList.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB698E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPGet.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPAdd.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPSet.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPRemove.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPCommit.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPApply.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCPPath.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDConsoleUser.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB699E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCDHostName.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69A005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCLocation.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69A205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetwork.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69A405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkConnection.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69A605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCNetworkReachability.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69A805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = SCProxies.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69AC05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = DHCP.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69AE05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = moh.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69B005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = DeviceOnHold.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69B205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = LinkConfiguration.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69B405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = dy_framework.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69B605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = VLANConfiguration.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69BE05C0722B0099E85F = {
+                       explicitFileType = sourcecode.mig;
+                       isa = PBXFileReference;
+                       name = config.defs;
+                       path = SystemConfiguration.fproj/config.defs;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69BF05C0722B0099E85F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = genSCPreferences.c;
+                       path = SystemConfiguration.fproj/genSCPreferences.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69C205C0722B0099E85F = {
+                       children = (
+                               15CB69CE05C0722B0099E85F,
+                               15CB69DF05C0722B0099E85F,
+                               15CB6A1805C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = configd;
+                       path = configd.tproj;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69CE05C0722B0099E85F = {
+                       children = (
+                               15CB69CF05C0722B0099E85F,
+                               15CB69D105C0722B0099E85F,
+                               15CB69D305C0722B0099E85F,
+                               15CB69D505C0722B0099E85F,
+                               15CB69D705C0722B0099E85F,
+                               15CB69D905C0722B0099E85F,
+                               15CB69DB05C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = Headers;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69CF05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = configd.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69D105C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = _SCD.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69D305C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = configd_server.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69D505C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = notify_server.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69D705C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = plugin_support.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69D905C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = session.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69DB05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = pattern.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69DF05C0722B0099E85F = {
+                       children = (
+                               15CB69E005C0722B0099E85F,
+                               15CB69E205C0722B0099E85F,
+                               15CB69E405C0722B0099E85F,
+                               15CB69E605C0722B0099E85F,
+                               15CB69E805C0722B0099E85F,
+                               15CB69EA05C0722B0099E85F,
+                               15CB69EC05C0722B0099E85F,
+                               15CB69F005C0722B0099E85F,
+                               15CB69F205C0722B0099E85F,
+                               15CB69F405C0722B0099E85F,
+                               15CB69F605C0722B0099E85F,
+                               15CB69F805C0722B0099E85F,
+                               15CB69FA05C0722B0099E85F,
+                               15CB69FE05C0722B0099E85F,
+                               15CB6A0005C0722B0099E85F,
+                               15CB6A0205C0722B0099E85F,
+                               15CB6A0405C0722B0099E85F,
+                               15CB6A0605C0722B0099E85F,
+                               15CB6A0805C0722B0099E85F,
+                               15CB6A0A05C0722B0099E85F,
+                               15CB6A0C05C0722B0099E85F,
+                               15CB6A0E05C0722B0099E85F,
+                               15CB6A1005C0722B0099E85F,
+                               15CB6A1205C0722B0099E85F,
+                               15CB6A1405C0722B0099E85F,
+                               15CB6A1605C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = Sources;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69E005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = configd.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69E205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _SCD.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69E405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = configd_server.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69E605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = notify_server.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69E805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = plugin_support.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69EA05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = session.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69EC05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = pattern.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69F005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configopen.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69F205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configclose.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69F405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configlock.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69F605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configunlock.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69F805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configlist.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69FA05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configadd.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB69FE05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configget.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configset.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configremove.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _configtouch.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _confignotify.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifyadd.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifyremove.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifychanges.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A0E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifyviaport.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A1005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifyviafd.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A1205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifyviasignal.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A1405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _notifycancel.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A1605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = _snapshot.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A1805C0722B0099E85F = {
+                       children = (
+                               15CB6A1F05C0722B0099E85F,
+                               15CB6A2005C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = "Supporting Files";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A1F05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = configd.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A2005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = text;
+                       path = configd.8;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A2205C0722B0099E85F = {
+                       children = (
+                               15CB6A2D05C0722B0099E85F,
+                               15CB6A3005C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = scselect;
+                       path = scselect.tproj;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A2D05C0722B0099E85F = {
+                       children = (
+                               15CB6A2E05C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = Sources;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A2E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = scselect.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A3005C0722B0099E85F = {
+                       children = (
+                               15CB6A3605C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = "Supporting Files";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A3605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = text;
+                       path = scselect.8;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A3705C0722B0099E85F = {
+                       children = (
+                               15CB6A4205C0722B0099E85F,
+                               15CB6A5305C0722B0099E85F,
+                               15CB6A6405C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = scutil;
+                       path = scutil.tproj;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4205C0722B0099E85F = {
+                       children = (
+                               15CB6A4305C0722B0099E85F,
+                               15CB6A4505C0722B0099E85F,
+                               15CB6A4705C0722B0099E85F,
+                               15CB6A4905C0722B0099E85F,
+                               15CB6A4B05C0722B0099E85F,
+                               15CB6A4D05C0722B0099E85F,
+                               15CB6A4F05C0722B0099E85F,
+                               15CB6A5105C0722B0099E85F,
+                               15A509A406C2518F001F0AB7,
+                               15DC34680711D49400A3311C,
+                               15DC346A0711D49400A3311C,
+                               15DC346C0711D49400A3311C,
+                               15DC346E0711D49400A3311C,
+                       );
+                       isa = PBXGroup;
+                       name = Headers;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4305C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = scutil.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4505C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = commands.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4705C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = dictionary.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4905C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = session.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4B05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = cache.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4D05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = notifications.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A4F05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = tests.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5105C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = prefs.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5305C0722B0099E85F = {
+                       children = (
+                               15CB6A5405C0722B0099E85F,
+                               15CB6A5605C0722B0099E85F,
+                               15CB6A5805C0722B0099E85F,
+                               15CB6A5A05C0722B0099E85F,
+                               15CB6A5C05C0722B0099E85F,
+                               15CB6A5E05C0722B0099E85F,
+                               15CB6A6005C0722B0099E85F,
+                               15CB6A6205C0722B0099E85F,
+                               15A509A306C2518F001F0AB7,
+                               15DC34670711D49400A3311C,
+                               15DC34690711D49400A3311C,
+                               15DC346B0711D49400A3311C,
+                               15DC346D0711D49400A3311C,
+                       );
+                       isa = PBXGroup;
+                       name = Sources;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = scutil.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5605C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = commands.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5805C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = dictionary.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = session.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5C05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = cache.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A5E05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = notifications.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A6005C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = tests.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A6205C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = prefs.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A6405C0722B0099E85F = {
+                       children = (
+                               15CB6A6A05C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = "Supporting Files";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A6A05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = text;
+                       path = scutil.8;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A6E05C0722B0099E85F = {
+                       children = (
+                               158AD9F80754EA2F00124717,
+                               15CB6A6F05C0722B0099E85F,
+                               1543636A0752D03C00A8EC6C,
+                               158ADABB0754EAAE00124717,
+                               15CB6A7405C0722B0099E85F,
+                               152CEED0070CF6640050F23C,
+                       );
+                       isa = PBXGroup;
+                       name = "External Frameworks and Libraries";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A6F05C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = wrapper.framework;
+                       name = CoreFoundation.framework;
+                       path = /System/Library/Frameworks/CoreFoundation.framework;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               15CB6A7405C0722B0099E85F = {
+                       isa = PBXFileReference;
+                       lastKnownFileType = "compiled.mach-o.dylib";
+                       name = libobjc.dylib;
+                       path = /usr/lib/libobjc.A.dylib;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               15CB6A7705C0722B0099E85F = {
+                       buildSettings = {
+                               CURRENT_PROJECT_VERSION = 130;
+                               FRAMEWORK_SEARCH_PATHS = "";
+                               HEADER_SEARCH_PATHS = "";
+                               INSTALL_GROUP = wheel;
+                               INSTALL_MODE_FLAG = "u+s,ugo-w,o+rX";
+                               INSTALL_OWNER = root;
+                               INSTALL_PATH = /usr/sbin;
+                               LIBRARY_SEARCH_PATHS = "";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               OTHER_LDFLAGS = "-dead_strip";
+                               OTHER_REZFLAGS = "";
+                               PRODUCT_NAME = scselect;
+                               REZ_EXECUTABLE = YES;
+                               SECTORDER_FLAGS = "";
+                               STRIPFLAGS = "-S";
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wall -Wno-four-char-constants -Wno-unknown-pragmas";
+                       };
+                       buildStyles = (
+                               15CB68FE05C072220099E85F,
+                               15CB68FF05C072220099E85F,
+                       );
+                       hasScannedForEncodings = 1;
+                       isa = PBXProject;
+                       mainGroup = 15CB68FC05C072220099E85F;
+                       productRefGroup = 15CB690F05C0722B0099E85F;
+                       projectDirPath = "";
+                       targets = (
+                               15CB690005C0722A0099E85F,
+                               157BB8AE075924360025DA7A,
+                               159D542007528E7C004F8947,
+                               155847FA07550D210046C2E9,
+                               15DAD5DF075913CE0084A6ED,
+                               15481BF7075A2B3900B32F56,
+                               15DAD63F07591A1A0084A6ED,
+                               159D549F07529FFF004F8947,
+                               1558481207550EC10046C2E9,
+                               155847430754FDCD0046C2E9,
+                               15FD733A0754DBDA001CC321,
+                               15FD731E0754DB9F001CC321,
+                               159D53EB07528C61004F8947,
+                               15FD72A10754DA4C001CC321,
+                               159D53E407528C4A004F8947,
+                               15FD72930754DA2B001CC321,
+                               159D53D307528BDA004F8947,
+                               15828AE60753B5F900AD4710,
+                               159D53DD07528C2E004F8947,
+                               15FD70FF0754D627001CC321,
+                               159D53F207528C79004F8947,
+                               15FD72B10754DA69001CC321,
+                               159D53F907528C95004F8947,
+                               15FD72C50754DA7E001CC321,
+                       );
+               };
+               15CB6A8305C072410099E85F = {
+                       children = (
+                               15CB69BF05C0722B0099E85F,
+                       );
+                       isa = PBXGroup;
+                       name = Schema;
+                       path = "";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CB6A8605C072500099E85F = {
+                       children = (
+                               15CB69BE05C0722B0099E85F,
+                               1514D76D05C08A5F00757DC9,
+                               15FCAAD005FD0EBF00CB79E6,
+                               15FCAACF05FD0EBF00CB79E6,
+                               23C1E2B8062DD45900835B54,
+                               23C1E2B4062DD2C700835B54,
+                       );
+                       isa = PBXGroup;
+                       name = MiG;
+                       path = "";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15CFC229068B222F00123568 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.script.sh;
+                       path = "get-mobility-info";
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               15DAD5730759115F0084A6ED = {
+                       containerPortal = 15CB6A7705C0722B0099E85F;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = 15FD731E0754DB9F001CC321;
+                       remoteInfo = ATconfig.bundle;
+               };
+               15DAD5740759115F0084A6ED = {
+                       isa = PBXTargetDependency;
+                       target = 15FD731E0754DB9F001CC321;
+                       targetProxy = 15DAD5730759115F0084A6ED;
+               };
+               15DAD5DF075913CE0084A6ED = {
+                       buildPhases = (
+                               15DAD5E0075913CE0084A6ED,
+                               15DAD5E4075913CE0084A6ED,
+                               15DAD5E9075913CE0084A6ED,
+                               15DAD5EA075913CE0084A6ED,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               INSTALLHDRS_COPY_PHASE = YES;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib;
+                               LIBRARY_STYLE = STATIC;
+                               PRODUCT_NAME = dnsinfo;
+                               SECTORDER_FLAGS = "";
+                               UNSTRIPPED_PRODUCT = YES;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = DNSConfiguration;
+                       productInstallPath = /usr/local/lib;
+                       productName = DNSConfiguration;
+                       productReference = 15DAD5EE075913CE0084A6ED;
+                       productType = "com.apple.product-type.library.static";
+               };
+               15DAD5E0075913CE0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               15DAD5E1075913CE0084A6ED,
+                               15DAD5E2075913CE0084A6ED,
+                               15DAD5E3075913CE0084A6ED,
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD5E1075913CE0084A6ED = {
+                       fileRef = 15B73F0905FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               15DAD5E2075913CE0084A6ED = {
+                       fileRef = 15B73F0C05FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD5E3075913CE0084A6ED = {
+                       fileRef = 1532629006281C9D00B1C10C;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               15DAD5E4075913CE0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               15DAD5E5075913CE0084A6ED,
+                               15DAD5E6075913CE0084A6ED,
+                               15DAD5E7075913CE0084A6ED,
+                               15DAD5E8075913CE0084A6ED,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD5E5075913CE0084A6ED = {
+                       fileRef = 15FCAAD005FD0EBF00CB79E6;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Client,
+                               );
+                       };
+               };
+               15DAD5E6075913CE0084A6ED = {
+                       fileRef = 15B73F0805FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD5E7075913CE0084A6ED = {
+                       fileRef = 15B73F0B05FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD5E8075913CE0084A6ED = {
+                       fileRef = 1521FC5C060F296A003B28F5;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD5E9075913CE0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD5EA075913CE0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXRezBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD5EE075913CE0084A6ED = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libdnsinfo.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15DAD63F07591A1A0084A6ED = {
+                       buildPhases = (
+                               15DAD6AC07591A1A0084A6ED,
+                               15DAD64107591A1A0084A6ED,
+                               15DAD66807591A1A0084A6ED,
+                               15DAD66C07591A1A0084A6ED,
+                               15DAD6AD07591A1A0084A6ED,
+                               15DAD6AF07591A1A0084A6ED,
+                               15DAD6B007591A1A0084A6ED,
+                               15DAD6B107591A1A0084A6ED,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               CURRENT_PROJECT_VERSION = 130;
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               HEADER_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               INFOPLIST_FILE = SystemConfiguration.fproj/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+                               LIBRARY_SEARCH_PATHS = "$(SYMROOT)";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               OTHER_LDFLAGS = "-seg_addr_table $(APPLE_INTERNAL_DEVELOPER_DIR)/seg_addr_table";
+                               PRODUCT_NAME = SystemConfiguration;
+                               SECTORDER_FLAGS = "-sectorder __TEXT __text $(OBJROOT)/SystemConfiguration.order";
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = framework;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = SystemConfiguration.framework;
+                       productInstallPath = "$(SYSTEM_LIBRARY_DIR)/Frameworks";
+                       productName = "SystemConfiguration (Framework)";
+                       productReference = 15DAD6C807591A1A0084A6ED;
+                       productType = "com.apple.product-type.framework";
+               };
+               15DAD64107591A1A0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               1506081A075A00A300B147BA,
+                               15DAD64307591A1A0084A6ED,
+                               15DAD64407591A1A0084A6ED,
+                               15DAD64507591A1A0084A6ED,
+                               15DAD64607591A1A0084A6ED,
+                               15DAD64707591A1A0084A6ED,
+                               15DAD64807591A1A0084A6ED,
+                               15DAD64907591A1A0084A6ED,
+                               15DAD64A07591A1A0084A6ED,
+                               15DAD64B07591A1A0084A6ED,
+                               15DAD64C07591A1A0084A6ED,
+                               15DAD64D07591A1A0084A6ED,
+                               15DAD64E07591A1A0084A6ED,
+                               15DAD64F07591A1A0084A6ED,
+                               15DAD65007591A1A0084A6ED,
+                               15DAD65107591A1A0084A6ED,
+                               15DAD65207591A1A0084A6ED,
+                               15DAD65307591A1A0084A6ED,
+                               15DAD65407591A1A0084A6ED,
+                               15DAD65507591A1A0084A6ED,
+                               15DAD65607591A1A0084A6ED,
+                               15DAD65707591A1A0084A6ED,
+                               15DAD65807591A1A0084A6ED,
+                               15DAD65907591A1A0084A6ED,
+                               15DAD65A07591A1A0084A6ED,
+                               15DAD65B07591A1A0084A6ED,
+                               15DAD65C07591A1A0084A6ED,
+                               15DAD65D07591A1A0084A6ED,
+                               15DAD65E07591A1A0084A6ED,
+                               15DAD65F07591A1A0084A6ED,
+                               15DAD66007591A1A0084A6ED,
+                               15DAD66107591A1A0084A6ED,
+                               15DAD66207591A1A0084A6ED,
+                               15DAD66307591A1A0084A6ED,
+                               15DAD66407591A1A0084A6ED,
+                               15DAD66507591A1A0084A6ED,
+                               15DAD66607591A1A0084A6ED,
+                               15DAD66707591A1A0084A6ED,
+                               156BD6BC07E0DFA9008698FF,
+                               154CF3F407E1EA4D00D8302E,
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD64307591A1A0084A6ED = {
+                       fileRef = 15CB691305C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64407591A1A0084A6ED = {
+                       fileRef = 15CB691505C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD64507591A1A0084A6ED = {
+                       fileRef = 15CB691705C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD64607591A1A0084A6ED = {
+                       fileRef = 15CB691B05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64707591A1A0084A6ED = {
+                       fileRef = 15CB691D05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64807591A1A0084A6ED = {
+                       fileRef = 15CB691F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD64907591A1A0084A6ED = {
+                       fileRef = 15CB692105C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64A07591A1A0084A6ED = {
+                       fileRef = 15CB692305C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64B07591A1A0084A6ED = {
+                       fileRef = 15CB692505C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD64C07591A1A0084A6ED = {
+                       fileRef = 15CB692705C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD64D07591A1A0084A6ED = {
+                       fileRef = 15CB692905C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64E07591A1A0084A6ED = {
+                       fileRef = 15CB692B05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD64F07591A1A0084A6ED = {
+                       fileRef = 15CB692D05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD65007591A1A0084A6ED = {
+                       fileRef = 15CB692F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD65107591A1A0084A6ED = {
+                       fileRef = 15CB693105C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD65207591A1A0084A6ED = {
+                       fileRef = 15AD7A380670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               15DAD65307591A1A0084A6ED = {
+                       fileRef = 15AD7A3A0670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD65407591A1A0084A6ED = {
+                       fileRef = 15CB693305C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD65507591A1A0084A6ED = {
+                       fileRef = 15CB693505C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD65607591A1A0084A6ED = {
+                       fileRef = 15CB693705C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                                       Project,
+                               );
+                       };
+               };
+               15DAD65707591A1A0084A6ED = {
+                       fileRef = 15CB693905C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD65807591A1A0084A6ED = {
+                       fileRef = 15CB693D05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               15DAD65907591A1A0084A6ED = {
+                       fileRef = 15CB693F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               15DAD65A07591A1A0084A6ED = {
+                       fileRef = 15CB694105C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD65B07591A1A0084A6ED = {
+                       fileRef = 15CB694305C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD65C07591A1A0084A6ED = {
+                       fileRef = 15CB694505C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD65D07591A1A0084A6ED = {
+                       fileRef = 15CB694705C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD65E07591A1A0084A6ED = {
+                       fileRef = 15CB694905C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD65F07591A1A0084A6ED = {
+                       fileRef = 15CB694B05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD66007591A1A0084A6ED = {
+                       fileRef = 15CB694D05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Project,
+                                       Private,
+                               );
+                       };
+               };
+               15DAD66107591A1A0084A6ED = {
+                       fileRef = 151BDA2B05D9E28B00657BC7;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD66207591A1A0084A6ED = {
+                       fileRef = 15B73F0905FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66307591A1A0084A6ED = {
+                       fileRef = 15B73F0C05FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66407591A1A0084A6ED = {
+                       fileRef = 23C1E2B4062DD2C700835B54;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66507591A1A0084A6ED = {
+                       fileRef = 23C1E2BE062DD5DB00835B54;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66607591A1A0084A6ED = {
+                       fileRef = 9EE943F406AF409B00772EB5;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD66707591A1A0084A6ED = {
+                       fileRef = 9EE943F506AF409B00772EB5;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Private,
+                               );
+                       };
+               };
+               15DAD66807591A1A0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               15DAD66907591A1A0084A6ED,
+                               15DAD66A07591A1A0084A6ED,
+                               15DAD66B07591A1A0084A6ED,
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD66907591A1A0084A6ED = {
+                       fileRef = 15B686220678B65C00FF4023;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66A07591A1A0084A6ED = {
+                       fileRef = 15CFC229068B222F00123568;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66B07591A1A0084A6ED = {
+                       fileRef = 1577253606EFBF3100D7B52B;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD66C07591A1A0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               15060818075A00A300B147BA,
+                               15DAD66D07591A1A0084A6ED,
+                               15DAD66E07591A1A0084A6ED,
+                               15DAD66F07591A1A0084A6ED,
+                               15DAD67007591A1A0084A6ED,
+                               15DAD67107591A1A0084A6ED,
+                               15DAD67207591A1A0084A6ED,
+                               15DAD67307591A1A0084A6ED,
+                               15DAD67407591A1A0084A6ED,
+                               15DAD67507591A1A0084A6ED,
+                               15DAD67607591A1A0084A6ED,
+                               15DAD67707591A1A0084A6ED,
+                               15DAD67807591A1A0084A6ED,
+                               15DAD67907591A1A0084A6ED,
+                               15DAD67A07591A1A0084A6ED,
+                               15DAD67B07591A1A0084A6ED,
+                               15DAD67C07591A1A0084A6ED,
+                               15DAD67D07591A1A0084A6ED,
+                               15DAD67E07591A1A0084A6ED,
+                               15DAD67F07591A1A0084A6ED,
+                               15DAD68007591A1A0084A6ED,
+                               15DAD68107591A1A0084A6ED,
+                               15DAD68207591A1A0084A6ED,
+                               15DAD68307591A1A0084A6ED,
+                               15DAD68407591A1A0084A6ED,
+                               15DAD68507591A1A0084A6ED,
+                               15DAD68607591A1A0084A6ED,
+                               15DAD68707591A1A0084A6ED,
+                               15DAD68807591A1A0084A6ED,
+                               15DAD68907591A1A0084A6ED,
+                               15DAD68A07591A1A0084A6ED,
+                               15DAD68B07591A1A0084A6ED,
+                               15DAD68C07591A1A0084A6ED,
+                               15DAD68D07591A1A0084A6ED,
+                               15DAD68E07591A1A0084A6ED,
+                               15DAD68F07591A1A0084A6ED,
+                               15DAD69007591A1A0084A6ED,
+                               15DAD69107591A1A0084A6ED,
+                               15DAD69207591A1A0084A6ED,
+                               15DAD69307591A1A0084A6ED,
+                               15DAD69407591A1A0084A6ED,
+                               15DAD69507591A1A0084A6ED,
+                               15DAD69607591A1A0084A6ED,
+                               15DAD69707591A1A0084A6ED,
+                               15DAD69807591A1A0084A6ED,
+                               15DAD69907591A1A0084A6ED,
+                               15DAD69A07591A1A0084A6ED,
+                               15DAD69B07591A1A0084A6ED,
+                               15DAD69C07591A1A0084A6ED,
+                               15DAD69D07591A1A0084A6ED,
+                               15DAD69E07591A1A0084A6ED,
+                               15DAD69F07591A1A0084A6ED,
+                               15DAD6A007591A1A0084A6ED,
+                               15DAD6A207591A1A0084A6ED,
+                               15DAD6A307591A1A0084A6ED,
+                               15DAD6A407591A1A0084A6ED,
+                               15DAD6A507591A1A0084A6ED,
+                               15DAD6A607591A1A0084A6ED,
+                               15DAD6A707591A1A0084A6ED,
+                               15DAD6A807591A1A0084A6ED,
+                               15DAD6A907591A1A0084A6ED,
+                               15DAD6AA07591A1A0084A6ED,
+                               15DAD6AB07591A1A0084A6ED,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD66D07591A1A0084A6ED = {
+                       fileRef = 15CB695005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD66E07591A1A0084A6ED = {
+                       fileRef = 15CB695205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD66F07591A1A0084A6ED = {
+                       fileRef = 15CB695405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67007591A1A0084A6ED = {
+                       fileRef = 15CB695605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67107591A1A0084A6ED = {
+                       fileRef = 15CB695805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67207591A1A0084A6ED = {
+                       fileRef = 15CB695A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67307591A1A0084A6ED = {
+                       fileRef = 15CB695C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67407591A1A0084A6ED = {
+                       fileRef = 15CB695E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67507591A1A0084A6ED = {
+                       fileRef = 15CB696005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67607591A1A0084A6ED = {
+                       fileRef = 15CB696405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67707591A1A0084A6ED = {
+                       fileRef = 15CB696605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67807591A1A0084A6ED = {
+                       fileRef = 15CB696805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67907591A1A0084A6ED = {
+                       fileRef = 15CB696A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67A07591A1A0084A6ED = {
+                       fileRef = 15CB696C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67B07591A1A0084A6ED = {
+                       fileRef = 15CB696E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67C07591A1A0084A6ED = {
+                       fileRef = 15CB697005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67D07591A1A0084A6ED = {
+                       fileRef = 15CB697205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67E07591A1A0084A6ED = {
+                       fileRef = 15CB697405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD67F07591A1A0084A6ED = {
+                       fileRef = 15CB697605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68007591A1A0084A6ED = {
+                       fileRef = 15CB697805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68107591A1A0084A6ED = {
+                       fileRef = 15CB697A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68207591A1A0084A6ED = {
+                       fileRef = 15CB697C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68307591A1A0084A6ED = {
+                       fileRef = 15CB697E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68407591A1A0084A6ED = {
+                       fileRef = 15CB698005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68507591A1A0084A6ED = {
+                       fileRef = 15CB698205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68607591A1A0084A6ED = {
+                       fileRef = 15CB698405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68707591A1A0084A6ED = {
+                       fileRef = 15CB698605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68807591A1A0084A6ED = {
+                       fileRef = 15CB698805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68907591A1A0084A6ED = {
+                       fileRef = 15CB698A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68A07591A1A0084A6ED = {
+                       fileRef = 15CB698C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68B07591A1A0084A6ED = {
+                       fileRef = 15CB698E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68C07591A1A0084A6ED = {
+                       fileRef = 15CB699005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68D07591A1A0084A6ED = {
+                       fileRef = 15CB699205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68E07591A1A0084A6ED = {
+                       fileRef = 15CB699405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD68F07591A1A0084A6ED = {
+                       fileRef = 15CB699605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69007591A1A0084A6ED = {
+                       fileRef = 15CB699805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69107591A1A0084A6ED = {
+                       fileRef = 15CB699A05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69207591A1A0084A6ED = {
+                       fileRef = 15CB699C05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69307591A1A0084A6ED = {
+                       fileRef = 15CB699E05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69407591A1A0084A6ED = {
+                       fileRef = 15CB69A005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69507591A1A0084A6ED = {
+                       fileRef = 15CB69A205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69607591A1A0084A6ED = {
+                       fileRef = 23C1E2B8062DD45900835B54;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Client,
+                               );
+                       };
+               };
+               15DAD69707591A1A0084A6ED = {
+                       fileRef = 15CB69A405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69807591A1A0084A6ED = {
+                       fileRef = 15CB69A605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69907591A1A0084A6ED = {
+                       fileRef = 15CB69A805C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69A07591A1A0084A6ED = {
+                       fileRef = 15CB69AC05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69B07591A1A0084A6ED = {
+                       fileRef = 15CB69AE05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69C07591A1A0084A6ED = {
+                       fileRef = 15CB69B005C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69D07591A1A0084A6ED = {
+                       fileRef = 15CB69B205C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69E07591A1A0084A6ED = {
+                       fileRef = 15CB69B405C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD69F07591A1A0084A6ED = {
+                       fileRef = 15CB69B605C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                               );
+                       };
+               };
+               15DAD6A007591A1A0084A6ED = {
+                       fileRef = 15CB69BE05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Client,
+                               );
+                       };
+               };
+               15DAD6A207591A1A0084A6ED = {
+                       fileRef = 151BDA5D05D9E2ED00657BC7;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6A307591A1A0084A6ED = {
+                       fileRef = 15B73F0B05FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6A407591A1A0084A6ED = {
+                       fileRef = 15B73F0805FD1B670096477F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6A507591A1A0084A6ED = {
+                       fileRef = 15FCAAD005FD0EBF00CB79E6;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Client,
+                               );
+                       };
+               };
+               15DAD6A607591A1A0084A6ED = {
+                       fileRef = 15AD7A390670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6A707591A1A0084A6ED = {
+                       fileRef = 15AD7A3B0670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6A807591A1A0084A6ED = {
+                       fileRef = 15AD7A3C0670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6A907591A1A0084A6ED = {
+                       fileRef = 15AD7A3D0670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6AA07591A1A0084A6ED = {
+                       fileRef = 15AD7A3E0670A85900BFE03C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6AB07591A1A0084A6ED = {
+                       fileRef = 9EE943F306AF409B00772EB5;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6AC07591A1A0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               /usr/local/lib/OrderFiles/SystemConfiguration.order,
+                       );
+                       isa = PBXShellScriptBuildPhase;
+                       name = SystemConfiguration.order;
+                       outputPaths = (
+                               "${OBJROOT}/SystemConfiguration.order",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "if [ -r /usr/local/lib/OrderFiles/SystemConfiguration.order ]; then\n\tcp /usr/local/lib/OrderFiles/SystemConfiguration.order ${OBJROOT}/SystemConfiguration.order\nelse\n\ttouch ${OBJROOT}/SystemConfiguration.order\nfi";
+               };
+               15DAD6AD07591A1A0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               15DAD6AE07591A1A0084A6ED,
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD6AE07591A1A0084A6ED = {
+                       fileRef = 15CB6A6F05C0722B0099E85F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15DAD6AF07591A1A0084A6ED = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXRezBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15DAD6B007591A1A0084A6ED = {
+                       buildActionMask = 8;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       isa = PBXShellScriptBuildPhase;
+                       name = "get-mobility-info";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+                       shellPath = /bin/sh;
+                       shellScript = "mkdir -p \"${DSTROOT}/usr/local/bin\"\nln -fs \"${INSTALL_PATH}/${TARGET_NAME}/Resources/get-mobility-info\" \"${DSTROOT}/usr/local/bin/\"\n";
+               };
+               15DAD6B107591A1A0084A6ED = {
+                       buildActionMask = 8;
+                       files = (
+                       );
+                       inputPaths = (
+                               preferences.xml,
+                       );
+                       isa = PBXShellScriptBuildPhase;
+                       name = preferences.plist;
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+                       shellPath = /bin/sh;
+                       shellScript = "PREFS_DIR=\"/Library/Preferences/SystemConfiguration\"\nmkdir -p ${DSTROOT}${PREFS_DIR}\nchmod 755 ${DSTROOT}${PREFS_DIR}\ninstall -c -m 644 preferences.xml ${DSTROOT}${PREFS_DIR}/preferences.plist";
+               };
+               15DAD6C807591A1A0084A6ED = {
+                       explicitFileType = wrapper.framework;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = SystemConfiguration.framework;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15DC34670711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = net_interface.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC34680711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = net_interface.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC34690711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = net_protocol.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC346A0711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = net_protocol.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC346B0711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = net_service.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC346C0711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = net_service.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC346D0711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = net_set.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15DC346E0711D49400A3311C = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = net_set.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15FCAACF05FD0EBF00CB79E6 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = shared_dns_info_types.h;
+                       path = dnsinfo/shared_dns_info_types.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               15FCAAD005FD0EBF00CB79E6 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.mig;
+                       name = shared_dns_info.defs;
+                       path = dnsinfo/shared_dns_info.defs;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15FD70FF0754D627001CC321 = {
+                       buildPhases = (
+                               15FD71010754D627001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INFOPLIST_FILE = Plugins/Kicker/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = Kicker;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = bundle;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = Kicker.bundle;
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = Kicker.bundle;
+                       productReference = 15FD71090754D628001CC321;
+                       productType = "com.apple.product-type.bundle";
+               };
+               15FD71010754D627001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               158ADD190754F1F100124717,
+                               158ADD1B0754F1F400124717,
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD71090754D628001CC321 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = Kicker.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD72930754DA2B001CC321 = {
+                       buildPhases = (
+                               15FD72940754DA2B001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INFOPLIST_FILE = Plugins/InterfaceNamer/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = InterfaceNamer;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = bundle;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = InterfaceNamer.bundle;
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = Kicker.bundle;
+                       productReference = 15FD72970754DA2B001CC321;
+                       productType = "com.apple.product-type.bundle";
+               };
+               15FD72940754DA2B001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD72970754DA2B001CC321 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = InterfaceNamer.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD72A10754DA4C001CC321 = {
+                       buildPhases = (
+                               15FD72A20754DA4C001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INFOPLIST_FILE = Plugins/IPMonitor/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = IPMonitor;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = bundle;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = IPMonitor.bundle;
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = Kicker.bundle;
+                       productReference = 15FD72A50754DA4C001CC321;
+                       productType = "com.apple.product-type.bundle";
+               };
+               15FD72A20754DA4C001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               158ADD0E0754F1A000124717,
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD72A50754DA4C001CC321 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = IPMonitor.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD72B10754DA69001CC321 = {
+                       buildPhases = (
+                               15FD72B20754DA69001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INFOPLIST_FILE = Plugins/LinkConfiguration/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = LinkConfiguration;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = bundle;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = LinkConfiguration.bundle;
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = Kicker.bundle;
+                       productReference = 15FD72B50754DA69001CC321;
+                       productType = "com.apple.product-type.bundle";
+               };
+               15FD72B20754DA69001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD72B50754DA69001CC321 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = LinkConfiguration.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD72C50754DA7E001CC321 = {
+                       buildPhases = (
+                               15FD72C60754DA7E001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INFOPLIST_FILE = Plugins/PreferencesMonitor/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = PreferencesMonitor;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = bundle;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = PreferencesMonitor.bundle;
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = Kicker.bundle;
+                       productReference = 15FD72C90754DA7E001CC321;
+                       productType = "com.apple.product-type.bundle";
+               };
+               15FD72C60754DA7E001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD72C90754DA7E001CC321 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = PreferencesMonitor.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD731E0754DB9F001CC321 = {
+                       buildPhases = (
+                               15FD731F0754DB9F001CC321,
+                               15FD73200754DB9F001CC321,
+                               15FD73210754DB9F001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               CURRENT_PROJECT_VERSION = 130;
+                               HEADER_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders";
+                               INFOPLIST_FILE = Plugins/ATconfig/Info.plist;
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/SystemConfiguration";
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = ATconfig;
+                               VALID_ARCHS = ppc;
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                               WRAPPER_EXTENSION = bundle;
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = ATconfig.bundle;
+                       productInstallPath = "$(USER_LIBRARY_DIR)/Bundles";
+                       productName = Kicker.bundle;
+                       productReference = 15FD73220754DB9F001CC321;
+                       productType = "com.apple.product-type.bundle";
+               };
+               15FD731F0754DB9F001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXResourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD73200754DB9F001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               15FD73480754DC2A001CC321,
+                               15FD735C0754DC3F001CC321,
+                               15FD735E0754DC43001CC321,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD73210754DB9F001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               158ADA3D0754EA5A00124717,
+                               1523F6EE075A36210066F0B2,
+                               158ADA160754EA2F00124717,
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD73220754DB9F001CC321 = {
+                       explicitFileType = wrapper.cfbundle;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = ATconfig.bundle;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD733A0754DBDA001CC321 = {
+                       buildPhases = (
+                               15FD733C0754DBDA001CC321,
+                               15FD733D0754DBDA001CC321,
+                               15FD733F0754DBDA001CC321,
+                       );
+                       buildRules = (
+                       );
+                       buildSettings = {
+                               INSTALL_MODE_FLAG = "a-w,a+rX";
+                               INSTALL_PATH = /usr/local/lib/SystemConfiguration;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "-fconstant-cfstrings";
+                               PRODUCT_NAME = ATconfig;
+                               WARNING_CFLAGS = "-Wall -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = ATconfig;
+                       productName = InterfaceNamer;
+                       productReference = 15FD73400754DBDA001CC321;
+                       productType = "com.apple.product-type.library.static";
+               };
+               15FD733C0754DBDA001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD733D0754DBDA001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               1508E39F07552B6A0062B350,
+                               1508E3A007552B6B0062B350,
+                               1508E3A107552B720062B350,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD733F0754DBDA001CC321 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               15FD73400754DBDA001CC321 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libATconfig.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               15FD73480754DC2A001CC321 = {
+                       fileRef = 159D53C707528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15FD735C0754DC3F001CC321 = {
+                       fileRef = 159D53CA07528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15FD735E0754DC43001CC321 = {
+                       fileRef = 159D53C507528B36004F8947;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               15FD73970754DE49001CC321 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15FD73EE0754DE62001CC321 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               15FD743E0754DE7A001CC321 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.xml;
+                       path = Info.plist;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+//150
+//151
+//152
+//153
+//154
+//230
+//231
+//232
+//233
+//234
+               23C1E2B4062DD2C700835B54 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = pppcontroller_types.h;
+                       path = /usr/local/include/ppp/pppcontroller_types.h;
+                       refType = 0;
+                       sourceTree = "<absolute>";
+               };
+               23C1E2B8062DD45900835B54 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.mig;
+                       name = pppcontroller.defs;
+                       path = SystemConfiguration.fproj/pppcontroller.defs;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               23C1E2BE062DD5DB00835B54 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = pppcontroller.h;
+                       path = configd.build/SystemConfiguration.framework.build/DerivedSources/pppcontroller.h;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+//230
+//231
+//232
+//233
+//234
+//9E0
+//9E1
+//9E2
+//9E3
+//9E4
+               9EE943F306AF409B00772EB5 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       path = BondConfiguration.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               9EE943F406AF409B00772EB5 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = BondConfiguration.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               9EE943F506AF409B00772EB5 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = BondConfigurationPrivate.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+       };
+       rootObject = 15CB6A7705C0722B0099E85F;
+}
diff --git a/dnsinfo/dnsinfo.h b/dnsinfo/dnsinfo.h
new file mode 100644 (file)
index 0000000..e26da0e
--- /dev/null
@@ -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 <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/cdefs.h>
+
+
+#define DEFAULT_SEARCH_ORDER    200000   /* search order for the "default" resolver domain name */
+
+
+typedef struct {
+       struct in_addr  address;
+       struct in_addr  mask;
+} dns_sortaddr_t;
+
+
+typedef struct {
+       char            *domain;        /* domain */
+       int32_t         n_nameserver;   /* # nameserver */
+       struct sockaddr **nameserver;
+       uint16_t        port;           /* port (in host byte order) */
+       int32_t         n_search;       /* # search */
+       char            **search;
+       int32_t         n_sortaddr;     /* # sortaddr */
+       dns_sortaddr_t  **sortaddr;
+       char            *options;       /* options */
+       uint32_t        timeout;        /* timeout */
+       uint32_t        search_order;   /* search_order */
+       void            *reserved[8];
+} dns_resolver_t;
+
+
+typedef struct {
+       int32_t         n_resolver;     /* resolver configurations */
+       dns_resolver_t  **resolver;
+       void            *reserved[8];
+} dns_config_t;
+
+
+__BEGIN_DECLS
+
+/*
+ * DNS configuration access APIs
+ */
+const char *   dns_configuration_notify_key    ();
+dns_config_t * dns_configuration_copy          ();
+void           dns_configuration_free          (dns_config_t *config);
+
+__END_DECLS
+
+#endif __DNSINFO_H__
diff --git a/dnsinfo/dnsinfo_copy.c b/dnsinfo/dnsinfo_copy.c
new file mode 100644 (file)
index 0000000..882b697
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdlib.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "dnsinfo.h"
+#include "dnsinfo_private.h"
+#include "shared_dns_info.h"
+
+
+static boolean_t
+add_list(void **padding, uint32_t *n_padding, int32_t count, int32_t size, void **list)
+{
+       int32_t need;
+
+       need = count * size;
+       if (need > *n_padding) {
+               return FALSE;
+       }
+
+       *list = (need == 0) ? NULL : *padding;
+       *padding   += need;
+       *n_padding -= need;
+       return TRUE;
+}
+
+
+static _dns_config_buf_t *
+copy_dns_info()
+{
+       uint8_t                 *buf    = NULL;
+       dnsDataOut_t            dataRef = NULL;
+       mach_msg_type_number_t  dataLen = 0;
+       mach_port_t             server;
+       kern_return_t           status;
+
+       server = _dns_configuration_server_port();
+       if (server == MACH_PORT_NULL) {
+               return NULL;
+       }
+
+       status = shared_dns_infoGet(server, &dataRef, &dataLen);
+       (void)mach_port_deallocate(mach_task_self(), server);
+       if (status != KERN_SUCCESS) {
+               mach_error("shared_dns_infoGet():", status);
+               return NULL;
+       }
+
+       if (dataRef != NULL) {
+               if (dataLen >= sizeof(_dns_config_buf_t)) {
+                       _dns_config_buf_t       *config         = (_dns_config_buf_t *)dataRef;
+                       uint32_t                len;
+                       uint32_t                n_padding       = ntohl(config->n_padding);
+
+                       len = dataLen + n_padding;
+                       buf = malloc(len);
+                       bcopy((void *)dataRef, buf, dataLen);
+                       bzero(&buf[dataLen], n_padding);
+               }
+
+               status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
+               if (status != KERN_SUCCESS) {
+                       mach_error("vm_deallocate():", status);
+                       free(buf);
+                       return NULL;
+               }
+       }
+
+       return (_dns_config_buf_t *)buf;
+}
+
+
+static dns_resolver_t *
+expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32_t *n_padding)
+{
+       dns_attribute_t         *attribute;
+       uint32_t                n_attribute;
+       int32_t                 n_nameserver    = 0;
+       int32_t                 n_search        = 0;
+       int32_t                 n_sortaddr      = 0;
+       dns_resolver_t          *resolver       = (dns_resolver_t *)&buf->resolver;
+
+       if (n_buf < sizeof(_dns_resolver_buf_t)) {
+               goto error;
+       }
+
+       // initialize domain
+
+       resolver->domain = NULL;
+
+       // initialize nameserver list
+
+       resolver->n_nameserver = ntohl(resolver->n_nameserver);
+       if (!add_list(padding,
+                     n_padding,
+                     resolver->n_nameserver,
+                     sizeof(struct sockaddr *),
+                     (void **)&resolver->nameserver)) {
+               goto error;
+       }
+
+       // initialize port
+
+       resolver->port = ntohs(resolver->port);
+
+       // initialize search list
+
+       resolver->n_search = ntohl(resolver->n_search);
+       if (!add_list(padding,
+                     n_padding,
+                     resolver->n_search,
+                     sizeof(char *),
+                     (void **)&resolver->search)) {
+               goto error;
+       }
+
+       // initialize sortaddr list
+
+       resolver->n_sortaddr = ntohl(resolver->n_sortaddr);
+       if (!add_list(padding,
+                     n_padding,
+                     resolver->n_sortaddr,
+                     sizeof(dns_sortaddr_t *),
+                     (void **)&resolver->sortaddr)) {
+               goto error;
+       }
+
+       // initialize options
+
+       resolver->options = NULL;
+
+       // initialize timeout
+
+       resolver->timeout = ntohl(resolver->timeout);
+
+       // initialize search_order
+
+       resolver->search_order = ntohl(resolver->search_order);
+
+       // process resolver buffer "attribute" data
+
+       n_attribute = n_buf - sizeof(_dns_resolver_buf_t);
+       attribute   = (dns_attribute_t *)&buf->attribute[0];
+       if (n_attribute != ntohl(buf->n_attribute)) {
+               goto error;
+       }
+
+       while (n_attribute >= sizeof(dns_attribute_t)) {
+               int32_t attribute_length        = ntohl(attribute->length);
+
+               switch (ntohl(attribute->type)) {
+                       case RESOLVER_ATTRIBUTE_DOMAIN :
+                               resolver->domain = (char *)&attribute->attribute[0];
+                               break;
+
+                       case RESOLVER_ATTRIBUTE_ADDRESS :
+                               resolver->nameserver[n_nameserver++] = (struct sockaddr *)&attribute->attribute[0];
+                               break;
+
+                       case RESOLVER_ATTRIBUTE_SEARCH :
+                               resolver->search[n_search++] = (char *)&attribute->attribute[0];
+                               break;
+
+                       case RESOLVER_ATTRIBUTE_SORTADDR :
+                               resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)&attribute->attribute[0];
+                               break;
+
+                       case RESOLVER_ATTRIBUTE_OPTIONS :
+                               resolver->options = (char *)&attribute->attribute[0];
+                               break;
+
+                       default :
+                               break;
+               }
+
+               attribute   = (dns_attribute_t *)((void *)attribute + attribute_length);
+               n_attribute -= attribute_length;
+       }
+
+       if ((n_nameserver != resolver->n_nameserver) ||
+           (n_search     != resolver->n_search    ) ||
+           (n_sortaddr   != resolver->n_sortaddr  )) {
+               goto error;
+       }
+
+       return resolver;
+
+    error :
+
+       return NULL;
+}
+
+
+static dns_config_t *
+expand_config(_dns_config_buf_t *buf)
+{
+       dns_attribute_t         *attribute;
+       dns_config_t            *config         = (dns_config_t *)buf;
+       uint32_t                n_attribute;
+       uint32_t                n_padding;
+       int32_t                 n_resolver      = 0;
+       void                    *padding;
+
+       // establish padding
+
+       padding   = &buf->attribute[ntohl(buf->n_attribute)];
+       n_padding = ntohl(buf->n_padding);
+
+       // initialize resolver list
+
+       config->n_resolver = ntohl(config->n_resolver);
+       if (!add_list(&padding,
+                     &n_padding,
+                     config->n_resolver,
+                     sizeof(dns_resolver_t *),
+                     (void **)&config->resolver)) {
+               goto error;
+       }
+
+       // process configuration buffer "attribute" data
+
+       n_attribute = ntohl(buf->n_attribute);
+       attribute   = (dns_attribute_t *)&buf->attribute[0];
+
+       while (n_attribute >= sizeof(dns_attribute_t)) {
+               int32_t attribute_length        = ntohl(attribute->length);
+
+               switch (ntohl(attribute->type)) {
+                       case CONFIG_ATTRIBUTE_RESOLVER : {
+                               dns_resolver_t  *resolver;
+
+                               // expand resolver buffer
+
+                               resolver = expand_resolver((_dns_resolver_buf_t *)&attribute->attribute[0],
+                                                          attribute_length - sizeof(dns_attribute_t),
+                                                          &padding,
+                                                          &n_padding);
+                               if (resolver == NULL) {
+                                       goto error;
+                               }
+
+                               // add resolver to config list
+
+                               config->resolver[n_resolver++] = resolver;
+
+                               break;
+                       }
+
+                       default :
+                               break;
+               }
+
+               attribute   = (dns_attribute_t *)((void *)attribute + attribute_length);
+               n_attribute -= attribute_length;
+       }
+
+       if (n_resolver != config->n_resolver) {
+               goto error;
+       }
+
+       return config;
+
+    error :
+
+       return NULL;
+}
+
+
+__private_extern__
+const char *
+dns_configuration_notify_key()
+{
+       return _dns_configuration_notify_key();
+}
+
+
+__private_extern__
+dns_config_t *
+dns_configuration_copy()
+{
+       _dns_config_buf_t       *buf;
+       dns_config_t            *config;
+
+       buf = copy_dns_info();
+       if (buf == NULL) {
+               return NULL;
+       }
+
+       config = expand_config(buf);
+       if (config == NULL) {
+               free(buf);
+               return NULL;
+       }
+
+       return config;
+}
+
+
+__private_extern__
+void
+dns_configuration_free(dns_config_t *config)
+{
+       if (config == NULL) {
+               return;
+       }
+
+       free((void *)config);
+       return;
+}
diff --git a/dnsinfo/dnsinfo_create.c b/dnsinfo/dnsinfo_create.c
new file mode 100644 (file)
index 0000000..6ff9bb3
--- /dev/null
@@ -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 <stdlib.h>
+#include <strings.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "dnsinfo_create.h"
+#include "dnsinfo_private.h"
+#include "shared_dns_info.h"
+
+
+#define ROUNDUP(a, size) \
+       (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
+
+
+/*
+ * to avoid extra calls to realloc() we want to pre-allocate the initial
+ * resolver and configuration buffers of a sufficient size that they would
+ * not normally need to be expanded.
+ */
+#define INITIAL_CONFIGURATION_BUF_SIZE  8192
+#define INITIAL_RESOLVER_BUF_SIZE       1024
+
+
+/*
+ * DNS [configuration] buffer functions
+ */
+
+
+__private_extern__
+dns_create_config_t
+_dns_configuration_create()
+{
+       _dns_config_buf_t       *config;
+
+       config = calloc(1, INITIAL_CONFIGURATION_BUF_SIZE);
+//     config->n_attribute = 0;
+//     config->n_padding = 0;
+       return (dns_create_config_t)config;
+}
+
+
+static void
+config_add_attribute(dns_create_config_t       *_config,
+                    uint32_t                   attribute_type,
+                    uint32_t                   attribute_length,
+                    void                       *attribute,
+                    uint32_t                   extra_padding)
+{
+       _dns_config_buf_t       *config = (_dns_config_buf_t *)*_config;
+       dns_attribute_t         *header;
+       int                     i;
+       uint32_t                newLen;
+       uint32_t                newSize;
+       uint32_t                oldLen;
+       uint32_t                rounded_length;
+
+       // add space
+
+       oldLen         = ntohl(config->n_attribute);
+       rounded_length = ROUNDUP(attribute_length, sizeof(uint32_t));
+       newLen         = sizeof(dns_attribute_t) + rounded_length;
+       newSize = sizeof(_dns_config_buf_t) + oldLen + newLen;
+       if (newSize > INITIAL_CONFIGURATION_BUF_SIZE) {
+               config = realloc(config, newSize);
+       }
+       config->n_attribute = htonl(ntohl(config->n_attribute) + newLen);
+
+       // increment additional padding that will be needed (later)
+       config->n_padding = htonl(ntohl(config->n_padding) + extra_padding);
+
+       // add attribute [header]
+
+       header = (dns_attribute_t *)&config->attribute[oldLen];
+       header->type   = htonl(attribute_type);
+       header->length = htonl(newLen);
+
+       // add attribute [data]
+
+       bcopy(attribute, &header->attribute[0], attribute_length);
+       for (i = attribute_length; i < rounded_length; i++) {
+               header->attribute[i] = 0;
+       }
+
+       *_config = (dns_create_config_t)config;
+       return;
+}
+
+
+__private_extern__
+void
+_dns_configuration_add_resolver(dns_create_config_t     *_config,
+                               dns_create_resolver_t   _resolver)
+{
+       _dns_config_buf_t       *config         = (_dns_config_buf_t *)*_config;
+       uint32_t                padding         = 0;
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)_resolver;
+
+       /*
+        * compute the amount of space that will be needed for
+        * pointers to the resolver, the nameservers, the search
+        * list, and the sortaddr list.
+        */
+       padding += sizeof(dns_resolver_t *);
+       if (resolver->resolver.n_nameserver != 0) {
+               padding += ntohl(resolver->resolver.n_nameserver) * sizeof(struct sockaddr *);
+       }
+       if (resolver->resolver.n_search != 0) {
+               padding += ntohl(resolver->resolver.n_search) * sizeof(char *);
+       }
+       if (resolver->resolver.n_sortaddr != 0) {
+               padding += ntohl(resolver->resolver.n_sortaddr) * sizeof(dns_sortaddr_t *);
+       }
+
+       config->config.n_resolver = htonl(ntohl(config->config.n_resolver) + 1);
+
+       config_add_attribute(_config,
+                            CONFIG_ATTRIBUTE_RESOLVER,
+                            sizeof(_dns_resolver_buf_t) + ntohl(resolver->n_attribute),
+                            (void *)resolver,
+                            padding);
+
+       return;
+}
+
+
+__private_extern__
+_Bool
+_dns_configuration_store(dns_create_config_t *_config)
+{
+       dnsDataOut_t            dataRef = NULL;
+       mach_msg_type_number_t  dataLen = 0;
+       mach_port_t             server;
+       kern_return_t           status;
+
+       server = _dns_configuration_server_port();
+       if (server == MACH_PORT_NULL) {
+               return FALSE;
+       }
+
+       if (_config != NULL) {
+               _dns_config_buf_t       *config = (_dns_config_buf_t *)*_config;
+
+               if (config != NULL) {
+                       dataRef = (dnsDataOut_t)config;
+                       dataLen = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
+               }
+       }
+
+       status = shared_dns_infoSet(server, dataRef, dataLen);
+       (void)mach_port_deallocate(mach_task_self(), server);
+       if (status != KERN_SUCCESS) {
+               mach_error("shared_dns_infoSet():", status);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+__private_extern__
+void
+_dns_configuration_free(dns_create_config_t *_config)
+{
+       _dns_config_buf_t       *config = (_dns_config_buf_t *)*_config;
+
+       free(config);
+       *_config = NULL;
+       return;
+}
+
+
+/*
+ * DNS resolver configuration functions
+ */
+
+__private_extern__
+dns_create_resolver_t
+_dns_resolver_create()
+{
+       _dns_resolver_buf_t     *buf;
+
+       buf = calloc(1, INITIAL_RESOLVER_BUF_SIZE);
+//     buf->n_attribute = 0;
+       return (dns_create_resolver_t)buf;
+}
+
+
+static void
+_dns_resolver_add_attribute(dns_create_resolver_t      *_resolver,
+                           uint32_t                    attribute_type,
+                           uint32_t                    attribute_length,
+                           void                        *attribute)
+{
+       dns_attribute_t         *header;
+       int                     i;
+       uint32_t                newLen;
+       uint32_t                newSize;
+       uint32_t                oldLen;
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+       uint32_t                rounded_length;
+
+       // add space
+
+       oldLen         = ntohl(resolver->n_attribute);
+       rounded_length = ROUNDUP(attribute_length, sizeof(uint32_t));
+       newLen         = sizeof(dns_attribute_t) + rounded_length;
+       newSize = sizeof(_dns_resolver_buf_t) + oldLen + newLen;
+       if (newSize > INITIAL_RESOLVER_BUF_SIZE) {
+               resolver = realloc(resolver, newSize);
+       }
+       resolver->n_attribute = htonl(ntohl(resolver->n_attribute) + newLen);
+
+       // add attribute [header]
+
+       header = (dns_attribute_t *)&resolver->attribute[oldLen];
+       header->type   = htonl(attribute_type);
+       header->length = htonl(newLen);
+
+       // add attribute [data]
+
+       bcopy(attribute, &header->attribute[0], attribute_length);
+       for (i = attribute_length; i < rounded_length; i++) {
+               header->attribute[i] = 0;
+       }
+
+       *_resolver = (dns_create_resolver_t)resolver;
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
+{
+       _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_DOMAIN, strlen(domain) + 1, (void *)domain);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_add_nameserver(dns_create_resolver_t *_resolver, struct sockaddr *nameserver)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.n_nameserver = htonl(ntohl(resolver->resolver.n_nameserver) + 1);
+       _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_ADDRESS, nameserver->sa_len, (void *)nameserver);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_port(dns_create_resolver_t *_resolver, uint32_t port)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.port = htons(port);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.n_search = htonl(ntohl(resolver->resolver.n_search) + 1);
+       _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SEARCH, strlen(search) + 1, (void *)search);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.n_sortaddr = htonl(ntohl(resolver->resolver.n_sortaddr) + 1);
+       _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SORTADDR, sizeof(dns_sortaddr_t), (void *)sortaddr);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
+{
+       _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_OPTIONS, strlen(options) + 1, (void *)options);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.timeout = htonl(timeout);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       resolver->resolver.search_order = htonl(order);
+       return;
+}
+
+
+__private_extern__
+void
+_dns_resolver_free(dns_create_resolver_t *_resolver)
+{
+       _dns_resolver_buf_t     *resolver       = (_dns_resolver_buf_t *)*_resolver;
+
+       free(resolver);
+       *_resolver = NULL;
+       return;
+}
diff --git a/dnsinfo/dnsinfo_create.h b/dnsinfo/dnsinfo_create.h
new file mode 100644 (file)
index 0000000..fd2d6fb
--- /dev/null
@@ -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 <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/cdefs.h>
+
+
+#include <dnsinfo.h>
+
+
+typedef const struct __dns_create_config *      dns_create_config_t;
+typedef const struct __dns_create_resolver *    dns_create_resolver_t;
+
+
+__BEGIN_DECLS
+
+/*
+ * DNS configuration creation APIs
+ */
+dns_create_config_t     _dns_configuration_create       ();
+void                   _dns_configuration_add_resolver (dns_create_config_t *_config, dns_create_resolver_t _resolver);
+_Bool                  _dns_configuration_store        (dns_create_config_t *_config);
+void                   _dns_configuration_free         (dns_create_config_t *_config);
+
+/*
+ * DNS [resolver] configuration creation APIs
+ */
+dns_create_resolver_t   _dns_resolver_create();
+void                   _dns_resolver_set_domain        (dns_create_resolver_t *_resolver, const char *domain);
+void                   _dns_resolver_add_nameserver    (dns_create_resolver_t *_resolver, struct sockaddr *nameserver);
+void                   _dns_resolver_set_port          (dns_create_resolver_t *_resolver, uint32_t port);      // host byte order
+void                   _dns_resolver_add_search        (dns_create_resolver_t *_resolver, const char *search);
+void                   _dns_resolver_add_sortaddr      (dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr);
+void                   _dns_resolver_set_options       (dns_create_resolver_t *_resolver, const char *options);
+void                   _dns_resolver_set_timeout       (dns_create_resolver_t *_resolver, uint32_t timeout);
+void                   _dns_resolver_set_order         (dns_create_resolver_t *_resolver, uint32_t order);
+void                   _dns_resolver_free              (dns_create_resolver_t *_resolver);
+
+__END_DECLS
+
+#endif __DNSINFO_CREATE_H__
diff --git a/dnsinfo/dnsinfo_private.c b/dnsinfo/dnsinfo_private.c
new file mode 100644 (file)
index 0000000..6ada24f
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdlib.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <servers/bootstrap.h>
+
+#include "dnsinfo_private.h"
+#include "shared_dns_info_types.h"
+
+
+__private_extern__
+const char *
+_dns_configuration_notify_key()
+{
+       return "com.apple.SystemConfiguration.dns_configuration";
+}
+
+
+__private_extern__
+mach_port_t
+_dns_configuration_server_port()
+{
+       mach_port_t     server          = MACH_PORT_NULL;
+       char            *server_name;
+       kern_return_t   status;
+
+       server_name = getenv("DNS_SERVER");
+       if (!server_name) {
+               server_name = DNS_SERVER;
+       }
+
+       status = bootstrap_look_up(bootstrap_port, server_name, &server);
+       switch (status) {
+               case BOOTSTRAP_SUCCESS :
+                       /* service currently registered, "a good thing" (tm) */
+                       break;
+               case BOOTSTRAP_UNKNOWN_SERVICE :
+                       /* service not currently registered, try again later */
+                       return MACH_PORT_NULL;
+               default :
+                       mach_error("could not lookup DNS configuration info service:", status);
+                       return MACH_PORT_NULL;
+       }
+
+       return server;
+}
+
diff --git a/dnsinfo/dnsinfo_private.h b/dnsinfo/dnsinfo_private.h
new file mode 100644 (file)
index 0000000..378787c
--- /dev/null
@@ -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 <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <mach/mach.h>
+
+#include "dnsinfo.h"
+
+
+/*
+ * What's all of this stuff about???
+ *
+ * In order to minimize the amount of data conversions associated with
+ * storing, retrieving, and accessing the systems DNS configuration I
+ * have opted to create a memory image filled with the actual data
+ * types / structures that would be used by those applications which
+ * make use of these APIS.  The implication here is that we use
+ * sockaddr's for addresses, char *'s for strings, etc.
+ *
+ * To achieve this goal the APIs which are used to store and access the
+ * configuration data build and use a single buffer of the relevant
+ * bits.  When multiple instances of a given type / structure are needed
+ * we maintain a count, the actual data, and when the configuration has
+ * been unpacked, arrays of pointers to the data.
+ *
+ * In memory, the data looks as follows:
+ *
+ * +-------------------------------------------------------------------+
+ * | struct _dns_config_buf_t                                          |
+ * +-+-------------+---------------------------------------------------+
+ * | | config      | struct dns_config_t                              |
+ * | |            +-+--------------+----------------------------------+
+ * | |             | | n_resolver   | int32_t                          | <- # of name resolvers
+ * | |            | +--------------+----------------------------------+
+ * | |             | | resolver     | dns_resolver_t **                | <- not used during creation, filled
+ * | |             | |              |                                  |    in with pointer to a list of
+ * | |            | |              |                                  |    resolver configurations which be
+ * | |            | |              |                                  |    established in the "padding"
+ * | |            | +--------------+----------------------------------+
+ * | |            | | ...          | ...                              |
+ * | +-------------+-+--------------+----------------------------------+
+ * | | n_attribute | uint32_t                                          | <- how many bytes of "attribute"
+ * | |            |                                                   |    data is associated with the
+ * | |            |                                                   |    configuration
+ * |-+-------------+---------------------------------------------------+
+ * | | n_padding   | uint32_t                                          | <- how many additional bytes
+ * | |            |                                                   |    for arrays (of pointers), ...
+ * +-+-------------+---------------------------------------------------+
+ * | struct dns_attribute_t                                            |
+ * |-+-------------+---------------------------------------------------+
+ * | | type        | uint32_t                                          | <- type of attribute (e.g. CONFIG_ATTRIBUTE_RESOLVER)
+ * | +-------------+---------------------------------------------------+
+ * | | length      | uint32_t                                          | <- length of the attribute
+ * | +-------------+---------------------------------------------------+
+ * | | attribute   | struct _dns_resolver_buf_t                        | <- the attribute data (resolver configuration #1)
+ * | |             +-+-------------+-----------------------------------+
+ * | |             | | resolver    | struct dns_resolver_t             |
+ * | |             | |            +--------------+--------------------+
+ * | |             | |            | domain       | char *             | <- not used during creation,
+ * | |             | |            |              |                    |    filled in with pointer to
+ * | |             | |            |              |                    |    domain name in the "padding"
+ * | |             | |            +--------------+--------------------+
+ * | |             | |            | n_nameserver | int32_t            | <- # of name server addresses
+ * | |             | |            +--------------+--------------------+
+ * | |             | |            | nameserver   | struct sockaddr ** | <- not used during creation,
+ * | |             | |            |              |                    |    filled in with pointer to
+ * | |             | |            |              |                    |    a list of addresses which
+ * | |             | |            |              |                    |    will be established in the
+ * | |             | |            |              |                    |    "padding"
+ * | |             | |            +--------------+--------------------+
+ * | |             | |            | ...                               |
+ * | |             +-+-------------+--------------+--------------------+
+ * | |             | | n_attribute | uint32_t                          |
+ * | |             +-+-------------+-----------------------------------+
+ * | |             | | attribute   | struct dns_attribute_t            |
+ * | |             | |            +-+-----------+---------------------+
+ * | |             | |            | | type      | uint32_t            | <- type of attribute (e.g. RESOLVER_ATTRIBUTE_DOMAIN)
+ * | |             | |            | +-----------+---------------------+
+ * | |             | |             | | length    | uint32_t            | <- length of the attribute
+ * | |             | |            | +-----------+---------------------+
+ * | |             | |            | | attribute |                     | <- the attribute data ("apple.com")
+ * | |             +-+-------------+-------------+---------------------+
+ * | |             | | attribute   | struct dns_attribute_t            |
+ * | |             | |            +-+-----------+---------------------+
+ * | |             | |            | | type      | uint32_t            | <- type of attribute (e.g. RESOLVER_ATTRIBUTE_ADDRESS)
+ * | |             | |            | +-----------+---------------------+
+ * | |             | |             | | length    | uint32_t            | <- length of the attribute
+ * | |             | |            | +-----------+---------------------+
+ * | |             | |            | | attribute |                     | <- the attribute data ("struct sockaddr_in" #1)
+ * | |             +---------------+-----------------------------------+
+ * | |             | | attribute   | struct dns_attribute_t            |
+ * | |             | |            +-+-----------+---------------------+
+ * | |             | |            | | type      | uint32_t            | <- type of attribute (e.g. RESOLVER_ATTRIBUTE_ADDRESS)
+ * | |             | |            | +-----------+---------------------+
+ * | |             | |             | | length    | uint32_t            | <- length of the attribute
+ * | |             | |            | +-----------+---------------------+
+ * | |             | |            | | attribute |                     | <- the attribute data ("struct sockaddr_in" #2)
+ * | |             +---------------+-----------------------------------+
+ * | |             | ...                                              |
+ * +-+-------------+---------------------------------------------------+
+ * | | attribute   | struct _dns_resolver_buf_t                               | <- the attribute data (resolver configuration #2)
+ * | |             +---------------+-----------------------------------+
+ * | |             | ...                                              |
+ * +---------------+---------------------------------------------------+
+ * | | ...                                                            |
+ * +---------------+---------------------------------------------------+
+ *
+ * When the data is unpacked the "n_padding" additional bytes
+ * specified in configuration buffer will be allocated at the
+ * end of this buffer. Arrays of pointers will be allocated
+ * within the extra space array element (an "attribute") is
+ * encountered the pointer reference will be filled in.
+ */
+
+
+// configuration buffer attributes
+enum {
+       CONFIG_ATTRIBUTE_RESOLVER       = 1
+};
+
+
+// resolver buffer attributes
+enum {
+       RESOLVER_ATTRIBUTE_DOMAIN       = 10,
+       RESOLVER_ATTRIBUTE_ADDRESS,
+       RESOLVER_ATTRIBUTE_SEARCH,
+       RESOLVER_ATTRIBUTE_SORTADDR,
+       RESOLVER_ATTRIBUTE_OPTIONS
+};
+
+
+typedef struct {
+       uint32_t        type;
+       uint32_t        length;
+       uint8_t         attribute[0];
+} dns_attribute_t;
+
+
+typedef struct {
+       dns_config_t    config;
+       uint32_t        n_attribute;
+       uint32_t        n_padding;
+       uint8_t         attribute[0];
+} _dns_config_buf_t;
+
+
+typedef struct {
+       dns_resolver_t  resolver;
+       uint32_t        n_attribute;
+       uint8_t         attribute[0];
+} _dns_resolver_buf_t;
+
+
+const char *    _dns_configuration_notify_key();
+mach_port_t    _dns_configuration_server_port();
+
+#endif __DNSINFO_PRIVATE_H__
diff --git a/dnsinfo/dnsinfo_server.c b/dnsinfo/dnsinfo_server.c
new file mode 100644 (file)
index 0000000..a87dd58
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <notify.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <servers/bootstrap.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SCPrivate.h>
+
+#include "dnsinfo_server.h"
+#include "dnsinfo_private.h"
+
+#include "session.h"
+
+static CFDataRef       shared_dns_info         = NULL;
+
+__private_extern__
+kern_return_t
+_shared_dns_infoGet(mach_port_t server, dnsDataOut_t *dataRef, mach_msg_type_number_t *dataLen)
+{
+       *dataRef = NULL;
+       *dataLen = 0;
+
+       if (shared_dns_info != NULL) {
+               if (!_SCSerializeData(shared_dns_info, (void **)dataRef, (CFIndex *)dataLen)) {
+                       return KERN_FAILURE;
+               }
+       }
+
+       return KERN_SUCCESS;
+}
+
+
+__private_extern__
+kern_return_t
+_shared_dns_infoSet(mach_port_t server, dnsData_t dataRef, mach_msg_type_number_t dataLen)
+{
+       CFDataRef               new_dns_info    = NULL;
+       const char              *notify_key;
+       serverSessionRef        mySession       = getSession(server);
+
+       if ((dataRef != NULL) && (dataLen > 0)) {
+               if (!_SCUnserializeData(&new_dns_info, (void *)dataRef, dataLen)) {
+                       goto error;
+               }
+       }
+
+       if (mySession->callerEUID != 0) {
+               goto error;
+       }
+
+       if (shared_dns_info != NULL) CFRelease(shared_dns_info);
+       shared_dns_info = new_dns_info;
+
+       notify_key = _dns_configuration_notify_key();
+       if (notify_key != NULL) {
+               uint32_t        status;
+
+               status = notify_post(notify_key);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: %d"), status);
+                       // notification posting failures are non-fatal
+               }
+       }
+
+       return KERN_SUCCESS;
+
+    error :
+
+       if (new_dns_info != NULL)    CFRelease(new_dns_info);
+       return KERN_FAILURE;
+}
diff --git a/dnsinfo/dnsinfo_server.h b/dnsinfo/dnsinfo_server.h
new file mode 100644 (file)
index 0000000..9bddeb0
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <mach/mach.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "shared_dns_info_types.h"
+
+__BEGIN_DECLS
+
+kern_return_t  _shared_dns_infoGet     (mach_port_t            server,
+                                        dnsDataOut_t           *dataRef,
+                                        mach_msg_type_number_t *dataLen);
+
+kern_return_t  _shared_dns_infoSet     (mach_port_t            server,
+                                        dnsData_t              dataRef,
+                                        mach_msg_type_number_t dataLen);
+
+__END_DECLS
+
+#endif /* !_S_DNSINFO_SERVER_H */
diff --git a/dnsinfo/shared_dns_info.defs b/dnsinfo/shared_dns_info.defs
new file mode 100644 (file)
index 0000000..9f12a18
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+subsystem shared_dns_info 21000;
+serverprefix _;
+
+import "shared_dns_info_types.h";
+
+/*
+ * DNS configuration (client->server)
+ */
+type dnsData    = ^ array [] of MACH_MSG_TYPE_BYTE
+       ctype : dnsData_t;
+
+/*
+ * DNS configuration (server->client)
+ */
+type dnsDataOut = ^ array [] of MACH_MSG_TYPE_BYTE
+       ctype : dnsDataOut_t;
+
+/*
+ * DNS configuration API's
+ */
+
+routine shared_dns_infoGet     (       server          : mach_port_t;
+                                out    data            : dnsDataOut, dealloc);
+
+routine shared_dns_infoSet     (       server          : mach_port_t;
+                                       data            : dnsData);
diff --git a/dnsinfo/shared_dns_info_types.h b/dnsinfo/shared_dns_info_types.h
new file mode 100644 (file)
index 0000000..e4fe4b6
--- /dev/null
@@ -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 (executable)
index 0000000..403b317
--- /dev/null
@@ -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"
index c4222c8984a7b34ccb34adb9a9b44cb6d82a8320..d25e57a7762ef98a246a76cab4bb99eb890d7ef3 100644 (file)
@@ -71,7 +71,7 @@
                                <key>LCPEchoInterval</key>
                                <integer>10</integer>
                                <key>Logfile</key>
                                <key>LCPEchoInterval</key>
                                <integer>10</integer>
                                <key>Logfile</key>
-                               <string>/tmp/ppp.log</string>
+                               <string>/var/log/ppp.log</string>
                                <key>VerboseLogging</key>
                                <integer>0</integer>
                                <key>__INACTIVE__</key>
                                <key>VerboseLogging</key>
                                <integer>0</integer>
                                <key>__INACTIVE__</key>
diff --git a/scselect.tproj/Makefile b/scselect.tproj/Makefile
deleted file mode 100644 (file)
index 9bf1aa4..0000000
+++ /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 (file)
index 46b1c86..0000000
+++ /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 (file)
index 13efa5f..0000000
+++ /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: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/scselect.tproj/PB.project b/scselect.tproj/PB.project
deleted file mode 100644 (file)
index f5d4f31..0000000
+++ /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 (file)
index f3c1b04..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
diff --git a/scselect.tproj/m.template b/scselect.tproj/m.template
deleted file mode 100644 (file)
index 1216fe5..0000000
+++ /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 (file)
index 0000000..c4c5645
--- /dev/null
@@ -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.
index 04a241e6e637ab1c80a303bb66e9b171950e9801..9dac36a4dd0f3c1f357554c345764db73fd5b634 100644 (file)
 #include <Security/AuthSession.h>
 
 
 #include <Security/AuthSession.h>
 
 
-Boolean        apply   = TRUE;
+static Boolean apply   = TRUE;
 
 
 
 
-static struct option longopts[] = {
+static const struct option longopts[] = {
 //     { "debug",              no_argument,            0,      'd' },
 //     { "verbose",            no_argument,            0,      'v' },
 //     { "do-not-apply",       no_argument,            0,      'n' },
 //     { "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()
 {
 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()
 {
 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;
        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;
        CFDictionaryRef         sets;
        CFIndex                 nSets;
        const void              **setKeys       = NULL;
@@ -200,8 +200,8 @@ main(int argc, char **argv)
                        ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman)
                        : CFSTR("");
 
                        ? 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);
        }
                SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
                exit (1);
        }
@@ -224,14 +224,14 @@ main(int argc, char **argv)
                newSet = str;
        }
 
                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);
        }
 
                exit (1);
        }
 
-       current = SCPreferencesGetValue(session, kSCPrefCurrentSet);
-       if (current) {
+       current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+       if (current != NULL) {
                if (CFStringHasPrefix(current, prefix)) {
                        CFMutableStringRef      tmp;
 
                if (CFStringHasPrefix(current, prefix)) {
                        CFMutableStringRef      tmp;
 
@@ -264,7 +264,7 @@ main(int argc, char **argv)
 
                if (CFEqual(newSet, key)) {
                        newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName);
 
                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;
                }
                        current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet);
                        goto found;
                }
@@ -324,12 +324,12 @@ main(int argc, char **argv)
     found :
 
        if (!(isAdmin() || hasLocalConsoleAccess())) {
     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,
                SCPrint(TRUE, stderr,
                        CFSTR("SCPreferencesSetValue(...,%@,%@) failed\n"),
                        kSCPrefCurrentSet,
@@ -337,19 +337,19 @@ main(int argc, char **argv)
                exit (1);
        }
 
                exit (1);
        }
 
-       if (!SCPreferencesCommitChanges(session)) {
+       if (!SCPreferencesCommitChanges(prefs)) {
                SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed\n"));
                exit (1);
        }
 
        if (apply) {
                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);
                }
        }
 
                        SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed\n"));
                        exit (1);
                }
        }
 
-       CFRelease(session);
+       CFRelease(prefs);
 
        SCPrint(TRUE, stdout,
                CFSTR("%@ updated to %@ (%@)\n"),
 
        SCPrint(TRUE, stdout,
                CFSTR("%@ updated to %@ (%@)\n"),
diff --git a/scutil.tproj/Makefile b/scutil.tproj/Makefile
deleted file mode 100644 (file)
index bfd12a8..0000000
+++ /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 (file)
index da52544..0000000
+++ /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 (file)
index b9f5238..0000000
+++ /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: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-# DSTROOT = $(HOME)
diff --git a/scutil.tproj/PB.project b/scutil.tproj/PB.project
deleted file mode 100644 (file)
index 6c31b0e..0000000
+++ /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"; 
-}
index 84074543cd1e2a6e15643c00fb408816cc312c01..74a71274f3516a8ddc819123c08dc1c9b73ebef3 100644 (file)
@@ -45,6 +45,7 @@ sort_keys(const void *p1, const void *p2, void *context) {
 }
 
 
 }
 
 
+__private_extern__
 void
 do_list(int argc, char **argv)
 {
 void
 do_list(int argc, char **argv)
 {
@@ -56,7 +57,7 @@ do_list(int argc, char **argv)
 
        pattern = CFStringCreateWithCString(NULL,
                                            (argc >= 1) ? argv[0] : ".*",
 
        pattern = CFStringCreateWithCString(NULL,
                                            (argc >= 1) ? argv[0] : ".*",
-                                           kCFStringEncodingMacRoman);
+                                           kCFStringEncodingUTF8);
 
        list = SCDynamicStoreCopyKeyList(store, pattern);
        CFRelease(pattern);
 
        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;
 
 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)) {
 
        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;
 
 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) {
        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;
 
 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()));
        }
        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;
 
 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);
 
        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;
 
 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()));
        }
        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;
 
 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()));
        }
        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;
 
 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()));
        }
        if (!SCDynamicStoreTouchValue(store, key)) {
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
        }
index 561f15c1e5d13f55bc4b679b071f6920373f519a..5a9046546c75c74658a8c85793a90a8ff6c7d945 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include "dictionary.h"
 #include "session.h"
 #include "cache.h"
 #include "dictionary.h"
 #include "session.h"
 #include "cache.h"
-#include "notify.h"
+#include "notifications.h"
 #include "tests.h"
 #include "tests.h"
+#include "net.h"
 
 #include "SCDynamicStoreInternal.h"
 
 
 
 #include "SCDynamicStoreInternal.h"
 
 
-const cmdInfo commands[] = {
+__private_extern__
+const cmdInfo commands_store[] = {
        /* cmd          minArgs maxArgs func                    group   ctype                   */
        /*      usage                                                                           */
 
        /* 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"                   },
 
        { "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,
        /* 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"
 
        { "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 */
 
 
        { "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,
                " 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,
                " 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,
 
        { "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"            },
 
        { "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.list [\"pattern\"]            : list notification keys"                     },
 
        { "n.add",      1,      2,      do_notify_add,          5,      0,
-               " n.add key [\"pattern\"]         : add notification key"                               },
+               " n.add key [\"pattern\"]         : add notification key"                       },
 
        { "n.remove",   1,      2,      do_notify_remove,       5,      0,
                " n.remove key [\"pattern\"]      : remove notification key"                    },
 
        { "n.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"                 },
 
        { "n.cancel",   0,      1,      do_notify_cancel,       5,      0,
                " n.cancel                      : cancel notification requests"                 },
 
-       { "snapshot",   0,      0,      do_snapshot,            9     2,
-               " snapshot                      : save snapshot of store and session data"      },
+       { "snapshot",   0,      0,      do_snapshot,            99,     2,
+               " snapshot                      : save snapshot of store and session data"      }
 };
 };
+__private_extern__
+const int nCommands_store = (sizeof(commands_store)/sizeof(cmdInfo));
+
+
+__private_extern__
+const cmdInfo commands_prefs[] = {
+       /* cmd          minArgs maxArgs func                    group   ctype                   */
+       /*      usage                                                                           */
+
+       { "help",       0,      0,      do_help,                0,      0,
+               " help                          : list available commands"                      },
+
+       { "f.read",     1,      1,      do_readFile,            0,      0,
+               " f.read file                   : process commands from file"                   },
+
+       { "quit",       0,      1,      do_net_quit,            0,      0,
+               " quit [!]                      : quit"                                         },
+
+       { "q",          0,      1,      do_net_quit,            0,      -1,
+               NULL                                                                            },
+
+       { "exit",       0,      1,      do_net_quit,            0,      -1,
+               NULL                                                                            },
+
+       /* network configuration manipulation commands */
+
+       { "open",       0,      1,      do_net_open,            2,      1,
+               " open                          : open the network configuration"               },
+
+       { "commit",     0,      0,      do_net_commit,          2,      0,
+               " commit                        : commit any changes"                           },
+
+       { "apply",      0,      0,      do_net_apply,           2,      0,
+               " apply                         : apply any changes"                            },
 
 
-const int nCommands = (sizeof(commands)/sizeof(cmdInfo));
+       { "close",      0,      1,      do_net_close,           2,      1,
+               " close [!]                     : close the network configuration"              },
 
 
-Boolean enablePrivateAPI       = FALSE;
+       { "create",     1,      3,      do_net_create,          3,      0,
+               " create interface <interfaceType> [ <interfaceName> | <interface#> ]\n"
+               " create protocol <protocolType>\n"
+               " create service [ <interfaceName> | <interface#> [ <serviceName> ]]\n"
+               " create set [setName]"                                                         },
 
 
+       { "disable",    1,      2,      do_net_disable,         5,      0,
+               " disable protocol [ <protocolType> ]\n"
+               " disable service  [ <serviceName> | <service#> ]"                              },
 
 
+       { "enable",     1,      2,      do_net_enable,          4,      0,
+               " enable protocol  [ <protocolType> ]\n"
+               " enable service   [ <serviceName> | <service#> ]"                              },
+
+       { "remove",     1,      2,      do_net_remove,          6,      0,
+               " remove protocol  [ <protocolType> ]\n"
+               " remove service   [ <serviceName> | <service#> ]\n"
+               " remove set       [ <setName> | <set#> ]"                                      },
+
+       { "select",     2,      2,      do_net_select,          7,      0,
+               " select interface <interfaceName> | <interface#> | $child | $service\n"
+               " select protocol  <protocolType>\n"
+               " select service   <serviceName> | <service#>\n"
+               " select set       <setName> | <set#>"                                          },
+
+       { "set",        2,      101,    do_net_set,             8,      0,
+               " set interface context-sensitive-arguments (or ? for help)\n"
+               " set protocol  context-sensitive-arguments (or ? for help)\n"
+               " set service   [ name <serviceName> ] [ order new-order ]\n"
+               " set set       [ name setName ]"                                               },
+
+       { "show",       1,      2,      do_net_show,            9,      0,
+               " show interfaces\n"
+               " show interface [ <interfaceName> | <interface#> ]\n"
+               " show protocols\n"
+               " show protocol  [ <protocolType> ]\n"
+               " show services  [ all ]\n"
+               " show service   [ <serviceName> | <service#> ]\n"
+               " show sets\n\n"
+               " show set       [ <setName> | <set#> ]"                                        },
+
+       { "snapshot",   0,      0,      do_net_snapshot,        99,     2,
+               " snapshot"                                                                     }
+
+};
+__private_extern__
+const int nCommands_prefs = (sizeof(commands_prefs)/sizeof(cmdInfo));
+
+
+__private_extern__ cmdInfo     *commands               = NULL;
+__private_extern__ int         nCommands               = 0;
+__private_extern__ Boolean     enablePrivateAPI        = FALSE;
+__private_extern__ Boolean     termRequested           = FALSE;
+
+
+__private_extern__
 void
 do_command(int argc, char **argv)
 {
 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;
                        }
                                SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
                                return;
                        }
-                       commands[i].func(argc, argv);
+                       (*commands[i].func)(argc, argv);
                        return;
                }
        }
                        return;
                }
        }
@@ -179,6 +278,7 @@ do_command(int argc, char **argv)
 }
 
 
 }
 
 
+__private_extern__
 void
 do_help(int argc, char **argv)
 {
 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++) {
 
        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 */
                }
                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)
 {
 void
 do_readFile(int argc, char **argv)
 {
@@ -236,3 +341,12 @@ do_readFile(int argc, char **argv)
 
        return;
 }
 
        return;
 }
+
+
+__private_extern__
+void
+do_quit(int argc, char **argv)
+{
+       termRequested = TRUE;
+       return;
+}
index a0a082129a557b3e58ee8022c6b431152244640d..f1fd33299a1536d6030975b881c21f9815fcb22c 100644 (file)
@@ -42,18 +42,26 @@ typedef struct {
        int     maxArgs;
        void    (*func)();
        int     group;
        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;
 
        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         enablePrivateAPI;
+extern Boolean         termRequested;
 
 __BEGIN_DECLS
 
 void   do_command              (int argc, char **argv);
 void   do_help                 (int argc, char **argv);
 
 __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
 void   do_readFile             (int argc, char **argv);
 
 __END_DECLS
index 8507ddac44ca179fb08636b53f17bb74ab3f6030..234c4e2f48dd75c3fb07a88c2b285e9c0fc7343b 100644 (file)
@@ -39,6 +39,7 @@
 //#include <limits.h>
 
 
 //#include <limits.h>
 
 
+__private_extern__
 void
 do_dictInit(int argc, char **argv)
 {
 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)
 {
 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)
 {
 void
 do_dictSetKey(int argc, char **argv)
 {
@@ -94,7 +97,7 @@ do_dictSetKey(int argc, char **argv)
        CFRelease(value);
        value = val;
 
        CFRelease(value);
        value = val;
 
-       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        argv++; argc--;
 
        while (argc > 0) {
        argv++; argc--;
 
        while (argc > 0) {
@@ -161,7 +164,7 @@ do_dictSetKey(int argc, char **argv)
                                return;
                        }
                } else {
                                return;
                        }
                } else {
-                       val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+                       val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
                }
 
                if (doArray) {
                }
 
                if (doArray) {
@@ -183,6 +186,7 @@ do_dictSetKey(int argc, char **argv)
 }
 
 
 }
 
 
+__private_extern__
 void
 do_dictRemoveKey(int argc, char **argv)
 {
 void
 do_dictRemoveKey(int argc, char **argv)
 {
@@ -203,7 +207,7 @@ do_dictRemoveKey(int argc, char **argv)
        CFRelease(value);
        value = val;
 
        CFRelease(value);
        value = val;
 
-       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key);
        CFRelease(key);
 
        CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key);
        CFRelease(key);
 
diff --git a/scutil.tproj/h.template b/scutil.tproj/h.template
deleted file mode 100644 (file)
index f3c1b04..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-$$
-/* $FILENAME$ created by $USERNAME$ on $DATE$ */
-
-#import <Foundation/Foundation.h>
-
-@interface $FILENAMESANSEXTENSION$ : NSObject
-{
-
-}
-
-@end
diff --git a/scutil.tproj/m.template b/scutil.tproj/m.template
deleted file mode 100644 (file)
index 1216fe5..0000000
+++ /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 (file)
index 0000000..c28dd55
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "commands.h"
+#include "net.h"
+#include "net_interface.h"
+#include "net_protocol.h"
+#include "net_service.h"
+#include "net_set.h"
+
+#include <unistd.h>
+
+
+__private_extern__ Boolean                     net_changed     = FALSE;
+
+__private_extern__ CFMutableArrayRef           new_interfaces  = NULL;
+
+__private_extern__ CFArrayRef                  interfaces      = NULL;
+__private_extern__ CFArrayRef                  services        = NULL;
+__private_extern__ CFArrayRef                  protocols       = NULL;
+__private_extern__ CFArrayRef                  sets            = NULL;
+
+__private_extern__ SCNetworkInterfaceRef       net_interface   = NULL;
+__private_extern__ SCNetworkServiceRef         net_service     = NULL;
+__private_extern__ SCNetworkProtocolRef                net_protocol    = NULL;
+__private_extern__ SCNetworkSetRef             net_set         = NULL;
+
+__private_extern__ CFNumberRef                 CFNumberRef_0   = NULL;
+__private_extern__ CFNumberRef                 CFNumberRef_1   = NULL;
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFNumberRef
+_copy_number(const char *arg)
+{
+       int     val;
+
+       if (sscanf(arg, "%d", &val) != 1) {
+               return NULL;
+       }
+
+       return CFNumberCreate(NULL, kCFNumberIntType, &val);
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFIndex
+_find_option(const char *option, optionsRef options, const int nOptions)
+{
+       CFIndex i;
+
+       for (i = 0; i < nOptions; i++) {
+               if (strcasecmp(option, options[i].option) == 0) {
+                       return i;
+               }
+       }
+
+       return kCFNotFound;
+}
+
+
+__private_extern__
+CFIndex
+_find_selection(CFStringRef choice, selections choices[], unsigned int *flags)
+{
+       CFIndex i;
+
+       i = 0;
+       while (choices[i].selection != NULL) {
+               if (CFStringCompare(choice,
+                                   choices[i].selection,
+                                   kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                       if (flags != NULL) {
+                               *flags = choices[i].flags;
+                       }
+                       return i;
+               }
+               i++;
+       }
+
+       return kCFNotFound;
+}
+
+
+__private_extern__
+Boolean
+_process_options(optionsRef options, int nOptions, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       while (argc > 0) {
+               CFIndex optionIndex     = kCFNotFound;
+
+               optionIndex = _find_option(argv[0], options, nOptions);
+               if (optionIndex == kCFNotFound) {
+                       SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+                       return FALSE;
+               }
+               argv++;
+               argc--;
+
+               switch (options[optionIndex].type) {
+                       case isOther :
+                               // all option processing is managed by the "handler"
+                               break;
+                       case isHelp :
+                               SCPrint(TRUE, stdout, CFSTR("%s\n"), options[optionIndex].info);
+                               return FALSE;
+                       case isChooseOne : {
+                               CFStringRef     choice;
+                               selections      *choices        = (selections *)options[optionIndex].info;
+                               unsigned int    flags;
+                               CFIndex         i;
+
+                               if (argc < 1) {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("%s not specified\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+                                       return FALSE;
+                               }
+
+                               choice = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+                               i = _find_selection(choice, choices, &flags);
+                               CFRelease(choice);
+
+                               if (i != kCFNotFound) {
+                                       if (choices[i].flags & selectionNotAvailable) {
+                                               SCPrint(TRUE, stdout,
+                                                       CFSTR("cannot select %s\n"),
+                                                       options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+                                                       return FALSE;
+                                       }
+
+                                       CFDictionarySetValue(newConfiguration,
+                                                            *(options[optionIndex].key),
+                                                            *(choices[i].key));
+                               } else {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("invalid %s\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+                                       return FALSE;
+                               }
+
+                               argv++;
+                               argc--;
+                               break;
+                       }
+                       case isChooseMultiple :
+                               if (argc < 1) {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("%s(s) not specified\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+                                       return FALSE;
+                               }
+
+                               if (strlen(argv[0]) > 0) {
+                                       CFIndex                 i;
+                                       CFIndex                 n;
+                                       CFMutableArrayRef       chosen;
+                                       CFStringRef             str;
+                                       CFArrayRef              str_array;
+
+                                       str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+                                       str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+                                       CFRelease(str);
+
+                                       chosen = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+                                       n = CFArrayGetCount(str_array);
+                                       for (i = 0; i < n; i++) {
+                                               CFStringRef     choice;
+                                               selections      *choices        = (selections *)options[optionIndex].info;
+                                               unsigned int    flags;
+                                               CFIndex         j;
+
+                                               choice = CFArrayGetValueAtIndex(str_array, i);
+                                               j = _find_selection(choice, choices, &flags);
+
+                                               if (j != kCFNotFound) {
+                                                       if (choices[j].flags & selectionNotAvailable) {
+                                                               SCPrint(TRUE, stdout,
+                                                                       CFSTR("cannot select %s\n"),
+                                                                       options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+                                                               CFArrayRemoveAllValues(chosen);
+                                                               break;
+                                                       }
+
+                                                       CFArrayAppendValue(chosen, *(choices[j].key));
+                                               } else {
+                                                       SCPrint(TRUE, stdout,
+                                                               CFSTR("invalid %s\n"),
+                                                               options[optionIndex].description != NULL ? options[optionIndex].description : "selection");
+                                                       CFArrayRemoveAllValues(chosen);
+                                                       break;
+                                               }
+                                       }
+                                       CFRelease(str_array);
+
+                                       if (CFArrayGetCount(chosen) > 0) {
+                                               CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), chosen);
+                                       } else {
+                                               CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+                                       }
+                                       CFRelease(chosen);
+                               } else {
+                                       CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+                               }
+
+                               argv++;
+                               argc--;
+                               break;
+                       case isBoolean :
+                               if (argc < 1) {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("%s not specified\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "enable/disable");
+                                       return FALSE;
+                               }
+
+                               if        ((strcasecmp(argv[0], "disable") == 0) ||
+                                          (strcasecmp(argv[0], "0"      ) == 0)) {
+                                       CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_0);
+                               } else if ((strcasecmp(argv[0], "enable") == 0) ||
+                                          (strcasecmp(argv[0], "1"     ) == 0)) {
+                                       CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), CFNumberRef_1);
+                               } else {
+                                       SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
+                                       return FALSE;
+                               }
+
+                               argv++;
+                               argc--;
+                               break;
+                       case isNumber :
+                               if (argc < 1) {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("%s not specified\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "value");
+                                       return FALSE;
+                               }
+
+                               if (strlen(argv[0]) > 0) {
+                                       CFNumberRef     num;
+
+                                       num = _copy_number(argv[0]);
+                                       if (num != NULL) {
+                                               CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), num);
+                                               CFRelease(num);
+                                       } else {
+                                               SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
+                                               return FALSE;
+                                       }
+                               } else {
+                                       CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+                               }
+
+                               argv++;
+                               argc--;
+                               break;
+                       case isString :
+                               if (argc < 1) {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("%s not specified\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "value");
+                                       return FALSE;
+                               }
+
+                               if (strlen(argv[0]) > 0) {
+                                       CFStringRef     str;
+
+                                       str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+                                       CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str);
+                                       CFRelease(str);
+                               } else {
+                                       CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+                               }
+
+                               argv++;
+                               argc--;
+                               break;
+                       case isStringArray :
+                               if (argc < 1) {
+                                       SCPrint(TRUE, stdout,
+                                               CFSTR("%s(s) not specified\n"),
+                                               options[optionIndex].description != NULL ? options[optionIndex].description : "value");
+                                       return FALSE;
+                               }
+
+                               if (strlen(argv[0]) > 0) {
+                                       CFStringRef     str;
+                                       CFArrayRef      str_array;
+
+                                       str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+                                       str_array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+                                       CFRelease(str);
+
+                                       CFDictionarySetValue(newConfiguration, *(options[optionIndex].key), str_array);
+                                       CFRelease(str_array);
+                               } else {
+                                       CFDictionaryRemoveValue(newConfiguration, *(options[optionIndex].key));
+                               }
+
+                               argv++;
+                               argc--;
+                               break;
+               }
+
+               if (options[optionIndex].handler != NULL) {
+                       CFStringRef     key;
+                       int             nArgs;
+
+                       key = options[optionIndex].key != NULL ? *(options[optionIndex].key) : NULL;
+                       nArgs = (*options[optionIndex].handler)(key,
+                                                               options[optionIndex].description,
+                                                               options[optionIndex].info,
+                                                               argc,
+                                                               argv,
+                                                               newConfiguration);
+                       if (nArgs < 0) {
+                               return FALSE;
+                       }
+
+                       argv += nArgs;
+                       argc -= nArgs;
+               }
+       }
+
+       return TRUE;
+}
+
+
+/* -------------------- */
+
+
+#define        N_QUICK 32
+
+__private_extern__
+void
+_show_entity(CFDictionaryRef entity, CFStringRef prefix)
+{
+       CFArrayRef              array;
+       const void *            keys_q[N_QUICK];
+       const void **           keys    = keys_q;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFMutableArrayRef       sorted;
+
+       n = CFDictionaryGetCount(entity);
+       if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) {
+               keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+       }
+       CFDictionaryGetKeysAndValues(entity, keys, NULL);
+
+       array  = CFArrayCreate(NULL, keys, n, &kCFTypeArrayCallBacks);
+       sorted = CFArrayCreateMutableCopy(NULL, n, array);
+       if (n > 1) {
+               CFArraySortValues(sorted,
+                                 CFRangeMake(0, n),
+                                 (CFComparatorFunction)CFStringCompare,
+                                 NULL);
+       }
+
+       for (i = 0; i < n; i++) {
+               CFStringRef     key;
+               CFTypeRef       value;
+
+               key   = CFArrayGetValueAtIndex(sorted, i);
+               value = CFDictionaryGetValue(entity, key);
+               if (isA_CFArray(value)) {
+                       CFStringRef     str;
+
+                       str = CFStringCreateByCombiningStrings(NULL, value, CFSTR(", "));
+                       SCPrint(TRUE, stdout, CFSTR("%@    %@ = (%@)\n"), prefix, key, str);
+                       CFRelease(str);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("%@    %@ = %@\n"), prefix, key, value);
+               }
+       }
+
+       CFRelease(sorted);
+       CFRelease(array);
+       if (keys != keys_q) {
+               CFAllocatorDeallocate(NULL, keys);
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+commitRequired(int argc, char **argv, const char *command)
+{
+       if (net_changed) {
+               if ((currentInput != NULL)                      &&
+                   isatty(fileno(currentInput->fp))            &&
+                   ((argc < 1) || (strcmp(argv[0], "!") != 0))
+                  ) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("configuration changes have not been committed\n"
+                                     "use \"commit\" to save changes"));
+                       if (command != NULL) {
+                               SCPrint(TRUE, stdout,
+                                       CFSTR(" or \"%s !\" to abandon changes"),
+                                       command);
+                       }
+                       SCPrint(TRUE, stdout, CFSTR("\n"));
+                       return TRUE;
+               }
+
+               SCPrint(TRUE, stdout, CFSTR("configuration changes abandoned\n"));
+       }
+
+       return FALSE;
+}
+
+
+__private_extern__
+void
+do_net_init()
+{
+       int     one     = 1;
+       int     zero    = 0;
+
+       CFNumberRef_0 = CFNumberCreate(NULL, kCFNumberIntType, &zero);
+       CFNumberRef_1 = CFNumberCreate(NULL, kCFNumberIntType, &one);
+
+       return;
+}
+
+
+__private_extern__
+void
+do_net_open(int argc, char **argv)
+{
+       CFStringRef     prefsID = NULL;
+
+       if (prefs != NULL) {
+               if (commitRequired(argc, argv, "close")) {
+                       return;
+               }
+               do_net_close(0, NULL);
+       }
+
+       if (argc > 0) {
+               prefsID = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+       }
+
+       prefs = SCPreferencesCreate(NULL, CFSTR("scutil --net"), prefsID);
+       if (prefsID != NULL) CFRelease(prefsID);
+
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       net_changed = FALSE;
+
+       net_set = SCNetworkSetCopyCurrent(prefs);
+       if (net_set != NULL) {
+               CFStringRef     setName;
+
+               setName = SCNetworkSetGetName(net_set);
+               if (setName != NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName);
+               } else {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("set ID \"%@\" selected\n"),
+                               SCNetworkSetGetSetID(net_set));
+               }
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+do_net_commit(int argc, char **argv)
+{
+       if (!SCPreferencesCommitChanges(prefs)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       net_changed = FALSE;
+
+       return;
+}
+
+
+__private_extern__
+void
+do_net_apply(int argc, char **argv)
+{
+       if (!SCPreferencesApplyChanges(prefs)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+       }
+       return;
+}
+
+
+__private_extern__
+void
+do_net_close(int argc, char **argv)
+{
+       if (commitRequired(argc, argv, "close")) {
+               return;
+       }
+
+       if (net_interface != NULL) {
+               CFRelease(net_interface);
+               net_interface = NULL;
+       }
+
+       if (net_service != NULL) {
+               CFRelease(net_service);
+               net_service = NULL;
+       }
+
+       if (net_protocol != NULL) {
+               CFRelease(net_protocol);
+               net_protocol = NULL;
+       }
+
+       if (net_set != NULL) {
+               CFRelease(net_set);
+               net_set = NULL;
+       }
+
+       if (interfaces != NULL) {
+               CFRelease(interfaces);
+               interfaces = NULL;
+       }
+
+       if (services != NULL) {
+               CFRelease(services);
+               services = NULL;
+       }
+
+       if (protocols != NULL) {
+               CFRelease(protocols);
+               protocols = NULL;
+       }
+
+       if (sets != NULL) {
+               CFRelease(sets);
+               sets = NULL;
+       }
+
+       if (new_interfaces != NULL) {
+               CFRelease(new_interfaces);
+               new_interfaces = NULL;
+       }
+
+       if (prefs != NULL) {
+               CFRelease(prefs);
+               prefs = NULL;
+       }
+
+       net_changed = FALSE;
+
+       return;
+}
+
+
+__private_extern__
+void
+do_net_quit(int argc, char **argv)
+{
+       if (commitRequired(argc, argv, "quit")) {
+               return;
+       }
+
+       termRequested = TRUE;
+       return;
+}
+
+
+/* -------------------- */
+
+
+typedef void (*net_func) (int argc, char **argv);
+
+static const struct {
+       char            *key;
+       net_func        create;
+       net_func        disable;
+       net_func        enable;
+       net_func        select;
+       net_func        set;
+       net_func        show;
+       net_func        remove;
+} net_keys[] = {
+
+       { "interfaces", NULL            , NULL            , NULL            ,
+                       NULL            , NULL            , show_interfaces ,
+                       NULL                                                },
+
+       { "interface",  create_interface, NULL            , NULL            ,
+                       select_interface, set_interface   , show_interface  ,
+                       NULL                                                },
+
+       { "services",   NULL            , NULL            , NULL            ,
+                       NULL            , NULL            , show_services   ,
+                       NULL                                                },
+
+       { "service",    create_service  , disable_service , enable_service  ,
+                       select_service  , set_service     , show_service    ,
+                       remove_service                                      },
+
+       { "protocols",  NULL            , NULL            , NULL            ,
+                       NULL            , NULL            , show_protocols  ,
+                       NULL                                                },
+
+       { "protocol",   create_protocol , disable_protocol, enable_protocol ,
+                       select_protocol , set_protocol    , show_protocol   ,
+                       remove_protocol                                     },
+
+       { "sets",       NULL            , NULL            , NULL            ,
+                       NULL            , NULL            , show_sets       ,
+                       NULL                                                },
+
+       { "set",        create_set      , NULL            , NULL            ,
+                       select_set      , set_set         , show_set        ,
+                       remove_set                                          }
+
+};
+#define        N_NET_KEYS      (sizeof(net_keys) / sizeof(net_keys[0]))
+
+
+static int
+findNetKey(char *key)
+{
+       int     i;
+
+       for (i = 0; i < (int)N_NET_KEYS; i++) {
+               if (strcmp(key, net_keys[i].key) == 0) {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+do_net_create(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("create what?\n"));
+               return;
+       }
+
+       if (*net_keys[i].create == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("create what?\n"));
+       }
+
+       (*net_keys[i].create)(argc, argv);
+       return;
+}
+
+
+__private_extern__
+void
+do_net_disable(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
+               return;
+       }
+
+       if (*net_keys[i].disable == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("disable what?\n"));
+       }
+
+       (*net_keys[i].disable)(argc, argv);
+       return;
+}
+
+
+__private_extern__
+void
+do_net_enable(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
+               return;
+       }
+
+       if (*net_keys[i].enable == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("enable what?\n"));
+       }
+
+       (*net_keys[i].enable)(argc, argv);
+       return;
+}
+
+
+__private_extern__
+void
+do_net_remove(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
+               return;
+       }
+
+       if (*net_keys[i].remove == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("remove what?\n"));
+       }
+
+       (*net_keys[i].remove)(argc, argv);
+       return;
+}
+
+
+__private_extern__
+void
+do_net_select(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("select what?\n"));
+               return;
+       }
+
+       if (*net_keys[i].select == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("select what?\n"));
+       }
+
+       (*net_keys[i].select)(argc, argv);
+       return;
+}
+
+
+__private_extern__
+void
+do_net_set(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("set what?\n"));
+               return;
+       }
+
+       (*net_keys[i].set)(argc, argv);
+       return;
+}
+
+
+__private_extern__
+void
+do_net_show(int argc, char **argv)
+{
+       char    *key;
+       int     i;
+
+       key = argv[0];
+       argv++;
+       argc--;
+
+       i = findNetKey(key);
+       if (i < 0) {
+               SCPrint(TRUE, stderr, CFSTR("show what?\n"));
+               return;
+       }
+
+       (*net_keys[i].show)(argc, argv);
+       return;
+}
+
+
+#include "SCPreferencesInternal.h"
+#include <fcntl.h>
+#include <unistd.h>
+__private_extern__
+void
+do_net_snapshot(int argc, char **argv)
+{
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+               return;
+       }
+
+       if (prefs != NULL) {
+               SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+
+               if (prefsPrivate->prefs != NULL) {
+                       int             fd;
+                       static int      n_snapshot      = 0;
+                       char            *path;
+                       CFDataRef       xmlData;
+
+                       asprintf(&path, "/tmp/prefs_snapshot_%d", n_snapshot++);
+                       fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+                       free(path);
+
+                       xmlData = CFPropertyListCreateXMLData(NULL, prefsPrivate->prefs);
+                       if (xmlData != NULL) {
+                               (void) write(fd, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData));
+                               CFRelease(xmlData);
+                       } else {
+                               SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+                       }
+
+                       (void) close(fd);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("prefs have not been accessed\n"));
+               }
+       }
+
+       return;
+}
diff --git a/scutil.tproj/net.h b/scutil.tproj/net.h
new file mode 100644 (file)
index 0000000..ad4a56a
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_H
+#define _NET_H
+
+#include <sys/cdefs.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+
+typedef int (*optionHandler) (CFStringRef              key,
+                             const char                *description,
+                             void                      *info,
+                             int                       argc,
+                             char                      **argv,
+                             CFMutableDictionaryRef    newConfiguration);
+
+typedef enum {
+       isOther,                // use "only" handler function for processing
+       isHelp,
+       isChooseOne,
+       isChooseMultiple,
+       isBoolean,
+       isNumber,
+       isString,
+       isStringArray
+} optionType;
+
+typedef const struct {
+       const CFStringRef       selection;
+       const CFStringRef       *key;
+       const unsigned int      flags;
+} selections;
+#define selectionNotAvailable  1<<0    // if you can't "choose" this selection
+
+typedef const struct {
+       const char              *option;
+       const char              *description;
+       optionType              type;
+       const CFStringRef       *key;
+       optionHandler           handler;
+       void                    *info;
+} options, *optionsRef;
+
+
+extern Boolean                 net_changed;
+                              
+extern CFMutableArrayRef       new_interfaces;
+
+extern CFArrayRef              interfaces;
+extern CFArrayRef              services;
+extern CFArrayRef              protocols;
+extern CFArrayRef              sets;
+
+extern SCNetworkInterfaceRef   net_interface;
+extern SCNetworkServiceRef     net_service;
+extern SCNetworkProtocolRef    net_protocol;
+extern SCNetworkSetRef         net_set;
+
+extern CFNumberRef             CFNumberRef_0;
+extern CFNumberRef             CFNumberRef_1;
+
+
+__BEGIN_DECLS
+
+Boolean                _process_options(optionsRef             options,
+                                int                    nOptions,
+                                int                    argc,
+                                char                   **argv,
+                                CFMutableDictionaryRef newConfiguration);
+
+CFNumberRef    _copy_number    (const char *arg);
+
+CFIndex                _find_option    (const char     *option,
+                                optionsRef     options,
+                                const int      nOptions);
+
+CFIndex                _find_selection (CFStringRef    choice,
+                                selections     choises[],
+                                unsigned int   *flags);
+
+void           _show_entity    (CFDictionaryRef entity, CFStringRef prefix);
+
+void   do_net_init             ();
+void   do_net_quit             ();
+
+void   do_net_open             (int argc, char **argv);
+void   do_net_commit           (int argc, char **argv);
+void   do_net_apply            (int argc, char **argv);
+void   do_net_close            (int argc, char **argv);
+
+void   do_net_create           (int argc, char **argv);
+void   do_net_disable          (int argc, char **argv);
+void   do_net_enable           (int argc, char **argv);
+void   do_net_remove           (int argc, char **argv);
+void   do_net_select           (int argc, char **argv);
+void   do_net_set              (int argc, char **argv);
+void   do_net_show             (int argc, char **argv);
+
+void   do_net_snapshot         (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_H */
diff --git a/scutil.tproj/net_interface.c b/scutil.tproj/net_interface.c
new file mode 100644 (file)
index 0000000..a7bb46c
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+
+#include <SystemConfiguration/LinkConfiguration.h>
+
+
+/* -------------------- */
+
+
+static CFArrayRef
+_copy_interfaces()
+{
+       CFMutableArrayRef       interfaces;
+       CFArrayRef              real_interfaces;
+
+       real_interfaces = SCNetworkInterfaceCopyAll();
+       if (real_interfaces == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return NULL;
+       }
+
+       interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       // include real interfaces
+       CFArrayAppendArray(interfaces,
+                          real_interfaces,
+                          CFRangeMake(0, CFArrayGetCount(real_interfaces)));
+       CFRelease(real_interfaces);
+
+       // include pseudo interfaces
+       CFArrayAppendValue(interfaces, kSCNetworkInterfaceIPv4);
+
+       // include interfaces that we have created
+       if (new_interfaces != NULL) {
+               CFArrayAppendArray(interfaces,
+                                  new_interfaces,
+                                  CFRangeMake(0, CFArrayGetCount(new_interfaces)));
+       }
+
+       return (CFArrayRef)interfaces;
+}
+
+
+__private_extern__
+SCNetworkInterfaceRef
+_find_interface(char *match)
+{
+       Boolean                 allowIndex      = TRUE;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFStringRef             select_name     = NULL;
+       SCNetworkInterfaceRef   selected        = NULL;
+
+       if (strcasecmp(match, "$child") == 0) {
+               if (net_interface == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
+                       goto done;
+               }
+
+               selected = SCNetworkInterfaceGetInterface(net_interface);
+               if(selected == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("no child interface\n"));
+               }
+
+               goto done;
+       } else if (strcasecmp(match, "$service") == 0) {
+               if (net_service == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+                       goto done;
+               }
+
+               selected = SCNetworkServiceGetInterface(net_service);
+               if(selected == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("no interface for service\n"));
+               }
+
+               goto done;
+       }
+
+       if (interfaces == NULL) {
+               interfaces = _copy_interfaces();
+               if (interfaces == NULL) {
+                       return NULL;
+               }
+               allowIndex = FALSE;
+       }
+
+       // try to select the interface by its display name
+
+       select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+       n = CFArrayGetCount(interfaces);
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef   interface;
+               CFStringRef             interfaceName;
+
+               interface = CFArrayGetValueAtIndex(interfaces, i);
+               interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+               if ((interfaceName != NULL) && CFEqual(select_name, interfaceName)) {
+                       if (selected == NULL) {
+                               selected = interface;
+                       } else {
+                               // if multiple interfaces match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the interface by its BSD name
+
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef   interface;
+               CFStringRef             bsd_name        = NULL;
+
+               interface = CFArrayGetValueAtIndex(interfaces, i);
+                while ((interface != NULL) && (bsd_name == NULL)) {
+                        bsd_name = SCNetworkInterfaceGetBSDName(interface);
+                        if (bsd_name == NULL) {
+                                interface = SCNetworkInterfaceGetInterface(interface);
+                        }
+                }
+
+               if ((bsd_name != NULL) && CFEqual(select_name, bsd_name)) {
+                       if (selected == NULL) {
+                               selected = interface;
+                       } else {
+                               // if multiple interfaces match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the interface by its interface type
+
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef   interface;
+               CFStringRef             interfaceType;
+
+               interface = CFArrayGetValueAtIndex(interfaces, i);
+               interfaceType = SCNetworkInterfaceGetInterfaceType(interface);
+               if (CFEqual(select_name, interfaceType)) {
+                       if (selected == NULL) {
+                               selected = interface;
+                       } else {
+                               // if multiple interfaces match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple interfaces match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       if (allowIndex) {
+               char    *end;
+               char    *str    = match;
+               long    val;
+
+               // try to select the interface by its index
+
+               errno = 0;
+               val = strtol(str, &end, 10);
+               if ((*str != '\0') &&
+                   ((*end == '\0') || (*end == '.')) &&
+                   (errno == 0)) {
+                       if ((val > 0) && (val <= n)) {
+                               selected = CFArrayGetValueAtIndex(interfaces, val - 1);
+
+                               if (*end == '.') {
+                                       str = end + 1;
+                                       val = strtol(str, &end, 10);
+                                       if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+                                               while (val-- > 0) {
+                                                       selected = SCNetworkInterfaceGetInterface(selected);
+                                                       if (selected == NULL) {
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("no match\n"));
+
+    done :
+
+       if (select_name != NULL) CFRelease(select_name);
+       return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_interface(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+       CFStringRef             interfaceName;
+       CFStringRef             interfaceType;
+       SCNetworkInterfaceRef   new_interface;
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("what interface type?\n"));
+               return;
+       }
+
+       interfaceType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+       if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
+// xxxxx
+SCPrint(TRUE, stdout, CFSTR("vlan creation not yet supported\n"));
+goto done;
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
+// xxxxx
+SCPrint(TRUE, stdout, CFSTR("bond creation not yet supported\n"));
+goto done;
+       } else {
+               if (argc < 2) {
+                       if (net_interface == NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
+                               goto done;
+                       }
+
+                       interface = net_interface;
+               } else {
+                       interface = _find_interface(argv[1]);
+               }
+
+               if (interface == NULL) {
+                       return;
+               }
+
+               new_interface = SCNetworkInterfaceCreateWithInterface(interface, interfaceType);
+               if (new_interface == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                       goto done;
+               }
+       }
+
+       if (new_interfaces == NULL) {
+               new_interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+       CFArrayAppendValue(new_interfaces, new_interface);
+
+       if (net_interface != NULL) CFRelease(net_interface);
+       net_interface = new_interface;
+
+       interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(net_interface);
+       if (interfaceName == NULL) {
+               interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+       }
+       if (interfaceName == NULL) {
+               interfaceName = SCNetworkInterfaceGetInterfaceType(net_interface);
+       }
+       SCPrint(TRUE, stdout, CFSTR("interface \"%@\" created and selected\n"), interfaceName);
+
+    done :
+
+       CFRelease(interfaceType);
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+select_interface(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+
+       interface = _find_interface(argv[0]);
+
+       if (interface != NULL) {
+               CFStringRef     interfaceName;
+
+               if (net_interface != NULL) CFRelease(net_interface);
+               net_interface = CFRetain(interface);
+
+               interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+               if (interfaceName == NULL) {
+                       interfaceName = SCNetworkInterfaceGetBSDName(interface);
+               }
+               if (interfaceName == NULL) {
+                       interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+               }
+
+               SCPrint(TRUE, stdout, CFSTR("interface \"%@\" selected\n"), interfaceName);
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+_show_interface(SCNetworkInterfaceRef interface, CFStringRef prefix, Boolean showChild)
+{
+       CFDictionaryRef configuration;
+       CFStringRef     if_bsd_name;
+       CFStringRef     if_localized_name;
+       CFStringRef     if_mac_address;
+       CFStringRef     if_type;
+       CFArrayRef      supported;
+
+       if_localized_name = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+       if (if_localized_name != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%@  name                 = %@\n"), prefix, if_localized_name);
+       }
+
+       if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
+       if (if_bsd_name != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%@  interface name       = %@\n"), prefix, if_bsd_name);
+       }
+
+       if_type = SCNetworkInterfaceGetInterfaceType(interface);
+       SCPrint(TRUE, stdout, CFSTR("%@  type                 = %@\n"), prefix, if_type);
+
+       if_mac_address = SCNetworkInterfaceGetHardwareAddressString(interface);
+       if (if_mac_address != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%@  address              = %@\n"), prefix, if_mac_address);
+       }
+
+       configuration = SCNetworkInterfaceGetConfiguration(interface);
+       if ((configuration != NULL) &&
+           CFDictionaryContainsKey(configuration, kSCResvInactive)) {
+               configuration = NULL;
+       }
+
+       if (if_bsd_name != NULL) {
+               CFArrayRef      available;
+               CFDictionaryRef active;
+               int             mtu_cur;
+               int             mtu_min;
+               int             mtu_max;
+
+               if (NetworkInterfaceCopyMTU(if_bsd_name, &mtu_cur, &mtu_min, &mtu_max)) {
+                       char    isCurrent       = '*';
+
+                       if (configuration != NULL) {
+                               int             mtu_req;
+                               CFNumberRef     num;
+
+                               num = CFDictionaryGetValue(configuration, kSCPropNetEthernetMTU);
+                               if (isA_CFNumber(num)) {
+                                       CFNumberGetValue(num, kCFNumberIntType, &mtu_req);
+                                       if (mtu_cur != mtu_req) {
+                                               mtu_cur = mtu_req;
+                                               isCurrent = ' ';
+                                       }
+                               }
+                       }
+
+                       SCPrint(TRUE, stdout, CFSTR("%@  mtu                %c = %ld (%ld < n < %ld)\n"),
+                               prefix,
+                               isCurrent,
+                               mtu_cur,
+                               mtu_min,
+                               mtu_max);
+               }
+
+               if (NetworkInterfaceCopyMediaOptions(if_bsd_name, NULL, &active, &available, TRUE)) {
+                       char            isCurrent       = ' ';
+                       CFArrayRef      options         = NULL;
+                       CFArrayRef      options_req     = NULL;
+                       CFStringRef     subtype         = NULL;
+                       CFStringRef     subtype_req     = NULL;
+
+                       if (configuration != NULL) {
+                               subtype_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaSubType);
+                               options_req = CFDictionaryGetValue(configuration, kSCPropNetEthernetMediaOptions);
+                       }
+
+                       if (subtype_req == NULL) {
+                               subtype_req = CFSTR("autoselect");
+                       }
+
+                       if (active != NULL) {
+                               subtype = CFDictionaryGetValue(active, kSCPropNetEthernetMediaSubType);
+                               options = CFDictionaryGetValue(active, kSCPropNetEthernetMediaOptions);
+                       }
+
+                       if (subtype != NULL) {
+                               if (((subtype_req != NULL) &&
+                                    CFEqual(subtype, subtype_req)) &&
+                                   ((options == options_req) ||
+                                    ((options != NULL) &&
+                                     (options_req != NULL) &&
+                                     CFEqual(options, options_req)))
+                                  ) {
+                                       isCurrent = '*';
+                               } else if ((subtype_req == NULL) ||
+                                          ((subtype_req != NULL) &&
+                                           CFEqual(subtype_req, CFSTR("autoselect")))) {
+                                       // if requested subtype not specified or "autoselect"
+                                       isCurrent = '*';
+                               }
+                       }
+
+                       if (subtype_req != NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("%@  media              %c = %@"),
+                                       prefix,
+                                       isCurrent,
+                                       subtype_req);
+
+                               if ((options_req != NULL) &&
+                                   (CFArrayGetCount(options_req) > 0)) {
+                                       CFStringRef     options_str;
+
+                                       options_str = CFStringCreateByCombiningStrings(NULL, options_req, CFSTR(","));
+                                       SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
+                                       CFRelease(options_str);
+                               }
+
+                               SCPrint(TRUE, stdout, CFSTR("\n"));
+                       }
+
+                       SCPrint(TRUE, stdout, CFSTR("\n"));
+
+                       if (available != NULL) {
+                               CFIndex         i;
+                               CFIndex         n_subtypes;
+                               CFArrayRef      subtypes;
+
+                               subtypes   = NetworkInterfaceCopyMediaSubTypes(available);
+                               n_subtypes = (subtypes != NULL) ? CFArrayGetCount(subtypes) : 0;
+                               for (i = 0; i < n_subtypes; i++) {
+                                       CFIndex         j;
+                                       CFIndex         n_subtype_options;
+                                       CFStringRef     subtype;
+                                       CFArrayRef      subtype_options;
+
+                                       subtype = CFArrayGetValueAtIndex(subtypes, i);
+                                       subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
+                                       n_subtype_options = (subtype_options != NULL) ? CFArrayGetCount(subtype_options) : 0;
+                                       for (j = 0; j < n_subtype_options; j++) {
+                                               char            isCurrent       = ' ';
+                                               CFArrayRef      options;
+
+                                               options = CFArrayGetValueAtIndex(subtype_options, j);
+
+                                               if (((subtype_req != NULL) &&
+                                                    CFEqual(subtype, subtype_req)) &&
+                                                   ((options == options_req) ||
+                                                    ((options != NULL) &&
+                                                     (options_req != NULL) &&
+                                                     CFEqual(options, options_req)))
+                                                  ) {
+                                                       isCurrent = '*';
+                                               }
+
+                                               SCPrint(TRUE, stdout, CFSTR("%@  %s    %c = %@"),
+                                                       prefix,
+                                                       ((i == 0) && (j == 0)) ? "supported media" : "               ",
+                                                       isCurrent,
+                                                       subtype);
+
+                                               if ((options != NULL) &&
+                                                   (CFArrayGetCount(options) > 0)) {
+                                                       CFStringRef     options_str;
+
+                                                       options_str = CFStringCreateByCombiningStrings(NULL, options, CFSTR(","));
+                                                       SCPrint(TRUE, stdout, CFSTR(" <%@>"), options_str);
+                                                       CFRelease(options_str);
+                                               }
+
+                                               SCPrint(TRUE, stdout, CFSTR("\n"));
+                                       }
+                                       CFRelease(subtype_options);
+                               }
+                       }
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("\n"));
+               }
+       }
+
+       supported = SCNetworkInterfaceGetSupportedInterfaceTypes(interface);
+       SCPrint(TRUE, stdout, CFSTR("%@  supported interfaces = "), prefix);
+       if (supported != NULL) {
+               CFIndex i;
+               CFIndex n       = CFArrayGetCount(supported);
+
+               for (i = 0; i < n; i++) {
+                       SCPrint(TRUE, stdout, CFSTR("%s%@"),
+                               (i == 0) ? "" : ", ",
+                               CFArrayGetValueAtIndex(supported, i));
+               }
+       }
+       SCPrint(TRUE, stdout, CFSTR("\n"));
+
+       supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
+       SCPrint(TRUE, stdout, CFSTR("%@  supported protocols  = "), prefix);
+       if (supported != NULL) {
+               CFIndex i;
+               CFIndex n       = CFArrayGetCount(supported);
+
+               for (i = 0; i < n; i++) {
+                       SCPrint(TRUE, stdout, CFSTR("%s%@"),
+                               (i == 0) ? "" : ", ",
+                               CFArrayGetValueAtIndex(supported, i));
+               }
+       }
+       SCPrint(TRUE, stdout, CFSTR("\n"));
+
+       if (configuration != NULL) {
+               CFMutableDictionaryRef  effective;
+
+               effective = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
+
+               // remove known (and already reported) interface configuration keys
+               if (CFDictionaryContainsKey(effective, kSCResvInactive)) {
+                       CFDictionaryRemoveAllValues(effective);
+               }
+               CFDictionaryRemoveValue(effective, kSCPropNetEthernetMTU);
+               CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaSubType);
+               CFDictionaryRemoveValue(effective, kSCPropNetEthernetMediaOptions);
+
+               if (CFDictionaryGetCount(effective) > 0) {
+                       SCPrint(TRUE, stdout, CFSTR("\n%@  per-interface configuration\n"), prefix);
+                       _show_entity(configuration, prefix);
+               }
+
+               CFRelease(effective);
+       }
+
+       if (_sc_debug) {
+               SCPrint(TRUE, stdout, CFSTR("\n%@\n"), interface);
+       }
+
+       interface = SCNetworkInterfaceGetInterface(interface);
+       if (interface != NULL) {
+               CFStringRef     newPrefix;
+
+               newPrefix = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@  "), prefix);
+               SCPrint(TRUE, stdout, CFSTR("\n%@child interface\n"), newPrefix);
+               _show_interface(interface, newPrefix, showChild);
+               CFRelease(newPrefix);
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_interfaces(int argc, char **argv)
+{
+       CFIndex         i;
+       CFIndex         n;
+
+       if (interfaces != NULL) CFRelease(interfaces);
+       interfaces = _copy_interfaces();
+       if (interfaces == NULL) {
+               return;
+       }
+
+       n = CFArrayGetCount(interfaces);
+       for (i = 0; i < n; i++) {
+               CFIndex                 childIndex      = 0;
+               SCNetworkInterfaceRef   interface;
+
+               interface = CFArrayGetValueAtIndex(interfaces, i);
+               do {
+                       CFStringRef     interfaceName;
+                       char            isSelected;
+
+                       interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+                       if (interfaceName == NULL) {
+                               interfaceName = SCNetworkInterfaceGetBSDName(interface);
+                       }
+                       if (interfaceName == NULL) {
+                               interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+                       }
+
+                       isSelected = ' ';
+                       if ((net_interface != NULL) && CFEqual(interface, net_interface)) {
+                               isSelected = '>';
+                       }
+
+                       if (childIndex == 0) {
+                               SCPrint(TRUE, stdout, CFSTR("%c%2d: %@\n"),
+                                       isSelected,
+                                       i + 1,
+                                       interfaceName);
+                       } else {
+                               SCPrint(TRUE, stdout, CFSTR("%c%2d.%d: %@\n"),
+                                       isSelected,
+                                       i + 1,
+                                       childIndex,
+                                       interfaceName);
+                       }
+
+                       interface = SCNetworkInterfaceGetInterface(interface);
+                       childIndex++;
+               } while (interface != NULL);
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+set_interface_bond(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+// xxxxx ("+device", "-device")
+SCPrint(TRUE, stdout, CFSTR("bond interface management not yet supported\n"));
+       return FALSE;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+set_interface_airport(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+SCPrint(TRUE, stdout, CFSTR("airport interface management not yet supported\n"));
+       return FALSE;
+}
+
+
+/* -------------------- */
+
+
+static options ethernetOptions[] = {
+       { "mtu"       , NULL, isNumber     , &kSCPropNetEthernetMTU         , NULL, NULL },
+       { "media"     , NULL, isString     , &kSCPropNetEthernetMediaSubType, NULL, NULL },
+       { "mediaopt"  , NULL, isStringArray, &kSCPropNetEthernetMediaOptions, NULL, NULL },
+
+       { "?"         , NULL , isHelp     , NULL                            , NULL,
+           "\nEthernet configuration commands\n\n"
+           " set interface [mtu n] [media type] [mediaopts opts]\n"
+       }
+};
+#define        N_ETHERNET_OPTIONS      (sizeof(ethernetOptions) / sizeof(ethernetOptions[0]))
+
+
+static Boolean
+set_interface_ethernet(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       CFStringRef     interfaceName;
+       Boolean         ok;
+
+       interfaceName = SCNetworkInterfaceGetBSDName(net_interface);
+       if (interfaceName == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("no BSD interface\n"));
+               return FALSE;
+       }
+
+       ok = _process_options(ethernetOptions, N_ETHERNET_OPTIONS, argc, argv, newConfiguration);
+       if (ok) {
+               CFNumberRef     mtu;
+               CFArrayRef      options;
+               CFStringRef     subtype;
+
+               // validate configuration
+
+               mtu = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMTU);
+               if (isA_CFNumber(mtu)) {
+                       int     mtu_max;
+                       int     mtu_min;
+                       int     mtu_val;
+
+                       if (!NetworkInterfaceCopyMTU(interfaceName, NULL, &mtu_min, &mtu_max)) {
+                               SCPrint(TRUE, stdout, CFSTR("cannot set MTU\n"));
+                               return FALSE;
+                       }
+
+                       if (!CFNumberGetValue(mtu, kCFNumberIntType, &mtu_val) ||
+                           (mtu_val < mtu_min) ||
+                           (mtu_val > mtu_max)) {
+                               SCPrint(TRUE, stdout, CFSTR("mtu out of range\n"));
+                               return FALSE;
+                       }
+               }
+
+               subtype = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaSubType);
+               options = CFDictionaryGetValue(newConfiguration, kSCPropNetEthernetMediaOptions);
+
+               if (subtype != NULL) {
+                       CFArrayRef      available       = NULL;
+                       CFArrayRef      config_options  = options;
+                       CFArrayRef      subtypes        = NULL;
+                       CFArrayRef      subtype_options = NULL;
+
+                       ok = FALSE;
+
+                       if (options == NULL) {
+                               config_options = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
+                       }
+
+                       if (interfaceName == NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("media type / options not available\n"));
+                               goto checked;
+                       }
+
+                       if (!NetworkInterfaceCopyMediaOptions(interfaceName, NULL, NULL, &available, FALSE)) {
+                               SCPrint(TRUE, stdout, CFSTR("media type / options not available\n"));
+                               goto checked;
+                       }
+
+                       if (available == NULL) {
+                               goto checked;
+                       }
+
+                       subtypes = NetworkInterfaceCopyMediaSubTypes(available);
+                       if ((subtypes == NULL) ||
+                           !CFArrayContainsValue(subtypes,
+                                                CFRangeMake(0, CFArrayGetCount(subtypes)),
+                                                subtype)) {
+                               SCPrint(TRUE, stdout, CFSTR("media type not valid\n"));
+                               goto checked;
+                       }
+
+                       subtype_options = NetworkInterfaceCopyMediaSubTypeOptions(available, subtype);
+                       if ((subtype_options == NULL) ||
+                           !CFArrayContainsValue(subtype_options,
+                                                 CFRangeMake(0, CFArrayGetCount(subtype_options)),
+                                                 config_options)) {
+                               SCPrint(TRUE, stdout, CFSTR("media options not valid for \"%@\"\n"), subtype);
+                               goto checked;
+                       }
+
+                       if (options == NULL) {
+                               CFDictionarySetValue(newConfiguration, kSCPropNetEthernetMediaOptions, config_options);
+                       }
+
+                       ok = TRUE;
+
+                   checked :
+
+                       if (available       != NULL)    CFRelease(available);
+                       if (subtypes        != NULL)    CFRelease(subtypes);
+                       if (subtype_options != NULL)    CFRelease(subtype_options);
+                       if (options         == NULL)    CFRelease(config_options);
+               } else {
+                       if (options != NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("media type and options must both be specified\n"));
+                               return FALSE;
+                       }
+               }
+       }
+
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+static selections modemDialSelections[] = {
+       { CFSTR("ignore"), &kSCValNetModemDialModeIgnoreDialTone , 0 },
+       { CFSTR("manual"), &kSCValNetModemDialModeManual         , 0 },
+       { CFSTR("wait")  , &kSCValNetModemDialModeWaitForDialTone, 0 },
+       { NULL           , NULL                                  , 0 }
+};
+
+static options modemOptions[] = {
+       { "ConnectionScript"             , "script", isString   , &kSCPropNetModemConnectionScript           , NULL, NULL                        },
+       { "DialMode"                     , "mode"  , isChooseOne, &kSCPropNetModemDialMode                   , NULL, (void *)modemDialSelections },
+       { "CallWaiting"                  , NULL    , isBoolean  , &kSCPropNetModemHoldEnabled                , NULL, NULL                        },
+       { "CallWaitingAlert"             , NULL    , isBoolean  , &kSCPropNetModemHoldCallWaitingAudibleAlert, NULL, NULL                        },
+       { "CallWaitingDisconnectOnAnswer", NULL    , isBoolean  , &kSCPropNetModemHoldDisconnectOnAnswer     , NULL, NULL                        },
+       { "DataCompression"              , NULL    , isBoolean  , &kSCPropNetModemDataCompression            , NULL, NULL                        },
+       { "ErrorCorrection"              , NULL    , isBoolean  , &kSCPropNetModemErrorCorrection            , NULL, NULL                        },
+       { "HoldReminder"                 , NULL    , isBoolean  , &kSCPropNetModemHoldReminder               , NULL, NULL                        },
+       { "HoldReminderTime"             , "time"  , isNumber   , &kSCPropNetModemHoldReminderTime           , NULL, NULL                        },
+       { "PulseDial"                    , NULL    , isBoolean  , &kSCPropNetModemPulseDial                  , NULL, NULL                        },
+       { "Speaker"                      , NULL    , isBoolean  , &kSCPropNetModemSpeaker                    , NULL, NULL                        },
+
+       { "?"                            , NULL    , isHelp     , NULL                                       , NULL,
+           "\nModem configuration commands\n\n"
+           " set interface [ConnectionScript connection-script]\n"
+           " set interface [CallWaiting {enable|disable}]\n"
+           " set interface [CallWaitingAlert {enable|disable}]\n"
+           " set interface [CallWaitingDisconnectOnAnswer {enable|disable}]\n"
+           " set interface [DialMode {ignore|wait}]\n"
+           " set interface [DataCompression {enable|disable}]\n"
+           " set interface [ErrorCorrection {enable|disable}]\n"
+           " set interface [HoldReminder {enable|disable}]\n"
+           " set interface [HoldReminderTime n]\n"
+           " set interface [PulseDial {enable|disable}]\n"
+           " set interface [Speaker {enable|disable}]"
+       }
+};
+#define        N_MODEM_OPTIONS (sizeof(modemOptions) / sizeof(modemOptions[0]))
+
+
+static Boolean
+set_interface_modem(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(modemOptions, N_MODEM_OPTIONS, argc, argv, newConfiguration);
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+static int
+__doPPPAuthPW(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("PPP password not specified\n"));
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               CFStringRef     encryptionType;
+
+               encryptionType = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
+               if (encryptionType == NULL) {
+                       CFIndex                 n;
+                       CFMutableDataRef        pw;
+                       CFStringRef             str;
+
+                       str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+                       n = CFStringGetLength(str);
+                       pw = CFDataCreateMutable(NULL, n * sizeof(UniChar));
+                       CFDataSetLength(pw, n * sizeof(UniChar));
+                       CFStringGetCharacters(str,
+                                             CFRangeMake(0, n),
+                                             (UniChar *)CFDataGetMutableBytePtr(pw));
+                       CFRelease(str);
+
+                       CFDictionarySetValue(newConfiguration, key, pw);
+                       CFRelease(pw);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("PPP password type \"%@\" not supported\n"), encryptionType);
+                       return -1;
+               }
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       return 1;
+}
+
+
+static int
+__doPPPAuthPWType(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("PPP password type mode not specified\n"));
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               if (strcasecmp(argv[0], "keychain") == 0) {
+                       CFDictionarySetValue(newConfiguration, key, kSCValNetPPPAuthPasswordEncryptionKeychain);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("invalid password type\n"));
+                       return -1;
+               }
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       // encryption type changed, reset password
+       CFDictionaryRemoveValue(newConfiguration, kSCPropNetPPPAuthPassword);
+
+       return 1;
+}
+
+
+static selections authPromptSelections[] = {
+       { CFSTR("before"), &kSCValNetPPPAuthPromptBefore, 0 },
+       { CFSTR("after") , &kSCValNetPPPAuthPromptAfter , 0 },
+       { NULL    , NULL                                , 0 }
+};
+
+
+static selections authProtocolSelections[] = {
+       { CFSTR("CHAP")   , &kSCValNetPPPAuthProtocolCHAP   , 0 },
+       { CFSTR("EAP")    , &kSCValNetPPPAuthProtocolEAP    , 0 },
+       { CFSTR("MSCHAP1"), &kSCValNetPPPAuthProtocolMSCHAP1, 0 },
+       { CFSTR("MSCHAP2"), &kSCValNetPPPAuthProtocolMSCHAP2, 0 },
+       { CFSTR("PAP")    , &kSCValNetPPPAuthProtocolPAP    , 0 },
+       { NULL            , NULL                            , 0 }
+};
+
+
+static options pppOptions[] = {
+       { "ACSP"                      , NULL          , isBoolean        , &kSCPropNetPPPACSPEnabled               , NULL             , NULL                           },
+       { "ConnectTime"               , "?time"       , isNumber         , &kSCPropNetPPPConnectTime               , NULL             , NULL                           },
+       { "DialOnDemand"              , NULL          , isBoolean        , &kSCPropNetPPPDialOnDemand              , NULL             , NULL                           },
+       { "DisconnectOnFastUserSwitch", NULL          , isBoolean        , &kSCPropNetPPPDisconnectOnFastUserSwitch, NULL             , NULL                           },
+       { "DisconnectOnIdle"          , NULL          , isBoolean        , &kSCPropNetPPPDisconnectOnIdle          , NULL             , NULL                           },
+       { "DisconnectOnIdleTimer"     , "timeout"     , isNumber         , &kSCPropNetPPPDisconnectOnIdleTimer     , NULL             , NULL                           },
+       { "DisconnectOnLogout"        , NULL          , isBoolean        , &kSCPropNetPPPDisconnectOnLogout        , NULL             , NULL                           },
+       { "DisconnectOnSleep"         , NULL          , isBoolean        , &kSCPropNetPPPDisconnectOnSleep         , NULL             , NULL                           },
+       { "DisconnectTime"            , "?time"       , isNumber         , &kSCPropNetPPPDisconnectTime            , NULL             , NULL                           },
+       { "IdleReminder"              , NULL          , isBoolean        , &kSCPropNetPPPIdleReminder              , NULL             , NULL                           },
+       { "IdleReminderTimer"         , "time"        , isNumber         , &kSCPropNetPPPIdleReminderTimer         , NULL             , NULL                           },
+       { "Logfile"                   , "path"        , isString         , &kSCPropNetPPPLogfile                   , NULL             , NULL                           },
+       { "Plugins"                   , "plugin"      , isStringArray    , &kSCPropNetPPPPlugins                   , NULL             , NULL                           },
+       { "RetryConnectTime"          , "time"        , isNumber         , &kSCPropNetPPPRetryConnectTime          , NULL             , NULL                           },
+       { "SessionTimer"              , "time"        , isNumber         , &kSCPropNetPPPSessionTimer              , NULL             , NULL                           },
+       { "UseSessionTimer"           , NULL          , isBoolean        , &kSCPropNetPPPUseSessionTimer           , NULL             , NULL                           },
+       { "VerboseLogging"            , NULL          , isBoolean        , &kSCPropNetPPPVerboseLogging            , NULL             , NULL                           },
+
+       // --- Auth: ---
+       { "AuthEAPPlugins"            , "plugin"      , isStringArray    , &kSCPropNetPPPAuthEAPPlugins            , NULL             , NULL                           },
+       { "AuthName"                  , "account"     , isString         , &kSCPropNetPPPAuthName                  , NULL             , NULL                           },
+       {   "Account"                 , "account"     , isString         , &kSCPropNetPPPAuthName                  , NULL             , NULL                           },
+       { "AuthPassword"              , "password"    , isOther          , &kSCPropNetPPPAuthPassword              , __doPPPAuthPW    , NULL                           },
+       {   "Password"                , "password"    , isOther          , &kSCPropNetPPPAuthPassword              , __doPPPAuthPW    , NULL                           },
+       { "AuthPasswordEncryption"    , "type"        , isOther          , &kSCPropNetPPPAuthPasswordEncryption    , __doPPPAuthPWType, NULL                           },
+       { "AuthPrompt"                , "before/after", isChooseOne      , &kSCPropNetPPPAuthPrompt                , NULL             , (void *)authPromptSelections   },
+       { "AuthProtocol"              , "protocol"    , isChooseMultiple , &kSCPropNetPPPAuthProtocol              , NULL             , (void *)authProtocolSelections },
+
+       // --- Comm: ---
+       { "CommRemoteAddress"         , "phone#"      , isString         , &kSCPropNetPPPCommRemoteAddress         , NULL             , NULL                           },
+       { "CommAlternateRemoteAddress", "phone#"      , isString         , &kSCPropNetPPPCommAlternateRemoteAddress, NULL             , NULL                           },
+       { "CommConnectDelay"          , "time"        , isNumber         , &kSCPropNetPPPCommConnectDelay          , NULL             , NULL                           },
+       { "CommDisplayTerminalWindow" , NULL          , isBoolean        , &kSCPropNetPPPCommDisplayTerminalWindow , NULL             , NULL                           },
+       { "CommRedialCount"           , "retry count" , isNumber         , &kSCPropNetPPPCommRedialCount           , NULL             , NULL                           },
+       { "CommRedialEnabled"         , NULL          , isBoolean        , &kSCPropNetPPPCommRedialEnabled         , NULL             , NULL                           },
+       { "CommRedialInterval"        , "retry delay" , isNumber         , &kSCPropNetPPPCommRedialInterval        , NULL             , NULL                           },
+       { "CommTerminalScript"        , "script"      , isString         , &kSCPropNetPPPCommTerminalScript        , NULL             , NULL                           },
+       { "CommUseTerminalScript"     , NULL          , isBoolean        , &kSCPropNetPPPCommUseTerminalScript     , NULL             , NULL                           },
+
+       // --- CCP: ---
+       { "CCPEnabled"                , NULL          , isBoolean        , &kSCPropNetPPPCCPEnabled                , NULL             , NULL                           },
+       { "CCPMPPE40Enabled"          , NULL          , isBoolean        , &kSCPropNetPPPCCPMPPE40Enabled          , NULL             , NULL                           },
+       { "CCPMPPE128Enabled"         , NULL          , isBoolean        , &kSCPropNetPPPCCPMPPE128Enabled         , NULL             , NULL                           },
+
+       // --- IPCP: ---
+       { "IPCPCompressionVJ"         , NULL          , isBoolean        , &kSCPropNetPPPIPCPCompressionVJ         , NULL             , NULL                           },
+       { "IPCPUsePeerDNS"            , NULL          , isBoolean        , &kSCPropNetPPPIPCPUsePeerDNS            , NULL             , NULL                           },
+
+       // --- LCP: ---
+       { "LCPEchoEnabled"            , NULL          , isBoolean        , &kSCPropNetPPPLCPEchoEnabled            , NULL             , NULL                           },
+       { "LCPEchoFailure"            , NULL          , isNumber         , &kSCPropNetPPPLCPEchoFailure            , NULL             , NULL                           },
+       { "LCPEchoInterval"           , NULL          , isNumber         , &kSCPropNetPPPLCPEchoInterval           , NULL             , NULL                           },
+       { "LCPCompressionACField"     , NULL          , isBoolean        , &kSCPropNetPPPLCPCompressionACField     , NULL             , NULL                           },
+       { "LCPCompressionPField"      , NULL          , isBoolean        , &kSCPropNetPPPLCPCompressionPField      , NULL             , NULL                           },
+       { "LCPMRU"                    , NULL          , isNumber         , &kSCPropNetPPPLCPMRU                    , NULL             , NULL                           },
+       { "LCPMTU"                    , NULL          , isNumber         , &kSCPropNetPPPLCPMTU                    , NULL             , NULL                           },
+       { "LCPReceiveACCM"            , NULL          , isNumber         , &kSCPropNetPPPLCPReceiveACCM            , NULL             , NULL                           },
+       { "LCPTransmitACCM"           , NULL          , isNumber         , &kSCPropNetPPPLCPTransmitACCM           , NULL             , NULL                           },
+
+       // --- Help ---
+       { "?"                         , NULL          , isHelp           , NULL                                    , NULL             ,
+           "\nPPP configuration commands\n\n"
+           " set interface [Account account]\n"
+           " set interface [Password password]\n"
+           " set interface [Number telephone-number]\n"
+           " set interface [AlternateNumber telephone-number]\n"
+           " set interface [IdleReminder {enable|disable}]\n"
+           " set interface [IdleReminderTimer time-in-seconds]\n"
+           " set interface [DisconnectOnIdle {enable|disable}]\n"
+           " set interface [DisconnectOnIdleTimer time-in-seconds]\n"
+           " set interface [DisconnectOnLogout {enable|disable}]"
+       }
+};
+#define        N_PPP_OPTIONS   (sizeof(pppOptions) / sizeof(pppOptions[0]))
+
+
+static Boolean
+set_interface_ppp(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(pppOptions, N_PPP_OPTIONS, argc, argv, newConfiguration);
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+static Boolean
+set_interface_vlan(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+// xxxxx ("device", "tag")
+SCPrint(TRUE, stdout, CFSTR("vlan interface management not yet supported\n"));
+       return FALSE;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+set_interface(int argc, char **argv)
+{
+       CFDictionaryRef         configuration;
+       CFStringRef             interfaceType;
+       CFMutableDictionaryRef  newConfiguration        = NULL;
+       Boolean                 ok                      = FALSE;
+
+       if (net_interface == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
+               return;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+               return;
+       }
+
+       configuration = SCNetworkInterfaceGetConfiguration(net_interface);
+       if (configuration == NULL) {
+               newConfiguration = CFDictionaryCreateMutable(NULL,
+                                                            0,
+                                                            &kCFTypeDictionaryKeyCallBacks,
+                                                            &kCFTypeDictionaryValueCallBacks);
+       } else {
+               newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
+               CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
+       }
+
+       interfaceType = SCNetworkInterfaceGetInterfaceType(net_interface);
+
+       if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBond)) {
+               ok = set_interface_bond(argc, argv, newConfiguration);
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeEthernet)) {
+               ok = set_interface_ethernet(argc, argv, newConfiguration);
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeModem)) {
+               ok = set_interface_modem(argc, argv, newConfiguration);
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIEEE80211)) {
+               ok = set_interface_airport(argc, argv, newConfiguration);
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) {
+               ok = set_interface_ppp(argc, argv, newConfiguration);
+       } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVLAN)) {
+               ok = set_interface_vlan(argc, argv, newConfiguration);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("this interfaces configuration cannot be changed\n"));
+       }
+
+       if (!ok) {
+               goto done;
+       }
+
+       if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
+           ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
+               if (!SCNetworkInterfaceSetConfiguration(net_interface, newConfiguration)) {
+                       if (SCError() == kSCStatusNoKey) {
+                               SCPrint(TRUE, stdout, CFSTR("could not update per-service interface configuration\n"));
+                       } else {
+                               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                       }
+                       goto done;
+               }
+
+               net_changed = TRUE;
+       }
+
+    done :
+
+       if (newConfiguration != NULL) CFRelease(newConfiguration);
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_interface(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+
+       if (argc == 1) {
+               interface = _find_interface(argv[0]);
+       } else {
+               if (net_interface != NULL) {
+                       interface = net_interface;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("interface not selected\n"));
+                       return;
+               }
+       }
+
+       if (interface != NULL) {
+               _show_interface(interface, CFSTR(""), TRUE);
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFStringRef
+_interface_description(SCNetworkInterfaceRef interface)
+{
+       CFMutableStringRef      description;
+       CFStringRef             if_bsd_name;
+       CFStringRef             if_type;
+
+       description = CFStringCreateMutable(NULL, 0);
+
+       if_type = SCNetworkInterfaceGetInterfaceType(interface);
+       CFStringAppend(description, if_type);
+
+       if_bsd_name = SCNetworkInterfaceGetBSDName(interface);
+       if (if_bsd_name != NULL) {
+               CFStringAppendFormat(description, NULL, CFSTR(" (%@)"), if_bsd_name);
+       }
+
+       interface = SCNetworkInterfaceGetInterface(interface);
+       while ((interface != NULL) &&
+              !CFEqual(interface, kSCNetworkInterfaceIPv4)) {
+               CFStringRef     childDescription;
+
+               childDescription = _interface_description(interface);
+               CFStringAppendFormat(description, NULL, CFSTR(" / %@"), childDescription);
+               CFRelease(childDescription);
+
+               interface = SCNetworkInterfaceGetInterface(interface);
+       }
+
+       return description;
+}
diff --git a/scutil.tproj/net_interface.h b/scutil.tproj/net_interface.h
new file mode 100644 (file)
index 0000000..780a84c
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_INTERFACE_H
+#define _NET_INTERFACE_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+CFStringRef            _interface_description  (SCNetworkInterfaceRef interface);
+SCNetworkInterfaceRef  _find_interface         (char *match);
+
+void   create_interface        (int argc, char **argv);
+void   select_interface        (int argc, char **argv);
+void   set_interface           (int argc, char **argv);
+void   show_interface          (int argc, char **argv);
+void   show_interfaces         (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_INTERFACE_H */
diff --git a/scutil.tproj/net_protocol.c b/scutil.tproj/net_protocol.c
new file mode 100644 (file)
index 0000000..49a3329
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+#include "net_protocol.h"
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFComparisonResult
+_compare_protocols(const void *val1, const void *val2, void *context)
+{
+       SCNetworkProtocolRef    p1      = (SCNetworkProtocolRef)val1;
+       SCNetworkProtocolRef    p2      = (SCNetworkProtocolRef)val2;
+       CFStringRef             type1;
+       CFStringRef             type2;
+
+       type1 = SCNetworkProtocolGetProtocolType(p1);
+       type2 = SCNetworkProtocolGetProtocolType(p2);
+
+       return CFStringCompare(type1, type2, 0);
+}
+
+
+static CFStringRef
+__copyIPv4Address(const char *arg)
+{
+       char                    buf[128];
+       struct sockaddr_in      sin;
+
+       bzero(&sin, sizeof(sin));
+       sin.sin_len    = sizeof(sin);
+       sin.sin_family = AF_INET;
+       if (inet_aton(arg, &sin.sin_addr) != 1) {
+               return NULL;
+       }
+
+       _SC_sockaddr_to_string((struct sockaddr *)&sin, buf, sizeof(buf));
+       return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
+}
+
+
+static CFStringRef
+__copyIPv6Address(const char *arg)
+{
+       char                    buf[128];
+       char                    *p;
+       struct sockaddr_in6     sin6;
+
+       bzero(&sin6, sizeof(sin6));
+       sin6.sin6_len    = sizeof(sin6);
+       sin6.sin6_family = AF_INET6;
+       if (inet_pton(AF_INET6, arg, &sin6.sin6_addr) != 1) {
+               return NULL;
+       }
+
+       p = strchr(arg, '%');
+       if (p != NULL) {
+               sin6.sin6_scope_id = if_nametoindex(p+1);
+       }
+
+       _SC_sockaddr_to_string((struct sockaddr *)&sin6, buf, sizeof(buf));
+       return CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
+}
+
+
+/* -------------------- */
+
+
+static SCNetworkProtocolRef
+_find_protocol(char *match)
+{
+       Boolean                 allowIndex      = TRUE;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFStringRef             select_name     = NULL;
+       SCNetworkProtocolRef    selected        = NULL;
+
+       if (protocols == NULL) {
+               if (net_service == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("network service not selected\n"));
+                       return NULL;
+               }
+
+               protocols = SCNetworkServiceCopyProtocols(net_service);
+               if (protocols == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                       return NULL;
+               }
+
+               n = CFArrayGetCount(protocols);
+               if (n > 1) {
+                       CFMutableArrayRef       sorted;
+
+                       sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+                       CFArraySortValues(sorted,
+                                         CFRangeMake(0, n),
+                                         _compare_protocols,
+                                         NULL);
+                       CFRelease(protocols);
+                       protocols = sorted;
+               }
+
+               allowIndex = FALSE;
+       }
+
+       // try to select the protocol by its protocol type
+
+       select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+       n = CFArrayGetCount(protocols);
+       for (i = 0; i < n; i++) {
+               SCNetworkProtocolRef    protocol;
+               CFStringRef             type;
+
+               protocol = CFArrayGetValueAtIndex(protocols, i);
+               type     = SCNetworkProtocolGetProtocolType(protocol);
+               if (CFStringCompare(select_name, type, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                       selected = protocol;
+                       goto done;
+               }
+       }
+
+       if (allowIndex) {
+               char    *end;
+               char    *str    = match;
+               long    val;
+
+               // try to select the protocol by its index
+
+               errno = 0;
+               val = strtol(str, &end, 10);
+               if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+                       if ((val > 0) && (val <= n)) {
+                               selected = CFArrayGetValueAtIndex(protocols, val - 1);
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("no match, which protocol?\n"));
+
+    done :
+
+       if (select_name != NULL) CFRelease(select_name);
+       return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_protocol(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+       CFStringRef             protocolType;
+
+       if ((argc < 1) || (strlen(argv[0]) == 0)) {
+               SCPrint(TRUE, stdout, CFSTR("what protocol type?\n"));
+               return;
+       }
+
+       if (net_service == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network service not selected\n"));
+               return;
+       }
+
+       protocolType = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+       interface = SCNetworkServiceGetInterface(net_service);
+       if (interface != NULL) {
+               CFArrayRef      supported;
+               CFIndex         i;
+               CFIndex         n;
+
+               supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
+               n = (supported != NULL) ? CFArrayGetCount(supported) : 0;
+               for (i = 0; i < n; i++) {
+                       CFStringRef     supportedType;
+
+                       supportedType = CFArrayGetValueAtIndex(supported, i);
+                       if (CFStringCompare(protocolType,
+                                           supportedType,
+                                           kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                               CFRelease(protocolType);
+                               protocolType = CFRetain(supportedType);
+                               break;
+                       }
+               }
+       }
+
+       if (!SCNetworkServiceAddProtocolType(net_service, protocolType)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               goto done;
+       }
+
+       net_changed = TRUE;
+
+       if (protocols != NULL) {
+               CFRelease(protocols);
+               protocols = NULL;
+       }
+
+       if (net_protocol != NULL) CFRelease(net_protocol);
+//     net_protocol = NULL;
+
+       net_protocol = SCNetworkServiceCopyProtocol(net_service, protocolType);
+       if (net_protocol == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               goto done;
+       }
+
+       SCPrint(TRUE, stdout,
+               CFSTR("protocol \"%@\" selected\n"),
+               protocolType);
+
+    done :
+
+       CFRelease(protocolType);
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+disable_protocol(int argc, char **argv)
+{
+       SCNetworkProtocolRef    protocol        = NULL;
+
+       if (argc > 0) {
+               protocol = _find_protocol(argv[0]);
+       } else {
+               if (net_protocol != NULL) {
+                       protocol = net_protocol;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+                       return;
+               }
+       }
+
+       if (protocol == NULL) {
+               return;
+       }
+
+       if (!SCNetworkProtocolSetEnabled(protocol, FALSE)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       net_changed = TRUE;
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+enable_protocol(int argc, char **argv)
+{
+       SCNetworkProtocolRef    protocol        = NULL;
+
+       if (argc > 0) {
+               protocol = _find_protocol(argv[0]);
+       } else {
+               if (net_protocol != NULL) {
+                       protocol = net_protocol;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+                       return;
+               }
+       }
+
+       if (protocol == NULL) {
+               return;
+       }
+
+       if (!SCNetworkProtocolSetEnabled(protocol, TRUE)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       net_changed = TRUE;
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+remove_protocol(int argc, char **argv)
+{
+       SCNetworkProtocolRef    protocol        = NULL;
+       CFStringRef             protocolType;
+
+       if (argc > 0) {
+               protocol = _find_protocol(argv[0]);
+       } else {
+               if (net_protocol != NULL) {
+                       protocol = net_protocol;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+                       return;
+               }
+       }
+
+       if (protocol == NULL) {
+               return;
+       }
+
+       CFRetain(protocol);
+
+       protocolType = SCNetworkProtocolGetProtocolType(protocol);
+       if (!SCNetworkServiceRemoveProtocolType(net_service, protocolType)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               goto done;
+       }
+
+       net_changed = TRUE;
+
+       SCPrint(TRUE, stdout,
+               CFSTR("protocol \"%@\" removed\n"),
+               protocolType);
+
+       if ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) {
+               CFRelease(net_protocol);
+               net_protocol = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+       }
+
+       if (protocols != NULL) {
+               CFRelease(protocols);
+               protocols = NULL;
+       }
+
+    done :
+
+       CFRelease(protocol);
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+select_protocol(int argc, char **argv)
+{
+       SCNetworkProtocolRef    protocol;
+
+       protocol = _find_protocol(argv[0]);
+
+       if (protocol == NULL) {
+               return;
+       }
+
+       if (net_protocol != NULL) CFRelease(net_protocol);
+       net_protocol = CFRetain(protocol);
+
+       SCPrint(TRUE, stdout,
+               CFSTR("protocol \"%@\" selected\n"),
+               SCNetworkProtocolGetProtocolType(protocol));
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+static selections appletalkConfigMethods[] = {
+       { CFSTR("node")      , &kSCValNetAppleTalkConfigMethodNode      , 0 },
+       { CFSTR("router")    , &kSCValNetAppleTalkConfigMethodRouter    , 0 },
+       { CFSTR("seedrouter"), &kSCValNetAppleTalkConfigMethodSeedRouter, 0 },
+       { NULL               , NULL                                     , 0 }
+};
+
+
+static int
+__doAppleTalkConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       CFStringRef     configMethod;
+
+       configMethod = CFDictionaryGetValue(newConfiguration, key);
+       if (!CFEqual(key, kSCValNetAppleTalkConfigMethodSeedRouter)) {
+               CFDictionaryRemoveValue(newConfiguration, kSCPropNetAppleTalkSeedZones);
+               CFDictionaryRemoveValue(newConfiguration, kSCPropNetAppleTalkSeedNetworkRange);
+       }
+
+       return 0;
+}
+
+
+static int
+__doAppleTalkNetworkRange(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("network range not specified\n"));
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               CFArrayRef      array;
+               char            *cp;
+               CFNumberRef     range[2];
+
+               range[0] = _copy_number(argv[0]);
+               if (range[0] == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("invalid start of range\n"));
+                       return -1;
+               }
+
+               cp = strchr(argv[0], '-');
+               if (cp == NULL) {
+                       range[1] = _copy_number(cp);
+                       if (range[1] == NULL) {
+                               CFRelease(range[0]);
+                               SCPrint(TRUE, stdout, CFSTR("invalid end of range\n"));
+                               return -1;
+                       }
+               } else {
+                       range[1] = CFRetain(range[0]);
+               }
+
+               array = CFArrayCreate(NULL,
+                                     (const void **)range,
+                                     sizeof(range)/sizeof(range[0]),
+                                     &kCFTypeArrayCallBacks);
+               CFRelease(range[0]);
+               CFRelease(range[1]);
+
+               CFDictionarySetValue(newConfiguration, key, array);
+               CFRelease(array);
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       return 1;
+}
+
+
+static options appletalkOptions[] = {
+       { "ConfigMethod"    , "configuration method"
+                                      , isChooseOne  , &kSCPropNetAppleTalkConfigMethod    , __doAppleTalkConfigMethod, (void *)appletalkConfigMethods },
+       {   "config"        , "configuration method"
+                                      , isChooseOne  , &kSCPropNetAppleTalkConfigMethod    , __doAppleTalkConfigMethod, (void *)appletalkConfigMethods },
+       { "DefaultZone"     , "zone"   , isString     , &kSCPropNetAppleTalkDefaultZone     , NULL                     , NULL                           },
+       { "NodeID"          , "node"   , isNumber     , &kSCPropNetAppleTalkNodeID          , NULL                     , NULL                           },
+       { "NetworkID"       , "network", isNumber     , &kSCPropNetAppleTalkNetworkID       , NULL                     , NULL                           },
+       { "SeedNetworkRange", "range"  , isOther      , &kSCPropNetAppleTalkSeedNetworkRange, __doAppleTalkNetworkRange, NULL                           },
+       { "SeedZones"       , "zone"   , isStringArray, &kSCPropNetAppleTalkSeedZones       , NULL                     , NULL                           },
+
+       { "?"               , NULL   , isHelp       , NULL                                , NULL                     ,
+           "\nAppleTalk configuration commands\n\n"
+           " set protocol config {Node|Router|SeedRouter}\n"
+           " set protocol defaultzone zone\n"
+           " set protocol node id\n"
+           " set protocol network id\n"
+           "\n w/config=Node\n"
+           "   None\n"
+           "\n w/config=Router\n"
+           "   None\n"
+           "\n w/config=SeedRouter\n"
+           "   set protocol seednetworkrange low[-high]\n"
+           "   set protocol seedzones zone[,zone-2]\n"
+       }
+};
+#define        N_APPLETALK_OPTIONS     (sizeof(appletalkOptions) / sizeof(appletalkOptions[0]))
+
+
+static Boolean
+set_protocol_appletalk(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(appletalkOptions, N_APPLETALK_OPTIONS, argc, argv, newConfiguration);
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+static CFStringRef
+__cleanupDomainName(CFStringRef domain)
+{
+       CFMutableStringRef      newDomain;
+
+       newDomain = CFStringCreateMutableCopy(NULL, 0, domain);
+       CFStringTrimWhitespace(newDomain);
+       CFStringTrim(newDomain, CFSTR("."));
+       if (CFStringGetLength(newDomain) == 0) {
+               CFRelease(newDomain);
+               newDomain = NULL;
+       }
+
+       return newDomain;
+}
+
+
+static int
+__doDNSDomain(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("DNS domain name not specified\n"));
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               CFStringRef     domain;
+               CFStringRef     str;
+
+               str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               domain = __cleanupDomainName(str);
+               CFRelease(str);
+
+               if (domain != NULL) {
+                       CFDictionarySetValue(newConfiguration, key, domain);
+                       CFRelease(domain);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("invalid DNS domain name\n"));
+                       return -1;
+               }
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       return 1;
+}
+
+
+static int
+__doDNSDomainArray(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       CFMutableArrayRef       domains;
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
+               return -1;
+       }
+
+       domains = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       if (strlen(argv[0]) > 0) {
+               CFArrayRef      array;
+               CFStringRef     str;
+
+               str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+               CFRelease(str);
+
+               if (array != NULL) {
+                       CFIndex i;
+                       CFIndex n       = CFArrayGetCount(array);
+
+                       for (i = 0; i < n; i++) {
+                               CFStringRef     domain;
+
+                               domain = __cleanupDomainName(CFArrayGetValueAtIndex(array, i));
+                               if (domain != NULL) {
+                                       CFArrayAppendValue(domains, domain);
+                                       CFRelease(domain);
+                               } else {
+                                       CFRelease(array);
+                                       CFRelease(domains);
+                                       SCPrint(TRUE, stdout, CFSTR("invalid DNS search domain name\n"));
+                                       return -1;
+                               }
+                       }
+                       CFRelease(array);
+               }
+       }
+
+       if (CFArrayGetCount(domains) > 0) {
+               CFDictionarySetValue(newConfiguration, key, domains);
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       CFRelease(domains);
+       return 1;
+}
+
+
+static int
+__doDNSServerAddresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       CFMutableArrayRef       servers;
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("DNS search domain name(s) not specified\n"));
+               return -1;
+       }
+
+       servers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+       if (strlen(argv[0]) > 0) {
+               CFArrayRef      array;
+               CFIndex         i;
+               CFIndex         n;
+               CFStringRef     str;
+
+               str = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(","));
+               CFRelease(str);
+
+               n = (array != NULL) ? CFArrayGetCount(array) : 0;
+               for (i = 0; i < n; i++) {
+                       char    str[32];
+
+                       if (_SC_cfstring_to_cstring(CFArrayGetValueAtIndex(array, i),
+                                                   str,
+                                                   sizeof(str),
+                                                   kCFStringEncodingUTF8) != NULL) {
+                               CFStringRef     server;
+
+                               server = __copyIPv4Address(str);
+                               if (server == NULL) {
+                                       server = __copyIPv6Address(str);
+                               }
+                               if (server != NULL) {
+                                       CFArrayAppendValue(servers, server);
+                                       CFRelease(server);
+                                       continue;
+                               }
+                       }
+
+                       SCPrint(TRUE, stdout, CFSTR("invalid DNS name server address\n"));
+                       CFRelease(array);
+                       CFRelease(servers);
+                       return -1;
+               }
+               if (array != NULL) CFRelease(array);
+       }
+
+       if (CFArrayGetCount(servers) > 0) {
+               CFDictionarySetValue(newConfiguration, key, servers);
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       CFRelease(servers);
+       return 1;
+}
+
+
+static options dnsOptions[] = {
+       { "DomainName"     , "domain" , isOther, &kSCPropNetDNSDomainName     , __doDNSDomain         , NULL },
+       {   "domain"       , "domain" , isOther, &kSCPropNetDNSDomainName     , __doDNSDomain         , NULL },
+       { "SearchDomains"  , "search" , isOther, &kSCPropNetDNSSearchDomains  , __doDNSDomainArray    , NULL },
+       {   "search"       , "search" , isOther, &kSCPropNetDNSSearchDomains  , __doDNSDomainArray    , NULL },
+       { "ServerAddresses", "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
+       {   "nameserver"   , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
+       {   "nameservers"  , "address", isOther, &kSCPropNetDNSServerAddresses, __doDNSServerAddresses, NULL },
+
+       { "?"              , NULL     , isHelp , NULL                         , NULL,
+           "\nDNS configuration commands\n\n"
+           " set protocol search domain-name[,domain-name-2]\n"
+           " set protocol nameserver x1.x1.x1.x1[,x2.x2.x2.x2]"
+       }
+};
+#define        N_DNS_OPTIONS   (sizeof(dnsOptions) / sizeof(dnsOptions[0]))
+
+
+static Boolean
+set_protocol_dns(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(dnsOptions, N_DNS_OPTIONS, argc, argv, newConfiguration);
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+#define allowIPv4Address       1<<1    // allow address
+#define allowIPv4Netmask       1<<2    // allow subnet mask
+#define allowIPv4Router                1<<3    // allow router
+#define allowIPv4DHCPClientID  1<<4    // allow DCHP Client ID
+
+static selections ipv4ConfigMethods[] = {
+       { CFSTR("BOOTP")    , &kSCValNetIPv4ConfigMethodBOOTP    , 0                                                 },
+       { CFSTR("DHCP")     , &kSCValNetIPv4ConfigMethodDHCP     , allowIPv4DHCPClientID                             },
+       { CFSTR("INFORM")   , &kSCValNetIPv4ConfigMethodINFORM   , allowIPv4Address                                  },
+       { CFSTR("LinkLocal"), &kSCValNetIPv4ConfigMethodLinkLocal, 0                                                 },
+       { CFSTR("Manual")   , &kSCValNetIPv4ConfigMethodManual   , allowIPv4Address|allowIPv4Netmask|allowIPv4Router },
+       { CFSTR("PPP")      , &kSCValNetIPv4ConfigMethodPPP      , allowIPv4Address|selectionNotAvailable            },
+       { NULL              , NULL                               , 0                                                 }
+};
+
+
+static int
+__doIPv4ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       unsigned int    flags;
+       CFStringRef     method;
+       CFIndex         methodIndex;
+
+       method = CFDictionaryGetValue(newConfiguration, key);
+       methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
+       if (methodIndex != kCFNotFound) {
+               if (!(flags & allowIPv4Address)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Addresses);
+               }
+               if (!(flags & allowIPv4Netmask)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4SubnetMasks);
+               }
+               if (!(flags & allowIPv4Router)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4Router);
+               }
+               if (!(flags & allowIPv4DHCPClientID)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv4DHCPClientID);
+               }
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int
+__doIPv4Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean useArray        = (info == (void *)FALSE) ? FALSE : TRUE;
+
+       if (strlen(argv[0]) > 0) {
+               CFStringRef     address;
+
+               address = __copyIPv4Address(argv[0]);
+               if (address != NULL) {
+                       if (useArray) {
+                               CFArrayRef      addresses;
+
+                               addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
+                               CFDictionarySetValue(newConfiguration, key, addresses);
+                               CFRelease(addresses);
+                       } else {
+                               CFDictionarySetValue(newConfiguration, key, address);
+                       }
+                       CFRelease(address);
+               } else {
+                       return -1;
+               }
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       return 1;
+}
+
+
+static options ipv4Options[] = {
+       { "ConfigMethod", "configuration method"
+                                    , isChooseOne   , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
+       {   "config"    , "configuration method"
+                                    , isChooseOne   , &kSCPropNetIPv4ConfigMethod, __doIPv4ConfigMethod, (void *)ipv4ConfigMethods },
+       { "Addresses"   , "address"  , isOther       , &kSCPropNetIPv4Addresses   , __doIPv4Addresses   , (void *)TRUE              },
+       {   "address"   , "address"  , isOther       , &kSCPropNetIPv4Addresses   , __doIPv4Addresses   , (void *)TRUE              },
+       { "SubnetMasks" , "netmask"  , isOther       , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses   , (void *)TRUE              },
+       {   "netmask"   , "netmask"  , isOther       , &kSCPropNetIPv4SubnetMasks , __doIPv4Addresses   , (void *)TRUE              },
+       { "Router"      , "address"  , isOther       , &kSCPropNetIPv4Router      , __doIPv4Addresses   , (void *)FALSE             },
+       { "DHCPClientID", "client ID", isString      , &kSCPropNetIPv4DHCPClientID, NULL                , NULL                      },
+
+       { "?"           , NULL       , isHelp        , NULL                       , NULL                ,
+           "\nIPv4 configuration commands\n\n"
+           " set protocol config {BOOTP|DHCP|INFORM|MANUAL}\n"
+           "\n w/config=BOOTP\n"
+           "   None\n"
+           "\n w/config=DHCP\n"
+           "   set protocol dhcpclientid identifier\n"
+           "\n w/config=INFORM\n"
+           "   set protocol address x.x.x.x\n"
+           "\n w/config=MANUAL\n"
+           "   set protocol address x.x.x.x\n"
+           "   set protocol netmask x.x.x.x\n"
+           "   set protocol router  x.x.x.x\n"
+       }
+};
+#define        N_IPV4_OPTIONS  (sizeof(ipv4Options) / sizeof(ipv4Options[0]))
+
+
+static Boolean
+set_protocol_ipv4(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(ipv4Options, N_IPV4_OPTIONS, argc, argv, newConfiguration);
+       if (ok) {
+               unsigned int    flags;
+               CFStringRef     method;
+               CFIndex         methodIndex;
+
+               // validate configuration
+               method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv4ConfigMethod);
+               methodIndex = _find_selection(method, (selections *)ipv4ConfigMethods, &flags);
+               if (methodIndex == kCFNotFound) {
+                       SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv4Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Addresses)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("IP address not allowed with %@ configuration\n"),
+                               ipv4ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv4Netmask) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4SubnetMasks)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("Subnet mask not allowed with %@ configuration\n"),
+                               ipv4ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv4Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4Router)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("Default route not allowed with %@ configuration\n"),
+                               ipv4ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv4DHCPClientID) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv4DHCPClientID)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("DHCP client ID not allowed with %@ configuration\n"),
+                               ipv4ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+       }
+
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+#define allowIPv6Address       1<<1    // allow address
+#define allowIPv6PrefixLength  1<<2    // allow prefix length
+#define allowIPv6Router                1<<3    // allow router
+
+static selections ipv6ConfigMethods[] = {
+       { CFSTR("Automatic")          , & kSCValNetIPv6ConfigMethodAutomatic          , 0                                                      },
+       { CFSTR("Manual")             , & kSCValNetIPv6ConfigMethodManual             , allowIPv6Address|allowIPv6PrefixLength|allowIPv6Router },
+       { CFSTR("RouterAdvertisement"), & kSCValNetIPv6ConfigMethodRouterAdvertisement, allowIPv6Address                                       },
+       { CFSTR("6to4")               , & kSCValNetIPv6ConfigMethod6to4               , 0                                                      },
+       { NULL                        , NULL                                          , 0                                                      }
+};
+
+
+static int
+__doIPv6ConfigMethod(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       unsigned int    flags;
+       CFStringRef     method;
+       CFIndex         methodIndex;
+
+       method = CFDictionaryGetValue(newConfiguration, key);
+       methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
+       if (methodIndex != kCFNotFound) {
+               if (!(flags & allowIPv6Address)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Addresses);
+               }
+               if (!(flags & allowIPv6PrefixLength)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6PrefixLength);
+               }
+               if (!(flags & allowIPv6Router)) {
+                       CFDictionaryRemoveValue(newConfiguration, kSCPropNetIPv6Router);
+               }
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int
+__doIPv6Addresses(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean useArray        = (info == (void *)FALSE) ? FALSE : TRUE;
+
+       if (strlen(argv[0]) > 0) {
+               CFStringRef     address;
+
+               address = __copyIPv6Address(argv[0]);
+               if (address != NULL) {
+                       if (useArray) {
+                               CFArrayRef      addresses;
+
+                               addresses = CFArrayCreate(NULL, (const void **)&address, 1, &kCFTypeArrayCallBacks);
+                               CFDictionarySetValue(newConfiguration, key, addresses);
+                               CFRelease(addresses);
+                       } else {
+                               CFDictionarySetValue(newConfiguration, key, address);
+                       }
+                       CFRelease(address);
+               } else {
+                       return -1;
+               }
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, key);
+       }
+
+       return 1;
+}
+
+
+static int
+__doIPv6PrefixLength(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       CFNumberRef     num;
+       int             prefixLength;
+
+       num = CFDictionaryGetValue(newConfiguration, kSCPropNetPPPAuthPasswordEncryption);
+       if (isA_CFNumber(num) &&
+           CFNumberGetValue(num, kCFNumberIntType, &prefixLength) &&
+           (prefixLength >= 0) && (prefixLength <= (sizeof(struct in6_addr) * 8))) {
+               return 0;
+       }
+
+       return -1;
+}
+
+
+static options ipv6Options[] = {
+       { "ConfigMethod", "configuration method"
+                                        , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
+       {   "config"    , "configuration method"
+                                        , isChooseOne, &kSCPropNetIPv6ConfigMethod, __doIPv6ConfigMethod, (void *)ipv6ConfigMethods },
+       { "Addresses"   , "address"      , isOther    , &kSCPropNetIPv6Addresses   , __doIPv6Addresses   , (void *)TRUE              },
+       {   "address"   , "address"      , isOther    , &kSCPropNetIPv6Addresses   , __doIPv6Addresses   , (void *)TRUE              },
+       { "PrefixLength", "prefix length", isNumber   , &kSCPropNetIPv6PrefixLength, __doIPv6PrefixLength, NULL                      },
+       { "Router"      , "address"      , isOther    , &kSCPropNetIPv6Router      , __doIPv6Addresses   , (void *)FALSE             },
+
+       { "?"           , NULL           , isHelp     , NULL                       , NULL                ,
+           "\nIPv6 configuration commands\n\n"
+           " set protocol config {Automatic|MANUAL}\n"
+           "\n w/config=Automatic\n"
+           "   None\n"
+           "\n w/config=MANUAL\n"
+           "   set protocol address x:x:x:x:x:x\n"
+           "   set protocol router  x:x:x:x:x:x\n"
+           "   set protocol prefixlength n\n"
+       }
+};
+#define        N_IPV6_OPTIONS  (sizeof(ipv6Options) / sizeof(ipv6Options[0]))
+
+
+static Boolean
+set_protocol_ipv6(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(ipv6Options, N_IPV6_OPTIONS, argc, argv, newConfiguration);
+       if (ok) {
+               unsigned int    flags;
+               CFStringRef     method;
+               CFIndex         methodIndex;
+
+               // validate configuration
+               method = CFDictionaryGetValue(newConfiguration, kSCPropNetIPv6ConfigMethod);
+               methodIndex = _find_selection(method, (selections *)ipv6ConfigMethods, &flags);
+               if (methodIndex == kCFNotFound) {
+                       SCPrint(TRUE, stdout, CFSTR("unknown configuration method\n"));
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv6Address) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Addresses)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("IP address not allowed with %@ configuration\n"),
+                               ipv6ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv6PrefixLength) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6PrefixLength)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("Prefix length not allowed with %@ configuration\n"),
+                               ipv6ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+
+               if (!(flags & allowIPv6Router) && CFDictionaryContainsKey(newConfiguration, kSCPropNetIPv6Router)) {
+                       SCPrint(TRUE, stdout,
+                               CFSTR("Router not allowed with %@ configuration\n"),
+                               ipv6ConfigMethods[methodIndex].selection);
+                       return FALSE;
+               }
+       }
+
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+typedef const struct {
+       const char              *proxy;
+       const CFStringRef       *keyEnable;
+       const CFStringRef       *keyProxy;
+       const CFStringRef       *keyPort;
+       const CFStringRef       *keyURL;
+} proxyKeys;
+
+static proxyKeys proxyKeys_FTP    = { "FTP"   , &kSCPropNetProxiesFTPEnable               , &kSCPropNetProxiesFTPProxy   , &kSCPropNetProxiesFTPPort   , NULL                                       };
+static proxyKeys proxyKeys_Gopher = { "Gopher", &kSCPropNetProxiesGopherEnable            , &kSCPropNetProxiesGopherProxy, &kSCPropNetProxiesGopherPort, NULL                                       };
+static proxyKeys proxyKeys_HTTP   = { "HTTP"  , &kSCPropNetProxiesHTTPEnable              , &kSCPropNetProxiesHTTPProxy  , &kSCPropNetProxiesHTTPPort  , NULL                                       };
+static proxyKeys proxyKeys_HTTPS  = { "HTTPS" , &kSCPropNetProxiesHTTPSEnable             , &kSCPropNetProxiesHTTPSProxy , &kSCPropNetProxiesHTTPSPort , NULL                                       };
+static proxyKeys proxyKeys_RTSP   = { "RTSP"  , &kSCPropNetProxiesRTSPEnable              , &kSCPropNetProxiesRTSPProxy  , &kSCPropNetProxiesRTSPPort  , NULL                                       };
+static proxyKeys proxyKeys_SOCKS  = { "SOCKS" , &kSCPropNetProxiesSOCKSEnable             , &kSCPropNetProxiesSOCKSProxy , &kSCPropNetProxiesSOCKSPort , NULL                                       };
+static proxyKeys proxyKeys_PAC    = { ".pac"  , &kSCPropNetProxiesProxyAutoConfigEnable   , NULL                         , NULL                        , &kSCPropNetProxiesProxyAutoConfigURLString };
+static proxyKeys proxyKeys_WPAD   = { "WPAD"  , &kSCPropNetProxiesProxyAutoDiscoveryEnable, NULL                         , NULL                        , NULL                                       };
+
+static proxyKeys       *currentProxy   = NULL;
+
+
+static int __doProxySelect    (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyEnable    (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyHost      (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyPort      (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyURL       (CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+static int __doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration);
+
+
+static options proxyOptions[] = {
+       // general options
+       { "ExceptionsList"        , "exceptions", isStringArray, &kSCPropNetProxiesExceptionsList        , NULL              , NULL                      },
+       { "ExcludeSimpleHostnames", NULL        , isBoolean    , &kSCPropNetProxiesExcludeSimpleHostnames, NULL              , NULL                      },
+       // proxy selection
+       { "FTP"                   , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_FTP    },
+       { "Gopher"                , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_Gopher },
+       { "HTTP"                  , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_HTTP   },
+       { "HTTPS"                 , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_HTTPS  },
+       { "RTSP"                  , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_RTSP   },
+       { "SOCKS"                 , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_SOCKS  },
+       { "ProxyAutoConfig"       , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_PAC    },
+       {   ".pac"                , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_PAC    },
+       { "ProxyAutoDiscovery"    , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_WPAD   },
+       {   "WPAD"                , NULL        , isOther      , NULL                                    , __doProxySelect   , (void *)&proxyKeys_WPAD   },
+       // proxy modifiers
+       { "disable"               , NULL        , isOther      , NULL                                    , __doProxyEnable    , (void *)FALSE             },
+       { "enable"                , NULL        , isOther      , NULL                                    , __doProxyEnable    , (void *)TRUE              },
+       { "proxy"                 , NULL        , isOther      , NULL                                    , __doProxyHost      , NULL                      },
+       {   "host"                , NULL        , isOther      , NULL                                    , __doProxyHost      , NULL                      },
+       { "port"                  , NULL        , isOther      , NULL                                    , __doProxyPort      , NULL                      },
+       { "url"                   , NULL        , isOther      , NULL                                    , __doProxyURL       , NULL                      },
+       // (ftp) proxy modifiers
+       { "FTPPassive"            , NULL        , isBoolean    , &kSCPropNetProxiesFTPPassive            , __doProxyFTPPassive, NULL                      },
+       {   "passive"             , NULL        , isBoolean    , &kSCPropNetProxiesFTPPassive            , __doProxyFTPPassive, NULL                      },
+       // help
+       { "?"                     , NULL        , isHelp       , NULL                                    , NULL                ,
+           "\nProxy configuration commands\n\n"
+           " set protocol ExceptionsList exception[,exception-2]\n"
+           " set protocol ExcludeSimpleHostnames {enable|disable}\n"
+           "\n"
+           " set protocol ftp {enable|disable}\n"
+           " set protocol ftp host proxy-host\n"
+           " set protocol ftp port proxy-port\n"
+           " set protocol ftp passive {enable|disable}\n"
+           "\n"
+           " set protocol http {enable|disable}\n"
+           " set protocol http host proxy-host\n"
+           " set protocol http port proxy-port\n"
+           "\n"
+           " set protocol https {enable|disable}\n"
+           " set protocol https host proxy-host\n"
+           " set protocol https port proxy-port\n"
+           "\n"
+           " set protocol rtsp {enable|disable}\n"
+           " set protocol rtsp host proxy-host\n"
+           " set protocol rtsp port proxy-port\n"
+           "\n"
+           " set protocol socks {enable|disable}\n"
+           " set protocol socks host proxy-host\n"
+           " set protocol socks port proxy-port\n"
+           "\n"
+           " set protocol .pac {enable|disable}\n"
+           " set protocol .pac url .pac-url\n"
+           "\n"
+           " set protocol wpad {enable|disable}\n"
+       }
+};
+#define        N_PROXY_OPTIONS (sizeof(proxyOptions) / sizeof(proxyOptions[0]))
+
+
+static int
+__doProxySelect(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       CFIndex nextOption;
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("proxy option[s] not specified\n"));
+               return -1;
+       }
+
+       currentProxy = (proxyKeys *)info;
+
+       nextOption = _find_option(argv[0], proxyOptions, N_PROXY_OPTIONS);
+       if ((nextOption == kCFNotFound) ||
+           (proxyOptions[nextOption].handler == __doProxySelect)) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy option[s] not specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int
+__doProxyEnable(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean enabled = (info == (void *)FALSE) ? FALSE : TRUE;
+
+       if (currentProxy == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+               return -1;
+       }
+
+       if (currentProxy->keyEnable == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy cannot be %s\n"),
+                       currentProxy->proxy,
+                       enabled ? "enabled" : "disabled");
+               return -1;
+       }
+
+
+       if (enabled) {
+               CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_1);
+       } else {
+               CFDictionarySetValue(newConfiguration, *(currentProxy->keyEnable), CFNumberRef_0);
+
+               if (currentProxy->keyProxy != NULL) {
+                       CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
+               }
+
+               if (currentProxy->keyPort != NULL) {
+                       CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
+               }
+
+               if (currentProxy->keyURL != NULL) {
+                       CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
+               }
+       }
+
+       return 0;
+}
+
+
+static Boolean
+__proxy_enabled(CFDictionaryRef configuration, const CFStringRef *enableKey)
+{
+       CFNumberRef     num;
+       int             val;
+
+       if (enableKey == NULL) {
+               return TRUE;    // if proxy does not need to be enabled
+       }
+
+       num = CFDictionaryGetValue(configuration, *enableKey);
+       if (!isA_CFNumber(num) ||
+           !CFNumberGetValue(num, kCFNumberIntType, &val) ||
+           (val == 0)) {
+               return FALSE;   // if not enabled
+       }
+
+       return TRUE;
+}
+
+
+static int
+__doProxyHost(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (currentProxy == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+               return -1;
+       }
+
+       if (currentProxy->keyProxy == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy host cannot be specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy host not specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               CFStringRef     host;
+
+               host = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               CFDictionarySetValue(newConfiguration, *(currentProxy->keyProxy), host);
+               CFRelease(host);
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyProxy));
+       }
+
+       return 1;
+}
+
+
+static int
+__doProxyPort(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (currentProxy == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+               return -1;
+       }
+
+       if (currentProxy->keyPort == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy port cannot be specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy port not specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               CFNumberRef     num;
+               int             port;
+
+               num = _copy_number(argv[0]);
+               if (!isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberIntType, &port) ||
+                   (port < 0) || (port > 65535)) {
+                       SCPrint(TRUE, stdout, CFSTR("invalid %s proxy port number\n"), currentProxy->proxy);
+                       return -1;
+               }
+
+               CFDictionarySetValue(newConfiguration, *(currentProxy->keyPort), num);
+               CFRelease(num);
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyPort));
+       }
+
+       return 1;
+}
+
+
+static int
+__doProxyURL(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (currentProxy == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+               return -1;
+       }
+
+       if (currentProxy->keyURL == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy URL cannot be specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (!__proxy_enabled(newConfiguration, currentProxy->keyEnable)) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy not enabled\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("%s proxy URL not specified\n"), currentProxy->proxy);
+               return -1;
+       }
+
+       if (strlen(argv[0]) > 0) {
+               CFStringRef     url;
+
+               url = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               CFDictionarySetValue(newConfiguration, *(currentProxy->keyURL), url);
+               CFRelease(url);
+       } else {
+               CFDictionaryRemoveValue(newConfiguration, *(currentProxy->keyURL));
+       }
+
+       return 1;
+}
+
+
+static int
+__doProxyFTPPassive(CFStringRef key, const char *description, void *info, int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       if (currentProxy == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("proxy not specified\n"));
+               return -1;
+       }
+
+       if (currentProxy != &proxyKeys_FTP) {
+               SCPrint(TRUE, stdout, CFSTR("passive can only be enable for FTP proxy\n"));
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static Boolean
+set_protocol_proxies(int argc, char **argv, CFMutableDictionaryRef newConfiguration)
+{
+       Boolean ok;
+
+       ok = _process_options(proxyOptions, N_PROXY_OPTIONS, argc, argv, newConfiguration);
+       return ok;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+set_protocol(int argc, char **argv)
+{
+       CFDictionaryRef         configuration;
+       CFMutableDictionaryRef  newConfiguration        = NULL;
+       Boolean                 ok                      = FALSE;
+       CFStringRef             protocolType;
+
+       if (net_protocol == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+               return;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+               return;
+       }
+
+       configuration = SCNetworkProtocolGetConfiguration(net_protocol);
+       if (configuration == NULL) {
+               newConfiguration = CFDictionaryCreateMutable(NULL,
+                                                            0,
+                                                            &kCFTypeDictionaryKeyCallBacks,
+                                                            &kCFTypeDictionaryValueCallBacks);
+       } else {
+               newConfiguration = CFDictionaryCreateMutableCopy(NULL, 0, configuration);
+               CFDictionaryRemoveValue(newConfiguration, kSCResvInactive);
+       }
+
+       protocolType = SCNetworkProtocolGetProtocolType(net_protocol);
+       if (CFEqual(protocolType, kSCNetworkProtocolTypeAppleTalk)) {
+               ok = set_protocol_appletalk(argc, argv, newConfiguration);
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
+               ok = set_protocol_dns(argc, argv, newConfiguration);
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
+               ok = set_protocol_ipv4(argc, argv, newConfiguration);
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
+               ok = set_protocol_ipv6(argc, argv, newConfiguration);
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
+               ok = set_protocol_proxies(argc, argv, newConfiguration);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("this protocols configuration cannot be changed\n"));
+       }
+
+       if (!ok) {
+               goto done;
+       }
+
+       if (((configuration == NULL) && (CFDictionaryGetCount(newConfiguration) > 0)) ||
+           ((configuration != NULL) && !CFEqual(configuration, newConfiguration))) {
+               if (!SCNetworkProtocolSetConfiguration(net_protocol, newConfiguration)) {
+                       SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                       goto done;
+               }
+
+               net_changed = TRUE;
+       }
+
+    done :
+
+       if (newConfiguration != NULL) CFRelease(newConfiguration);
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_protocol(int argc, char **argv)
+{
+       CFDictionaryRef         configuration;
+       SCNetworkProtocolRef    protocol        = NULL;
+       CFStringRef             protocolType;
+
+       if (argc > 0) {
+               protocol = _find_protocol(argv[0]);
+       } else {
+               if (net_protocol != NULL) {
+                       protocol = net_protocol;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("protocol not selected\n"));
+                       return;
+               }
+       }
+
+       if (protocol == NULL) {
+               return;
+       }
+
+       protocolType = SCNetworkProtocolGetProtocolType(protocol);
+       SCPrint(TRUE, stdout, CFSTR("protocol type        = %@\n"), protocolType);
+
+       configuration = SCNetworkProtocolGetConfiguration(protocol);
+       if (configuration != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("\n  protocol configuration\n"));
+               _show_entity(configuration, CFSTR(""));
+       }
+
+       if (_sc_debug) {
+               SCPrint(TRUE, stdout, CFSTR("\n%@\n"), protocol);
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+show_protocols(int argc, char **argv)
+{
+       CFIndex i;
+       CFIndex n;
+
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+               return;
+       }
+
+       if (net_service == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+               return;
+       }
+
+       if (protocols != NULL) CFRelease(protocols);
+       protocols = SCNetworkServiceCopyProtocols(net_service);
+       if (protocols == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       n = CFArrayGetCount(protocols);
+       if (n > 1) {
+               CFMutableArrayRef       sorted;
+
+               sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+               CFArraySortValues(sorted,
+                                 CFRangeMake(0, n),
+                                 _compare_protocols,
+                                 NULL);
+               CFRelease(protocols);
+               protocols = sorted;
+       }
+
+       for (i = 0; i < n; i++) {
+               SCNetworkProtocolRef    protocol;
+               CFStringRef             protocolType;
+
+               protocol     = CFArrayGetValueAtIndex(protocols, i);
+               protocolType = SCNetworkProtocolGetProtocolType(protocol);
+
+               SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%*s :"),
+                       ((net_protocol != NULL) && CFEqual(protocol, net_protocol)) ? '>' : ' ',
+                       i + 1,
+                       protocolType,
+                       sizeof("AppleTalk") - CFStringGetLength(protocolType) - 1,
+                       "");
+
+               if (SCNetworkProtocolGetEnabled(protocol)) {
+                       CFStringRef     description;
+
+                       description = _protocol_description(protocol, FALSE);
+                       SCPrint(TRUE, stdout, CFSTR(" %@"), description);
+                       CFRelease(description);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR(" *DISABLED*"));
+               }
+               SCPrint(TRUE, stdout, CFSTR("\n"));
+       }
+
+       return;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFStringRef
+_protocol_description(SCNetworkProtocolRef protocol, Boolean skipEmpty)
+{
+       CFDictionaryRef         configuration;
+       CFMutableStringRef      description     = NULL;
+       CFStringRef             protocolType;
+
+       description = CFStringCreateMutable(NULL, 0);
+
+       if (!SCNetworkProtocolGetEnabled(protocol)) {
+               goto done;
+       }
+
+       configuration = SCNetworkProtocolGetConfiguration(protocol);
+       if (configuration == NULL) {
+               goto done;
+       }
+
+       protocolType = SCNetworkProtocolGetProtocolType(protocol);
+       if (CFEqual(protocolType, kSCNetworkProtocolTypeAppleTalk)) {
+               CFStringRef     method;
+
+               method = CFDictionaryGetValue(configuration, kSCPropNetAppleTalkConfigMethod);
+               if (isA_CFString(method)) {
+                       CFStringAppendFormat(description,
+                                            NULL,
+                                            CFSTR("%@"),
+                                            method);
+               }
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeDNS)) {
+               CFStringRef     domain;
+               CFArrayRef      search;
+               CFArrayRef      servers;
+
+               domain  = CFDictionaryGetValue(configuration, kSCPropNetDNSDomainName);
+               if (isA_CFString(domain)) {
+                       CFStringAppendFormat(description,
+                                            NULL,
+                                            CFSTR("domain=%@"),
+                                            domain);
+               }
+
+               search = CFDictionaryGetValue(configuration, kSCPropNetDNSSearchDomains);
+               if (isA_CFArray(search)) {
+                       CFStringRef     str;
+
+                       str = CFStringCreateByCombiningStrings(NULL, search, CFSTR(","));
+                       CFStringAppendFormat(description,
+                                            NULL,
+                                            CFSTR("%ssearch=%@"),
+                                            CFStringGetLength(description) > 0 ? ", " : "",
+                                            str);
+                       CFRelease(str);
+               }
+
+               servers = CFDictionaryGetValue(configuration, kSCPropNetDNSServerAddresses);
+               if (isA_CFArray(servers)) {
+                       CFStringRef     str;
+
+                       str = CFStringCreateByCombiningStrings(NULL, servers, CFSTR(","));
+                       CFStringAppendFormat(description,
+                                            NULL,
+                                            CFSTR("%sservers=%@"),
+                                            CFStringGetLength(description) > 0 ? ", " : "",
+                                            str);
+                       CFRelease(str);
+               }
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv4)) {
+               CFStringRef     method;
+
+               method = CFDictionaryGetValue(configuration, kSCPropNetIPv4ConfigMethod);
+               if (isA_CFString(method)) {
+                       CFArrayRef      addresses;
+
+                       addresses = CFDictionaryGetValue(configuration, kSCPropNetIPv4Addresses);
+                       if (CFEqual(method, kSCValNetIPv4ConfigMethodINFORM) &&
+                           isA_CFArray(addresses)) {
+                               CFStringAppendFormat(description,
+                                                    NULL,
+                                                    CFSTR("%@, address=%@"),
+                                                    method,
+                                                    CFArrayGetValueAtIndex(addresses, 0));
+                       } else if (CFEqual(method, kSCValNetIPv4ConfigMethodManual) &&
+                                  isA_CFArray(addresses)) {
+                               CFStringAppendFormat(description,
+                                                    NULL,
+                                                    CFSTR("%@, address=%@"),
+                                                    method,
+                                                    CFArrayGetValueAtIndex(addresses, 0));
+                       } else {
+                               CFStringAppendFormat(description,
+                                                    NULL,
+                                                    CFSTR("%@"),
+                                                    method);
+                       }
+               }
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeIPv6)) {
+               CFStringRef     method;
+
+               method = CFDictionaryGetValue(configuration, kSCPropNetIPv6ConfigMethod);
+               if (isA_CFString(method)) {
+                       CFStringAppendFormat(description,
+                                            NULL,
+                                            CFSTR("%@"),
+                                            method);
+               }
+       } else if (CFEqual(protocolType, kSCNetworkProtocolTypeProxies)) {
+               CFIndex                 i;
+               static proxyKeys        *keys[] = { &proxyKeys_FTP,     &proxyKeys_Gopher,      &proxyKeys_HTTP,        &proxyKeys_HTTPS,
+                                                   &proxyKeys_RTSP,    &proxyKeys_SOCKS,       &proxyKeys_PAC,         &proxyKeys_WPAD };
+
+               for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
+                       proxyKeys       *currentProxy   = keys[i];
+
+                       if (!__proxy_enabled(configuration, currentProxy->keyEnable)) {
+                               continue;
+                       }
+
+                       if (((currentProxy->keyProxy != NULL) &&
+                            !CFDictionaryContainsKey(configuration, *(currentProxy->keyProxy))) ||
+                           ((currentProxy->keyURL != NULL) &&
+                            !CFDictionaryContainsKey(configuration, *(currentProxy->keyURL)))) {
+                               continue;
+                       }
+
+                       CFStringAppendFormat(description,
+                                            NULL,
+                                            CFSTR("%s%s"),
+                                            CFStringGetLength(description) > 0 ? ", " : "",
+                                            currentProxy->proxy);
+               }
+       }
+
+    done :
+
+       if (skipEmpty && CFStringGetLength(description) == 0) {
+               CFRelease(description);
+               description = NULL;
+       }
+
+       return description;
+}
diff --git a/scutil.tproj/net_protocol.h b/scutil.tproj/net_protocol.h
new file mode 100644 (file)
index 0000000..30b650e
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_PROTOCOL_H
+#define _NET_PROTOCOL_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+CFComparisonResult     _compare_protocols      (const void *val1, const void *val2, void *context);
+CFStringRef            _protocol_description   (SCNetworkProtocolRef protocol, Boolean skipEmpty);
+
+void   create_protocol         (int argc, char **argv);
+void   disable_protocol        (int argc, char **argv);
+void   enable_protocol         (int argc, char **argv);
+void   remove_protocol         (int argc, char **argv);
+void   select_protocol         (int argc, char **argv);
+void   set_protocol            (int argc, char **argv);
+void   show_protocol           (int argc, char **argv);
+void   show_protocols          (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_PROTOCOL_H */
diff --git a/scutil.tproj/net_service.c b/scutil.tproj/net_service.c
new file mode 100644 (file)
index 0000000..30c00b3
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+#include "net_service.h"
+#include "net_interface.h"
+#include "net_protocol.h"
+
+
+/* -------------------- */
+
+
+__private_extern__
+CFComparisonResult
+_compare_services(const void *val1, const void *val2, void *context)
+{
+       CFStringRef             id1;
+       CFStringRef             id2;
+       CFArrayRef              order   = (CFArrayRef)context;
+       SCNetworkServiceRef     s1      = (SCNetworkServiceRef)val1;
+       SCNetworkServiceRef     s2      = (SCNetworkServiceRef)val2;
+
+       id1 = SCNetworkServiceGetServiceID(s1);
+       id2 = SCNetworkServiceGetServiceID(s2);
+
+       if (order != NULL) {
+               CFIndex o1;
+               CFIndex o2;
+               CFRange range;
+
+               range = CFRangeMake(0, CFArrayGetCount(order));
+               o1 = CFArrayGetFirstIndexOfValue(order, range, id1);
+               o2 = CFArrayGetFirstIndexOfValue(order, range, id2);
+
+               if (o1 > o2) {
+                       return (o2 != kCFNotFound) ? kCFCompareGreaterThan : kCFCompareLessThan;
+               } else if (o1 < o2) {
+                       return (o1 != kCFNotFound) ? kCFCompareLessThan    : kCFCompareGreaterThan;
+               }
+       }
+
+       return CFStringCompare(id1, id2, 0);
+}
+
+
+static SCNetworkServiceRef
+_find_service(char *match)
+{
+       Boolean                 allowIndex      = TRUE;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFStringRef             select_name     = NULL;
+       SCNetworkServiceRef     selected        = NULL;
+
+       if (services == NULL) {
+               if (net_set == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+                       return NULL;
+               }
+
+               services = SCNetworkSetCopyServices(net_set);
+               if (services == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                       return NULL;
+               }
+
+               allowIndex = FALSE;
+       }
+
+       // try to select the service by its serviceID
+
+       select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+       n = CFArrayGetCount(services);
+       for (i = 0; i < n; i++) {
+               SCNetworkServiceRef     service;
+               CFStringRef             serviceID;
+
+               service   = CFArrayGetValueAtIndex(services, i);
+               serviceID = SCNetworkServiceGetServiceID(service);
+               if (CFEqual(select_name, serviceID)) {
+                       selected = service;
+                       goto done;
+               }
+       }
+
+       // try to select the service by its name
+
+       for (i = 0; i < n; i++) {
+               SCNetworkServiceRef     service;
+               CFStringRef             serviceName;
+
+               service     = CFArrayGetValueAtIndex(services, i);
+               serviceName = SCNetworkServiceGetName(service);
+               if ((serviceName != NULL) && CFEqual(select_name, serviceName)) {
+                       if (selected == NULL) {
+                               selected = service;
+                       } else {
+                               // if multiple services match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the service by its name (case insensitive)
+
+       for (i = 0; i < n; i++) {
+               SCNetworkServiceRef     service;
+               CFStringRef             serviceName;
+
+               service     = CFArrayGetValueAtIndex(services, i);
+               serviceName = SCNetworkServiceGetName(service);
+               if ((serviceName != NULL) &&
+                   CFStringCompare(select_name,
+                                   serviceName,
+                                   kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                       if (selected == NULL) {
+                               selected = service;
+                       } else {
+                               // if multiple services match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the service by its [BSD] interface name
+
+       for (i = 0; i < n; i++) {
+               SCNetworkInterfaceRef   interface;
+               CFStringRef             interfaceName   = NULL;
+               SCNetworkServiceRef     service;
+
+               service     = CFArrayGetValueAtIndex(services, i);
+
+               interface = SCNetworkServiceGetInterface(service);
+               while ((interface != NULL) && (interfaceName == NULL)) {
+                       interfaceName = SCNetworkInterfaceGetBSDName(interface);
+                       if (interfaceName == NULL) {
+                               interface = SCNetworkInterfaceGetInterface(interface);
+                       }
+               }
+
+               if (interfaceName == NULL) {
+                       continue;
+               }
+
+               if (CFStringCompare(select_name,
+                                   interfaceName,
+                                   kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                       if (selected == NULL) {
+                               selected = service;
+                       } else {
+                               // if multiple services match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the service by its index
+
+       if (allowIndex) {
+               char    *end;
+               char    *str    = match;
+               long    val;
+
+               errno = 0;
+               val = strtol(str, &end, 10);
+               if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+                       if ((val > 0) && (val <= n)) {
+                               selected = CFArrayGetValueAtIndex(services, val - 1);
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("no match, which service?\n"));
+
+    done :
+
+       if (select_name != NULL) CFRelease(select_name);
+       return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_service(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+       CFStringRef             interfaceName;
+       Boolean                 ok;
+       CFArrayRef              order;
+       CFMutableArrayRef       newOrder;
+       SCNetworkServiceRef     service         = NULL;
+       CFStringRef             serviceName;
+       CFStringRef             setName;
+       CFArrayRef              supported;
+
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+               return;
+       }
+
+       if (net_set == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+               return;
+       }
+
+       if (argc < 1) {
+               if (net_interface == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
+                       return;
+               }
+
+               interface = net_interface;
+       } else {
+               interface = _find_interface(argv[0]);
+               argv++;
+               argc--;
+       }
+
+       if (interface == NULL) {
+               return;
+       }
+
+       supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
+       if (supported == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("no network protocols are supported over this interface\n"));
+               return;
+       }
+
+       service = SCNetworkServiceCreate(prefs, interface);
+       if (service == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               goto done;
+       }
+
+       if ((argc > 0) && (strlen(argv[0]) > 0)) {
+               Boolean         ok;
+
+               serviceName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               argv++;
+               argc--;
+
+               ok = SCNetworkServiceSetName(service, serviceName);
+               CFRelease(serviceName);
+               if (!ok) {
+                       SCPrint(TRUE, stdout, CFSTR("service not created: %s\n"), SCErrorString(SCError()));
+                       CFRelease(service);
+                       return;
+               }
+       }
+
+       ok = SCNetworkSetAddService(net_set, service);
+       if (!ok) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               (void)SCNetworkServiceRemove(service);
+               goto done;
+       }
+
+       net_changed = TRUE;
+
+       order = SCNetworkSetGetServiceOrder(net_set);
+       if (order == NULL) {
+               newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       } else {
+               newOrder = CFArrayCreateMutableCopy(NULL, 0, order);
+       }
+       CFArrayAppendValue(newOrder, SCNetworkServiceGetServiceID(service));
+       ok = SCNetworkSetSetServiceOrder(net_set, newOrder);
+       CFRelease(newOrder);
+       if (!ok) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               (void)SCNetworkServiceRemove(service);
+               goto done;
+       }
+
+       interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+       if (interfaceName == NULL) {
+               interfaceName = SCNetworkInterfaceGetBSDName(interface);
+       }
+       if (interfaceName != NULL) {
+               if (!SCNetworkServiceSetName(service, interfaceName)) {
+                       CFIndex         i;
+
+                       for (i = 2; i < 100; i++) {
+                               serviceName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ %d"), interfaceName, i);
+                               ok = SCNetworkServiceSetName(service, serviceName);
+                               CFRelease(serviceName);
+                               if (ok) {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (net_service != NULL) CFRelease(net_service);
+       net_service = CFRetain(service);
+
+       serviceName = SCNetworkServiceGetName(service);
+       if (serviceName != NULL) {
+               SCPrint(TRUE, stdout,
+                       CFSTR("service \"%@\" (%@) created and selected\n"),
+                       serviceName,
+                       SCNetworkServiceGetServiceID(service));
+       } else {
+               SCPrint(TRUE, stdout,
+                       CFSTR("service ID \"%@\" created and selected\n"),
+                       SCNetworkServiceGetServiceID(service));
+       }
+
+       setName = SCNetworkSetGetName(net_set);
+       if (setName != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("& added to set \"%@\"\n"), setName);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("& added to set ID \"%@\"\n"),
+                       SCNetworkSetGetSetID(net_set));
+       }
+
+       if (net_interface != NULL) CFRelease(net_interface);
+       net_interface = CFRetain(interface);
+
+       interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+       if (interfaceName == NULL) {
+               interfaceName = SCNetworkInterfaceGetBSDName(interface);
+       }
+       if (interfaceName == NULL) {
+               interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+       }
+
+       SCPrint(TRUE, stdout,
+               CFSTR("& interface \"%@\" selected\n"),
+               interfaceName);
+
+       if (protocols != NULL) {
+               CFRelease(protocols);
+               protocols = NULL;
+       }
+
+       if (net_protocol != NULL) {
+               CFRelease(net_protocol);
+               net_protocol = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+       }
+
+       if (services != NULL) {
+               CFRelease(services);
+               services = NULL;
+       }
+
+    done :
+
+       if (service != NULL) CFRelease(service);
+       return;
+}
+
+
+__private_extern__
+void
+disable_service(int argc, char **argv)
+{
+       SCNetworkServiceRef     service;
+
+       if (argc == 1) {
+               service = _find_service(argv[0]);
+       } else {
+               if (net_service != NULL) {
+                       service = net_service;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+                       return;
+               }
+       }
+
+       if (service == NULL) {
+               return;
+       }
+
+       if (!SCNetworkServiceSetEnabled(service, FALSE)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       net_changed = TRUE;
+
+       return;
+}
+
+
+__private_extern__
+void
+enable_service(int argc, char **argv)
+{
+       SCNetworkServiceRef     service;
+
+       if (argc == 1) {
+               service = _find_service(argv[0]);
+       } else {
+               if (net_service != NULL) {
+                       service = net_service;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+                       return;
+               }
+       }
+
+       if (service == NULL) {
+               return;
+       }
+
+       if (!SCNetworkServiceSetEnabled(service, TRUE)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       net_changed = TRUE;
+
+       return;
+}
+
+
+__private_extern__
+void
+remove_service(int argc, char **argv)
+{
+       SCNetworkServiceRef     service         = NULL;
+       CFStringRef             serviceName;
+
+       if (argc == 1) {
+               service = _find_service(argv[0]);
+       } else {
+               if (net_service != NULL) {
+                       service = net_service;
+               }
+       }
+
+       if (service == NULL) {
+               return;
+       }
+
+       CFRetain(service);
+
+       if (!SCNetworkServiceRemove(service)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               goto done;
+       }
+
+       net_changed = TRUE;
+
+       serviceName = SCNetworkServiceGetName(service);
+       if (serviceName != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("service \"%@\" removed\n"), serviceName);
+       } else {
+               SCPrint(TRUE, stdout,
+                       CFSTR("service ID \"%@\" removed\n"),
+                       SCNetworkServiceGetServiceID(service));
+       }
+
+       if ((net_service != NULL) && CFEqual(service, net_service)) {
+               CFRelease(net_service);
+               net_service = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+
+               if (protocols != NULL) {
+                       CFRelease(protocols);
+                       protocols = NULL;
+               }
+
+               if (net_protocol != NULL) {
+                       CFRelease(net_protocol);
+                       net_protocol = NULL;
+                       SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+               }
+
+               if (net_interface != NULL) {
+                       CFRelease(net_interface);
+                       net_interface = NULL;
+                       SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+               }
+       }
+
+       if (services != NULL) {
+               CFRelease(services);
+               services = NULL;
+       }
+
+    done :
+
+       CFRelease(service);
+       return;
+}
+
+
+__private_extern__
+void
+select_service(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+       SCNetworkServiceRef     service;
+       CFStringRef             serviceName;
+
+       service = _find_service(argv[0]);
+
+       if (service == NULL) {
+               return;
+       }
+
+       if (net_service != NULL) CFRelease(net_service);
+       net_service = CFRetain(service);
+
+       serviceName = SCNetworkServiceGetName(service);
+       if (serviceName != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("service \"%@\" selected\n"), serviceName);
+       } else {
+               SCPrint(TRUE, stdout,
+                       CFSTR("service ID \"%@\" selected\n"),
+                       SCNetworkServiceGetServiceID(service));
+       }
+
+       interface = SCNetworkServiceGetInterface(service);
+       if (interface != NULL) {
+               CFStringRef     interfaceName;
+
+               if (net_interface != NULL) CFRelease(net_interface);
+               net_interface = CFRetain(interface);
+
+               interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+               if (interfaceName == NULL) {
+                       interfaceName = SCNetworkInterfaceGetBSDName(interface);
+               }
+               if (interfaceName == NULL) {
+                       interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
+               }
+
+               SCPrint(TRUE, stdout,
+                       CFSTR("& interface \"%@\" selected\n"),
+                       interfaceName);
+       } else {
+               if (net_interface != NULL) {
+                       CFRelease(net_interface);
+                       net_interface = NULL;
+                       SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+               }
+       }
+
+       if (protocols != NULL) {
+               CFRelease(protocols);
+               protocols = NULL;
+       }
+
+       if (net_protocol != NULL) {
+               CFRelease(net_protocol);
+               net_protocol = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+set_service(int argc, char **argv)
+{
+       Boolean ok;
+
+       if (net_service == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+               return;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+               return;
+       }
+
+       while (argc > 0) {
+               char    *command;
+
+               command = argv[0];
+               argv++;
+               argc--;
+
+               if (strcmp(command, "name") == 0) {
+                       CFStringRef     serviceName;
+
+                       if (argc < 1) {
+                               SCPrint(TRUE, stdout, CFSTR("name not specified\n"));
+                               return;
+                       }
+
+                       serviceName = (strlen(argv[0]) > 0)
+                                       ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8)
+                                       : NULL;
+                       argv++;
+                       argc--;
+
+                       ok = SCNetworkServiceSetName(net_service, serviceName);
+                       if (serviceName != NULL) CFRelease(serviceName);
+                       if (!ok) {
+                               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                               return;
+                       }
+
+                       net_changed = TRUE;
+               } else if (strcmp(command, "order") == 0) {
+
+                       char            *end;
+                       long            newIndex;
+                       CFIndex         nServices;
+                       char            *str;
+                       CFArrayRef      services;
+
+                       services = SCNetworkSetCopyServices(net_set);
+                       nServices = CFArrayGetCount(services);
+                       CFRelease(services);
+
+                       if (argc < 1) {
+                               SCPrint(TRUE, stdout, CFSTR("order not specified\n"));
+                               return;
+                       }
+
+                       if (net_set == NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+                               return;
+                       }
+
+                       str = argv[0];
+                       argv++;
+                       argc--;
+
+                       errno = 0;
+                       newIndex = strtol(str, &end, 10);
+                       if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+                               if ((newIndex > 0) && (newIndex <= nServices)) {
+                                       CFIndex                 curIndex;
+                                       CFMutableArrayRef       newOrder;
+                                       CFArrayRef              order;
+                                       CFStringRef             serviceID       = SCNetworkServiceGetServiceID(net_service);
+
+                                       order = SCNetworkSetGetServiceOrder(net_set);
+                                       if (order == NULL) {
+                                               newOrder = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                                       } else {
+                                               newOrder = CFArrayCreateMutableCopy(NULL, 0, order);
+                                       }
+
+                                       curIndex = CFArrayGetFirstIndexOfValue(newOrder,
+                                                                              CFRangeMake(0, CFArrayGetCount(newOrder)),
+                                                                              serviceID);
+                                       if (curIndex != kCFNotFound) {
+                                               CFArrayRemoveValueAtIndex(newOrder, curIndex);
+                                       }
+
+                                       if (newIndex <= CFArrayGetCount(newOrder)) {
+                                               CFArrayInsertValueAtIndex(newOrder, newIndex - 1, serviceID);
+                                       } else {
+                                               CFArrayAppendValue(newOrder, serviceID);
+                                       }
+
+                                       ok = SCNetworkSetSetServiceOrder(net_set, newOrder);
+                                       CFRelease(newOrder);
+                                       if (!ok) {
+                                               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                                               return;
+                                       }
+
+                                       net_changed = TRUE;
+                               } else {
+                                       SCPrint(TRUE, stdout, CFSTR("set order to what?\n"));
+                                       return;
+                               }
+                       } else {
+                               SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+                               return;
+                       }
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+               }
+       }
+
+       return;
+}
+
+
+static void
+__show_service_interface(SCNetworkServiceRef service, const char *prefix)
+{
+       CFStringRef             description;
+       SCNetworkInterfaceRef   interface;
+
+       interface = SCNetworkServiceGetInterface(service);
+       if (interface == NULL) {
+               return;
+       }
+
+       description = _interface_description(interface);
+       SCPrint(TRUE, stdout, CFSTR("%s%@\n"), prefix, description);
+       CFRelease(description);
+
+       return;
+}
+
+static void
+__show_service_protocols(SCNetworkServiceRef service, const char *prefix, Boolean skipEmpty)
+{
+       CFIndex         i;
+       CFIndex         n;
+       CFArrayRef      protocols;
+
+       protocols = SCNetworkServiceCopyProtocols(service);
+       if (protocols == NULL) {
+               return;
+       }
+
+       n = CFArrayGetCount(protocols);
+       if (n > 1) {
+               CFMutableArrayRef       sorted;
+
+               sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+               CFArraySortValues(sorted,
+                                 CFRangeMake(0, n),
+                                 _compare_protocols,
+                                 NULL);
+               CFRelease(protocols);
+               protocols = sorted;
+       }
+
+       for (i = 0; i < n; i++) {
+               CFStringRef             description;
+               SCNetworkProtocolRef    protocol;
+
+               protocol = CFArrayGetValueAtIndex(protocols, i);
+               description = _protocol_description(protocol, skipEmpty);
+               if (description != NULL) {
+                       CFStringRef     protocolType;
+
+                       protocolType = SCNetworkProtocolGetProtocolType(protocol);
+                       SCPrint(TRUE, stdout,
+                               CFSTR("%s%@%*s : %@\n"),
+                               prefix,
+                               protocolType,
+                               sizeof("Interface") - CFStringGetLength(protocolType) - 1,
+                               "",
+                               description);
+                       CFRelease(description);
+               }
+       }
+
+       CFRelease(protocols);
+       return;
+}
+
+
+__private_extern__
+void
+show_service(int argc, char **argv)
+{
+       SCNetworkInterfaceRef   interface;
+       CFArrayRef              protocols;
+       SCNetworkServiceRef     service;
+       CFStringRef             serviceName;
+
+       if (argc == 1) {
+               service = _find_service(argv[0]);
+       } else {
+               if (net_service != NULL) {
+                       service = net_service;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("service not selected\n"));
+                       return;
+               }
+       }
+
+       if (service == NULL) {
+               return;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("service id           = %@\n"), SCNetworkServiceGetServiceID(service));
+
+       serviceName = SCNetworkServiceGetName(service);
+       SCPrint(TRUE, stdout, CFSTR("name                 = %@\n"),
+               (serviceName != NULL) ? serviceName : CFSTR(""));
+
+       interface = SCNetworkServiceGetInterface(service);
+       if (interface != NULL) {
+               CFStringRef     interfaceName;
+
+               interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
+               if (interfaceName != NULL) {
+                       CFRetain(interfaceName);
+               } else {
+                       interfaceName = _interface_description(interface);
+               }
+               if (interfaceName != NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("interface            = %@\n"), interfaceName);
+                       CFRelease(interfaceName);
+               }
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("\n  No interface!\n\n"));
+       }
+
+       protocols = SCNetworkServiceCopyProtocols(service);
+       if (protocols != NULL) {
+               CFIndex n;
+
+               n = CFArrayGetCount(protocols);
+               if (n > 1) {
+                       CFMutableArrayRef       sorted;
+
+                       sorted = CFArrayCreateMutableCopy(NULL, 0, protocols);
+                       CFArraySortValues(sorted,
+                                         CFRangeMake(0, n),
+                                         _compare_protocols,
+                                         NULL);
+                       CFRelease(protocols);
+                       protocols = sorted;
+               }
+
+               if (n > 0) {
+                       CFIndex i;
+
+                       SCPrint(TRUE, stdout, CFSTR("configured protocols = "));
+                       for (i = 0; i < n; i++) {
+                               SCNetworkProtocolRef    protocol;
+
+                               protocol = CFArrayGetValueAtIndex(protocols, i);
+                               SCPrint(TRUE, stdout, CFSTR("%s%@"),
+                                       (i == 0) ? "" : ", ",
+                                       SCNetworkProtocolGetProtocolType(protocol));
+                       }
+                       SCPrint(TRUE, stdout, CFSTR("\n"));
+
+                       __show_service_protocols(service, "  ", FALSE);
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("no configured protocols\n"));
+               }
+
+               CFRelease(protocols);
+       }
+
+       if (_sc_debug) {
+               SCPrint(TRUE, stdout, CFSTR("\n%@\n"), service);
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+show_services(int argc, char **argv)
+{
+       CFIndex i;
+       CFIndex n;
+
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+               return;
+       }
+
+       if (argc == 1) {
+               if (services != NULL) CFRelease(services);
+               services = SCNetworkServiceCopyAll(prefs);
+       } else {
+               if (net_set == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+                       return;
+               }
+
+               if (services != NULL) CFRelease(services);
+               services = SCNetworkSetCopyServices(net_set);
+               n = (services != NULL) ? CFArrayGetCount(services) : 0;
+               if (n > 1) {
+                       CFArrayRef              order;
+                       CFMutableArrayRef       sorted;
+
+                       order  = SCNetworkSetGetServiceOrder(net_set);
+                       sorted = CFArrayCreateMutableCopy(NULL, 0, services);
+                       CFArraySortValues(sorted,
+                                         CFRangeMake(0, CFArrayGetCount(sorted)),
+                                         _compare_services,
+                                         (void *)order);
+                       CFRelease(services);
+                       services = sorted;
+               }
+       }
+
+       if (services == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       n = CFArrayGetCount(services);
+       for (i = 0; i < n; i++) {
+               SCNetworkServiceRef     service;
+               CFStringRef             serviceName;
+               CFStringRef             serviceID;
+
+               service     = CFArrayGetValueAtIndex(services, i);
+               serviceID   = SCNetworkServiceGetServiceID(service);
+               serviceName = SCNetworkServiceGetName(service);
+               if (serviceName == NULL) serviceName = CFSTR("");
+
+               SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%-*s (%@)%s\n"),
+                       ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
+                       i + 1,
+                       serviceName,
+                       30 - CFStringGetLength(serviceName),
+                       " ",
+                       serviceID,
+                       SCNetworkServiceGetEnabled(service) ? "" : " *DISABLED*");
+
+               __show_service_interface(service, "       Interface : ");
+               __show_service_protocols(service, "       ", TRUE);
+       }
+
+       return;
+}
diff --git a/scutil.tproj/net_service.h b/scutil.tproj/net_service.h
new file mode 100644 (file)
index 0000000..d346ada
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_SERVICE_H
+#define _NET_SERVICE_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+CFComparisonResult     _compare_services       (const void *val1, const void *val2, void *context);
+
+void   create_service          (int argc, char **argv);
+void   disable_service         (int argc, char **argv);
+void   enable_service          (int argc, char **argv);
+void   remove_service          (int argc, char **argv);
+void   select_service          (int argc, char **argv);
+void   set_service             (int argc, char **argv);
+void   show_service            (int argc, char **argv);
+void   show_services           (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_SERVICE_H */
diff --git a/scutil.tproj/net_set.c b/scutil.tproj/net_set.c
new file mode 100644 (file)
index 0000000..0e0082e
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+
+#include "scutil.h"
+#include "net.h"
+#include "net_set.h"
+#include "net_service.h"
+
+
+/* -------------------- */
+
+
+static CFComparisonResult
+_compare_sets(const void *val1, const void *val2, void *context)
+{
+       CFStringRef     id1;
+       CFStringRef     id2;
+       CFStringRef     name1;
+       CFStringRef     name2;
+       SCNetworkSetRef s1      = (SCNetworkSetRef)val1;
+       SCNetworkSetRef s2      = (SCNetworkSetRef)val2;
+
+       name1 = SCNetworkSetGetName(s1);
+       name2 = SCNetworkSetGetName(s2);
+
+       if (name1 != NULL) {
+               if (name2 != NULL) {
+                       return CFStringCompare(name1, name2, 0);
+               } else {
+                       return kCFCompareLessThan;
+               }
+       }
+
+       if (name2 != NULL) {
+               return kCFCompareGreaterThan;
+       }
+
+       id1 = SCNetworkSetGetSetID(s1);
+       id2 = SCNetworkSetGetSetID(s2);
+       return CFStringCompare(id1, id2, 0);
+}
+
+
+static CFArrayRef
+_copy_sets()
+{
+       CFArrayRef              sets;
+       CFMutableArrayRef       sorted;
+
+       sets = SCNetworkSetCopyAll(prefs);
+       if (sets == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return NULL;
+       }
+
+       sorted = CFArrayCreateMutableCopy(NULL, 0, sets);
+       CFArraySortValues(sorted,
+                         CFRangeMake(0, CFArrayGetCount(sorted)),
+                         _compare_sets,
+                         NULL);
+
+       CFRelease(sets);
+       sets = CFArrayCreateCopy(NULL, sorted);
+       CFRelease(sorted);
+       return sets;
+}
+
+
+static SCNetworkSetRef
+_find_set(char *match)
+{
+       Boolean                 allowIndex      = TRUE;
+       CFIndex                 i;
+       CFIndex                 n;
+       CFStringRef             select_name     = NULL;
+       SCNetworkSetRef         selected        = NULL;
+
+       if (sets == NULL) {
+               if (prefs == NULL) {
+                       SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+                       return NULL;
+               }
+
+               sets = _copy_sets();
+               if (sets == NULL) {
+                       return NULL;
+               }
+
+               allowIndex = FALSE;
+       }
+
+       // try to select the set by its setID
+
+       select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);
+
+       n = CFArrayGetCount(sets);
+       for (i = 0; i < n; i++) {
+               SCNetworkSetRef set;
+               CFStringRef     setID;
+
+               set   = CFArrayGetValueAtIndex(sets, i);
+               setID = SCNetworkSetGetSetID(set);
+               if (CFEqual(select_name, setID)) {
+                       selected = set;
+                       goto done;
+
+               }
+       }
+
+       // try to select the set by its name
+
+       for (i = 0; i < n; i++) {
+               SCNetworkSetRef set;
+               CFStringRef     setName;
+
+               set     = CFArrayGetValueAtIndex(sets, i);
+               setName = SCNetworkSetGetName(set);
+               if ((setName != NULL) &&
+                   CFEqual(select_name, setName)) {
+                       if (selected == NULL) {
+                               selected = set;
+                       } else {
+                               // if multiple sets match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple sets match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the set by its name (case insensitive)
+
+       for (i = 0; i < n; i++) {
+               SCNetworkSetRef set;
+               CFStringRef     setName;
+
+               set     = CFArrayGetValueAtIndex(sets, i);
+               setName = SCNetworkSetGetName(set);
+               if ((setName != NULL) &&
+                   CFStringCompare(select_name,
+                                   setName,
+                                   kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+                       if (selected == NULL) {
+                               selected = set;
+                       } else {
+                               // if multiple sets match
+                               selected = NULL;
+                               SCPrint(TRUE, stdout, CFSTR("multiple sets match\n"));
+                               goto done;
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       // try to select the set by its index
+
+       if (allowIndex) {
+               char    *end;
+               char    *str    = match;
+               long    val;
+
+               errno = 0;
+               val = strtol(str, &end, 10);
+               if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
+                       if ((val > 0) && (val <= n)) {
+                               selected = CFArrayGetValueAtIndex(sets, val - 1);
+                       }
+               }
+       }
+
+       if (selected != NULL) {
+               goto done;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("no match, which set?\n"));
+
+    done :
+
+       if (select_name != NULL) CFRelease(select_name);
+       return selected;
+}
+
+
+/* -------------------- */
+
+
+__private_extern__
+void
+create_set(int argc, char **argv)
+{
+       SCNetworkSetRef set;
+       CFStringRef     setName;
+
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+               return;
+       }
+
+       set = SCNetworkSetCreate(prefs);
+       if (set == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       if ((argc > 0) && (strlen(argv[0]) > 0)) {
+               Boolean         ok;
+
+               setName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+               argv++;
+               argc--;
+
+               ok = SCNetworkSetSetName(set, setName);
+               CFRelease(setName);
+               if (!ok) {
+                       SCPrint(TRUE, stdout, CFSTR("set not created: %s\n"), SCErrorString(SCError()));
+                       (void) SCNetworkSetRemove(set);
+                       CFRelease(set);
+                       return;
+               }
+       }
+
+       net_changed = TRUE;
+
+       if (net_set != NULL) CFRelease(net_set);
+       net_set = set;
+
+       setName = SCNetworkSetGetName(set);
+       if (setName != NULL) {
+               SCPrint(TRUE, stdout,
+                       CFSTR("set \"%@\" (%@) created and selected\n"),
+                       setName,
+                       SCNetworkSetGetSetID(set));
+       } else {
+               SCPrint(TRUE, stdout,
+                       CFSTR("set ID \"%@\" created and selected\n"),
+                       SCNetworkSetGetSetID(set));
+       }
+
+       if (net_service != NULL) {
+               CFRelease(net_service);
+               net_service = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+       }
+
+       if (net_protocol != NULL) {
+               CFRelease(net_protocol);
+               net_protocol = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+       }
+
+       if (net_interface != NULL) {
+               CFRelease(net_interface);
+               net_interface = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+       }
+
+       if (sets != NULL) {
+               CFRelease(sets);
+               sets = NULL;
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+remove_set(int argc, char **argv)
+{
+       SCNetworkSetRef set     = NULL;
+       CFStringRef     setName;
+
+       if (argc == 1) {
+               set = _find_set(argv[0]);
+       } else {
+               if (net_set != NULL) {
+                       set = net_set;
+               }
+       }
+
+       if (set == NULL) {
+               return;
+       }
+
+       CFRetain(set);
+
+       if (!SCNetworkSetRemove(set)) {
+               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+               goto done;
+       }
+
+       net_changed = TRUE;
+
+       setName = SCNetworkSetGetName(set);
+       if (setName != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("set \"%@\" removed\n"), setName);
+       } else {
+               SCPrint(TRUE, stdout,
+                       CFSTR("set ID \"%@\" removed\n"),
+                       SCNetworkSetGetSetID(set));
+       }
+
+       if (CFEqual(set, net_set)) {
+               if (net_service != NULL) {
+                       CFRelease(net_service);
+                       net_service = NULL;
+                       SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+               }
+
+               if (net_protocol != NULL) {
+                       CFRelease(net_protocol);
+                       net_protocol = NULL;
+                       SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+               }
+
+               if (net_interface != NULL) {
+                       CFRelease(net_interface);
+                       net_interface = NULL;
+                       SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+               }
+       }
+
+       if (sets != NULL) {
+               CFRelease(sets);
+               sets = NULL;
+       }
+
+    done :
+
+       CFRelease(set);
+       return;
+}
+
+
+__private_extern__
+void
+select_set(int argc, char **argv)
+{
+       SCNetworkSetRef set;
+       CFStringRef     setName;
+
+       set = _find_set(argv[0]);
+
+       if (set == NULL) {
+               return;
+       }
+
+       if (net_set != NULL) CFRelease(net_set);
+       net_set = CFRetain(set);
+
+       setName = SCNetworkSetGetName(set);
+       if (setName != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("set \"%@\" selected\n"), setName);
+       } else {
+               SCPrint(TRUE, stdout,
+                       CFSTR("set ID \"%@\" selected\n"),
+                       SCNetworkSetGetSetID(set));
+       }
+
+       if (net_service != NULL) {
+               CFRelease(net_service);
+               net_service = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no service selected\n"));
+       }
+
+       if (net_protocol != NULL) {
+               CFRelease(net_protocol);
+               net_protocol = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
+       }
+
+       if (net_interface != NULL) {
+               CFRelease(net_interface);
+               net_interface = NULL;
+               SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+set_set(int argc, char **argv)
+{
+       Boolean ok;
+
+       if (net_set == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+               return;
+       }
+
+       if (argc < 1) {
+               SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+               return;
+       }
+
+       while (argc > 0) {
+               char    *command;
+
+               command = argv[0];
+               argv++;
+               argc--;
+
+               if (strcmp(command, "name") == 0) {
+                       CFStringRef     setName;
+
+                       if (argc < 1) {
+                               SCPrint(TRUE, stdout, CFSTR("name not specified\n"));
+                               return;
+                       }
+
+                       setName = (strlen(argv[0]) > 0)
+                                       ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8)
+                                       : NULL;
+                       argv++;
+                       argc--;
+
+                       ok = SCNetworkSetSetName(net_set, setName);
+                       if (setName != NULL) CFRelease(setName);
+                       if (!ok) {
+                               SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
+                               return;
+                       }
+
+                       net_changed = TRUE;
+
+                       if (sets != NULL) {
+                               /*
+                                * since the (displayed) ordering may have changed, refresh sets
+                                */
+                               char    *setID;
+
+                               setID = _SC_cfstring_to_cstring(SCNetworkSetGetSetID(net_set),
+                                                               NULL,
+                                                               0,
+                                                               kCFStringEncodingUTF8);
+
+                               CFRelease(net_set);
+                               net_set = NULL;
+
+                               CFRelease(sets);
+                               sets = NULL;
+
+                               net_set = _find_set(setID);
+                               if (net_set != NULL) {
+                                       CFRetain(net_set);
+                               }
+
+                               CFAllocatorDeallocate(NULL, setID);
+                       }
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("set what?\n"));
+               }
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+show_set(int argc, char **argv)
+{
+       CFArrayRef      services;
+       SCNetworkSetRef set     = NULL;
+       CFStringRef     setName;
+
+       if (argc == 1) {
+               set = _find_set(argv[0]);
+       } else {
+               if (net_set != NULL) {
+                       set = net_set;
+               } else {
+                       SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
+                       return;
+               }
+       }
+
+       if (set == NULL) {
+               return;
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("set id               = %@\n"), SCNetworkSetGetSetID(set));
+
+       setName = SCNetworkSetGetName(set);
+       SCPrint(TRUE, stdout, CFSTR("name                 = %@\n"),
+               (setName != NULL) ? setName : CFSTR(""));
+
+       services = SCNetworkSetCopyServices(set);
+       if (services != NULL) {
+               CFIndex                 i;
+               CFIndex                 n;
+               CFIndex                 nOrder  = 0;
+               CFArrayRef              order;
+               CFMutableArrayRef       sorted  = (CFMutableArrayRef)services;
+
+               order = SCNetworkSetGetServiceOrder(set);
+               if (order != NULL) {
+                       nOrder = CFArrayGetCount(order);
+               }
+
+               n = CFArrayGetCount(services);
+               if (n > 1) {
+                       sorted = CFArrayCreateMutableCopy(NULL, 0, services);
+                       CFArraySortValues(sorted,
+                                         CFRangeMake(0, CFArrayGetCount(sorted)),
+                                         _compare_services,
+                                         (void *)order);
+               }
+
+               SCPrint(TRUE, stdout, CFSTR("services =\n"));
+
+               for (i = 0; i < n; i++) {
+                       CFIndex                 orderIndex      = kCFNotFound;
+                       SCNetworkServiceRef     service;
+                       CFStringRef             serviceName;
+                       CFStringRef             serviceID;
+
+                       service     = CFArrayGetValueAtIndex(sorted, i);
+                       serviceID   = SCNetworkServiceGetServiceID(service);
+                       serviceName = SCNetworkServiceGetName(service);
+                       if (serviceName == NULL) serviceName = CFSTR("");
+
+                       if (order != NULL) {
+                               orderIndex  = CFArrayGetFirstIndexOfValue(order,
+                                                                         CFRangeMake(0, nOrder),
+                                                                         serviceID);
+                       }
+                       if (orderIndex != kCFNotFound) {
+                               SCPrint(TRUE, stdout, CFSTR("%c%2d: %@%-*s (%@)\n"),
+                                       ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
+                                       orderIndex + 1,
+                                       serviceName,
+                                       30 - CFStringGetLength(serviceName),
+                                       " ",
+                                       serviceID);
+                       } else {
+                               SCPrint(TRUE, stdout, CFSTR("%c  : %@%-*s (%@)\n"),
+                                       ((net_service != NULL) && CFEqual(service, net_service)) ? '>' : ' ',
+                                       serviceName,
+                                       30 - CFStringGetLength(serviceName),
+                                       " ",
+                                       serviceID);
+                       }
+               }
+
+               CFRelease(services);
+
+               if (sorted != services) CFRelease(sorted);
+       }
+
+       if (_sc_debug) {
+               SCPrint(TRUE, stdout, CFSTR("\n%@\n"), set);
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+show_sets(int argc, char **argv)
+{
+       SCNetworkSetRef current;
+       CFIndex         i;
+       CFIndex         n;
+
+       if (prefs == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
+               return;
+       }
+
+       if (sets == NULL) {
+               sets = _copy_sets();
+               if (sets == NULL) {
+                       return;
+               }
+       }
+
+       current = SCNetworkSetCopyCurrent(prefs);
+
+       n = CFArrayGetCount(sets);
+       for (i = 0; i < n; i++) {
+               SCNetworkSetRef set;
+               CFStringRef     setID;
+               CFStringRef     setName;
+
+               set     = CFArrayGetValueAtIndex(sets, i);
+               setID   = SCNetworkSetGetSetID(set);
+               setName = SCNetworkSetGetName(set);
+               if (setName == NULL) setName = CFSTR("");
+
+               SCPrint(TRUE, stdout, CFSTR(" %c%c%2d: %@%-*s (%@)\n"),
+                       ((current != NULL) && CFEqual(set, current)) ? '*' : ' ',
+                       ((net_set != NULL) && CFEqual(set, net_set)) ? '>' : ' ',
+                       i + 1,
+                       setName,
+                       30 - CFStringGetLength(setName),
+                       " ",
+                       setID);
+       }
+
+       if (current != NULL)    CFRelease(current);
+
+       return;
+}
diff --git a/scutil.tproj/net_set.h b/scutil.tproj/net_set.h
new file mode 100644 (file)
index 0000000..d8f7215
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NET_SET_H
+#define _NET_SET_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+void   create_set              (int argc, char **argv);
+void   remove_set              (int argc, char **argv);
+void   select_set              (int argc, char **argv);
+void   set_set                 (int argc, char **argv);
+void   show_set                (int argc, char **argv);
+void   show_sets               (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NET_SET_H */
diff --git a/scutil.tproj/notifications.c b/scutil.tproj/notifications.c
new file mode 100644 (file)
index 0000000..aa3715d
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - public API conversion
+ *
+ * November 9, 2000            Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "scutil.h"
+#include "notifications.h"
+
+
+static int                     osig;
+static struct sigaction                *oact   = NULL;
+
+
+static CFComparisonResult
+sort_keys(const void *p1, const void *p2, void *context) {
+       CFStringRef key1 = (CFStringRef)p1;
+       CFStringRef key2 = (CFStringRef)p2;
+       return CFStringCompare(key1, key2, 0);
+}
+
+
+__private_extern__
+void
+storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+       int             i;
+       CFIndex         n;
+
+       SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
+
+       n = CFArrayGetCount(changedKeys);
+       if (n > 0) {
+               for (i = 0; i < n; i++) {
+                       SCPrint(TRUE,
+                               stdout,
+                               CFSTR("  changed key [%d] = %@\n"),
+                               i,
+                               CFArrayGetValueAtIndex(changedKeys, i));
+               }
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("  no changed key's.\n"));
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_list(int argc, char **argv)
+{
+       int                     i;
+       CFArrayRef              list;
+       CFIndex                 listCnt;
+       Boolean                 isRegex = FALSE;
+       CFMutableArrayRef       sortedList;
+
+       if (store == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoStoreSession));
+               return;
+       }
+
+       if (argc == 1)
+               isRegex = TRUE;
+
+       list = isRegex ? watchedPatterns : watchedKeys;
+       if (!list) {
+               SCPrint(TRUE,
+                       stdout,
+                       CFSTR("  no notifier %s.\n"),
+                       isRegex ? "patterns" : "keys");
+               return;
+       }
+
+       listCnt = CFArrayGetCount(list);
+       sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list);
+       CFArraySortValues(sortedList,
+                         CFRangeMake(0, listCnt),
+                         sort_keys,
+                         NULL);
+
+       if (listCnt > 0) {
+               for (i = 0; i < listCnt; i++) {
+                       SCPrint(TRUE,
+                               stdout,
+                               CFSTR("  notifier %s [%d] = %@\n"),
+                               isRegex ? "pattern" : "key",
+                               i,
+                               CFArrayGetValueAtIndex(sortedList, i));
+               }
+       } else {
+               SCPrint(TRUE,
+                       stdout,
+                       CFSTR("  no notifier %s.\n"),
+                       isRegex ? "patterns" : "keys");
+       }
+       CFRelease(sortedList);
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_add(int argc, char **argv)
+{
+       CFStringRef             key;
+       CFMutableArrayRef       keys;
+       Boolean                 isRegex = FALSE;
+
+       if (store == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoStoreSession));
+               return;
+       }
+
+       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+       if (argc == 2)
+               isRegex = TRUE;
+
+       keys = isRegex ? watchedPatterns : watchedKeys;
+       if (CFArrayContainsValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusKeyExists));
+               CFRelease(key);
+               return;
+       }
+
+       CFArrayAppendValue(keys, key);
+       CFRelease(key);
+
+       if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_remove(int argc, char **argv)
+{
+       CFStringRef             key;
+       CFMutableArrayRef       keys;
+       CFIndex                 i;
+       Boolean                 isRegex = FALSE;
+
+       if (store == NULL) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoStoreSession));
+               return;
+       }
+
+       key   = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
+
+       if (argc == 2)
+               isRegex = TRUE;
+
+       keys = isRegex ? watchedPatterns : watchedKeys;
+       i = CFArrayGetFirstIndexOfValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key);
+       CFRelease(key);
+
+       if (i == kCFNotFound) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoKey));
+               return;
+       }
+
+       CFArrayRemoveValueAtIndex(keys, i);
+
+       if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_changes(int argc, char **argv)
+{
+       CFArrayRef      list;
+       CFIndex         listCnt;
+       int             i;
+
+       list = SCDynamicStoreCopyNotifiedKeys(store);
+       if (!list) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       listCnt = CFArrayGetCount(list);
+       if (listCnt > 0) {
+               for (i = 0; i < listCnt; i++) {
+                       SCPrint(TRUE,
+                               stdout,
+                               CFSTR("  changedKey [%d] = %@\n"),
+                               i,
+                               CFArrayGetValueAtIndex(list, i));
+               }
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("  no changedKey's.\n"));
+       }
+       CFRelease(list);
+
+       return;
+}
+
+
+static void *
+_watcher(void *arg)
+{
+       notifyRl = CFRunLoopGetCurrent();
+       if (!notifyRl) {
+               SCPrint(TRUE, stdout, CFSTR("  CFRunLoopGetCurrent() failed\n"));
+               return NULL;
+       }
+
+       notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+       if (!notifyRls) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return NULL;
+       }
+       CFRunLoopAddSource(notifyRl, notifyRls, kCFRunLoopDefaultMode);
+
+       CFRunLoopRun();
+       return NULL;
+}
+
+__private_extern__
+void
+do_notify_watch(int argc, char **argv)
+{
+       pthread_attr_t  tattr;
+       pthread_t       tid;
+
+       if (notifyRl) {
+               return;
+       }
+
+       pthread_attr_init(&tattr);
+       pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
+       pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
+//      pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
+       pthread_create(&tid, &tattr, _watcher, NULL);
+       pthread_attr_destroy(&tattr);
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_wait(int argc, char **argv)
+{
+       if (!SCDynamicStoreNotifyWait(store)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       return;
+}
+
+
+static boolean_t
+notificationWatcher(SCDynamicStoreRef store, void *arg)
+{
+       SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
+       SCPrint(TRUE, stdout, CFSTR("  arg = %s.\n"), (char *)arg);
+       return TRUE;
+}
+
+
+static boolean_t
+notificationWatcherVerbose(SCDynamicStoreRef store, void *arg)
+{
+       SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
+       SCPrint(TRUE, stdout, CFSTR("  arg = %s.\n"), (char *)arg);
+       do_notify_changes(0, NULL);     /* report the keys which changed */
+       return TRUE;
+}
+
+
+__private_extern__
+void
+do_notify_callback(int argc, char **argv)
+{
+       SCDynamicStoreCallBack_v1       func  = notificationWatcher;
+
+       if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
+               func = notificationWatcherVerbose;
+       }
+
+       if (!SCDynamicStoreNotifyCallback(store, CFRunLoopGetCurrent(), func, "Changed detected by callback handler!")) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_file(int argc, char **argv)
+{
+       int32_t         reqID = 0;
+       int             fd;
+       union {
+               char    data[4];
+               int32_t gotID;
+       } buf;
+       char            *bufPtr;
+       int             needed;
+
+       if (argc == 1) {
+               if ((sscanf(argv[0], "%d", &reqID) != 1)) {
+                       SCPrint(TRUE, stdout, CFSTR("invalid identifier.\n"));
+                       return;
+               }
+       }
+
+       if (!SCDynamicStoreNotifyFileDescriptor(store, reqID, &fd)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       bzero(buf.data, sizeof(buf.data));
+       bufPtr = &buf.data[0];
+       needed = sizeof(buf.gotID);
+       while (needed > 0) {
+               int     got;
+
+               got = read(fd, bufPtr, needed);
+               if (got == -1) {
+                       /* if error detected */
+                       SCPrint(TRUE, stdout, CFSTR("read() failed: %s.\n"), strerror(errno));
+                       break;
+               }
+
+               if (got == 0) {
+                       /* if end of file detected */
+                       SCPrint(TRUE, stdout, CFSTR("read(): detected end of file.\n"));
+                       break;
+               }
+
+               SCPrint(TRUE, stdout, CFSTR("Received %d bytes.\n"), got);
+               bufPtr += got;
+               needed -= got;
+       }
+
+       if (needed != sizeof(buf.gotID)) {
+               SCPrint(TRUE, stdout, CFSTR("  Received notification, identifier = %d.\n"), buf.gotID);
+       }
+
+       /* this utility only allows processes one notification per "n.file" request */
+       (void) SCDynamicStoreNotifyCancel(store);
+
+       (void) close(fd);       /* close my side of the file descriptor */
+
+       return;
+}
+
+
+static void
+signalCatcher(int signum)
+{
+       static int      n = 0;
+
+       SCPrint(TRUE, stdout, CFSTR("Received sig%s (#%d).\n"), sys_signame[signum], n++);
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_signal(int argc, char **argv)
+{
+       int                     sig;
+       pid_t                   pid;
+       struct sigaction        nact;
+       int                     ret;
+
+       if (isdigit(*argv[0])) {
+               if ((sscanf(argv[0], "%d", &sig) != 1) || (sig <= 0) || (sig >= NSIG)) {
+                       SCPrint(TRUE, stdout, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG-1);
+                       return;
+               }
+       } else {
+               for (sig = 1; sig < NSIG; sig++) {
+                       if (strcasecmp(argv[0], sys_signame[sig]) == 0)
+                               break;
+               }
+               if (sig >= NSIG) {
+                       CFMutableStringRef      str;
+
+                       SCPrint(TRUE, stdout, CFSTR("Signal must be one of the following:\n"));
+
+                       str = CFStringCreateMutable(NULL, 0);
+                       for (sig = 1; sig < NSIG; sig++) {
+                               CFStringAppendFormat(str, NULL, CFSTR(" %-6s"), sys_signame[sig]);
+                               if ((sig % 10) == 0) {
+                                       CFStringAppendFormat(str, NULL, CFSTR("\n"));
+                               }
+                       }
+                       if ((sig % 10) != 0) {
+                               CFStringAppendFormat(str, NULL, CFSTR("\n"));
+                       }
+                       SCPrint(TRUE, stdout, CFSTR("%@"), str);
+                       CFRelease(str);
+                       return;
+               }
+
+       }
+
+       if ((argc != 2) || (sscanf(argv[1], "%d", &pid) != 1)) {
+               pid = getpid();
+       }
+
+       if (oact != NULL) {
+               ret = sigaction(osig, oact, NULL);      /* restore original signal handler */
+       } else {
+               oact = malloc(sizeof(struct sigaction));
+       }
+
+       nact.sa_handler = signalCatcher;
+       sigemptyset(&nact.sa_mask);
+       nact.sa_flags = SA_RESTART;
+       ret = sigaction(sig, &nact, oact);
+       osig = sig;
+       SCPrint(TRUE, stdout, CFSTR("signal handler started.\n"));
+
+       if (!SCDynamicStoreNotifySignal(store, pid, sig)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       return;
+}
+
+
+__private_extern__
+void
+do_notify_cancel(int argc, char **argv)
+{
+       int                     ret;
+
+       if (notifyRls) {
+               CFRunLoopSourceInvalidate(notifyRls);
+               CFRelease(notifyRls);
+               notifyRls = NULL;
+       }
+
+       if (notifyRl) {
+               CFRunLoopStop(notifyRl);
+               notifyRl  = NULL;
+       }
+
+       if (!SCDynamicStoreNotifyCancel(store)) {
+               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
+               return;
+       }
+
+       if (oact != NULL) {
+               ret = sigaction(osig, oact, NULL);      /* restore original signal handler */
+               free(oact);
+               oact = NULL;
+       }
+
+       return;
+}
diff --git a/scutil.tproj/notifications.h b/scutil.tproj/notifications.h
new file mode 100644 (file)
index 0000000..a0f4735
--- /dev/null
@@ -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 <ajn@apple.com>
+ * - public API conversion
+ *
+ * November 9, 2000            Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#ifndef _NOTIFICATIONS_H
+#define _NOTIFICATIONS_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+void   storeCallback           (SCDynamicStoreRef      store,
+                                CFArrayRef             changedKeys,
+                                void                   *info);
+
+void   do_notify_list          (int argc, char **argv);
+void   do_notify_add           (int argc, char **argv);
+void   do_notify_remove        (int argc, char **argv);
+void   do_notify_changes       (int argc, char **argv);
+void   do_notify_watch         (int argc, char **argv);
+void   do_notify_wait          (int argc, char **argv);
+void   do_notify_callback      (int argc, char **argv);
+void   do_notify_signal        (int argc, char **argv);
+void   do_notify_file          (int argc, char **argv);
+void   do_notify_cancel        (int argc, char **argv);
+
+__END_DECLS
+
+#endif /* !_NOTIFICATIONS_H */
diff --git a/scutil.tproj/notify.c b/scutil.tproj/notify.c
deleted file mode 100644 (file)
index 9b0d9cc..0000000
+++ /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 <ajn@apple.com>
- * - public API conversion
- *
- * November 9, 2000            Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "scutil.h"
-#include "notify.h"
-
-
-static int                     osig;
-static struct sigaction                *oact   = NULL;
-
-
-static CFComparisonResult
-sort_keys(const void *p1, const void *p2, void *context) {
-       CFStringRef key1 = (CFStringRef)p1;
-       CFStringRef key2 = (CFStringRef)p2;
-       return CFStringCompare(key1, key2, 0);
-}
-
-
-void
-storeCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
-{
-       int             i;
-       CFIndex         n;
-
-       SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
-
-       n = CFArrayGetCount(changedKeys);
-       if (n > 0) {
-               for (i = 0; i < n; i++) {
-                       SCPrint(TRUE,
-                               stdout,
-                               CFSTR("  changed key [%d] = %@\n"),
-                               i,
-                               CFArrayGetValueAtIndex(changedKeys, i));
-               }
-       } else {
-               SCPrint(TRUE, stdout, CFSTR("  no changed key's.\n"));
-       }
-
-       return;
-}
-
-
-void
-do_notify_list(int argc, char **argv)
-{
-       int                     i;
-       CFArrayRef              list;
-       CFIndex                 listCnt;
-       Boolean                 isRegex = FALSE;
-       CFMutableArrayRef       sortedList;
-
-       if (!store) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoStoreSession));
-               return;
-       }
-
-       if (argc == 1)
-               isRegex = TRUE;
-
-       list = isRegex ? watchedPatterns : watchedKeys;
-       if (!list) {
-               SCPrint(TRUE,
-                       stdout,
-                       CFSTR("  no notifier %s.\n"),
-                       isRegex ? "patterns" : "keys");
-               return;
-       }
-
-       listCnt = CFArrayGetCount(list);
-       sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list);
-       CFArraySortValues(sortedList,
-                         CFRangeMake(0, listCnt),
-                         sort_keys,
-                         NULL);
-
-       if (listCnt > 0) {
-               for (i = 0; i < listCnt; i++) {
-                       SCPrint(TRUE,
-                               stdout,
-                               CFSTR("  notifier %s [%d] = %@\n"),
-                               isRegex ? "pattern" : "key",
-                               i,
-                               CFArrayGetValueAtIndex(sortedList, i));
-               }
-       } else {
-               SCPrint(TRUE,
-                       stdout,
-                       CFSTR("  no notifier %s.\n"),
-                       isRegex ? "patterns" : "keys");
-       }
-       CFRelease(sortedList);
-
-       return;
-}
-
-
-void
-do_notify_add(int argc, char **argv)
-{
-       CFStringRef             key;
-       CFMutableArrayRef       keys;
-       Boolean                 isRegex = FALSE;
-
-       if (!store) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoStoreSession));
-               return;
-       }
-
-       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
-
-       if (argc == 2)
-               isRegex = TRUE;
-
-       keys = isRegex ? watchedPatterns : watchedKeys;
-       if (CFArrayContainsValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusKeyExists));
-               CFRelease(key);
-               return;
-       }
-
-       CFArrayAppendValue(keys, key);
-       CFRelease(key);
-
-       if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-       }
-
-       return;
-}
-
-
-void
-do_notify_remove(int argc, char **argv)
-{
-       CFStringRef             key;
-       CFMutableArrayRef       keys;
-       CFIndex                 i;
-       Boolean                 isRegex = FALSE;
-
-       if (!store) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoStoreSession));
-               return;
-       }
-
-       key   = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
-
-       if (argc == 2)
-               isRegex = TRUE;
-
-       keys = isRegex ? watchedPatterns : watchedKeys;
-       i = CFArrayGetFirstIndexOfValue(keys, CFRangeMake(0, CFArrayGetCount(keys)), key);
-       CFRelease(key);
-
-       if (i == kCFNotFound) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(kSCStatusNoKey));
-               return;
-       }
-
-       CFArrayRemoveValueAtIndex(keys, i);
-
-       if (!SCDynamicStoreSetNotificationKeys(store, watchedKeys, watchedPatterns)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-       }
-
-       return;
-}
-
-
-void
-do_notify_changes(int argc, char **argv)
-{
-       CFArrayRef      list;
-       CFIndex         listCnt;
-       int             i;
-
-       list = SCDynamicStoreCopyNotifiedKeys(store);
-       if (!list) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return;
-       }
-
-       listCnt = CFArrayGetCount(list);
-       if (listCnt > 0) {
-               for (i = 0; i < listCnt; i++) {
-                       SCPrint(TRUE,
-                               stdout,
-                               CFSTR("  changedKey [%d] = %@\n"),
-                               i,
-                               CFArrayGetValueAtIndex(list, i));
-               }
-       } else {
-               SCPrint(TRUE, stdout, CFSTR("  no changedKey's.\n"));
-       }
-       CFRelease(list);
-
-       return;
-}
-
-
-static void *
-_watcher(void *arg)
-{
-       notifyRl = CFRunLoopGetCurrent();
-       if (!notifyRl) {
-               SCPrint(TRUE, stdout, CFSTR("  CFRunLoopGetCurrent() failed\n"));
-               return NULL;
-       }
-
-       notifyRls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
-       if (!notifyRls) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return NULL;
-       }
-       CFRunLoopAddSource(notifyRl, notifyRls, kCFRunLoopDefaultMode);
-
-       CFRunLoopRun();
-       return NULL;
-}
-
-void
-do_notify_watch(int argc, char **argv)
-{
-       pthread_attr_t  tattr;
-       pthread_t       tid;
-
-       if (notifyRl) {
-               return;
-       }
-
-       pthread_attr_init(&tattr);
-       pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
-       pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
-//      pthread_attr_setstacksize(&tattr, 96 * 1024); // each thread gets a 96K stack
-       pthread_create(&tid, &tattr, _watcher, NULL);
-       pthread_attr_destroy(&tattr);
-
-       return;
-}
-
-
-void
-do_notify_wait(int argc, char **argv)
-{
-       if (!SCDynamicStoreNotifyWait(store)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return;
-       }
-
-       return;
-}
-
-
-static boolean_t
-notificationWatcher(SCDynamicStoreRef store, void *arg)
-{
-       SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
-       SCPrint(TRUE, stdout, CFSTR("  arg = %s.\n"), (char *)arg);
-       return TRUE;
-}
-
-
-static boolean_t
-notificationWatcherVerbose(SCDynamicStoreRef store, void *arg)
-{
-       SCPrint(TRUE, stdout, CFSTR("notification callback (store address = %p).\n"), store);
-       SCPrint(TRUE, stdout, CFSTR("  arg = %s.\n"), (char *)arg);
-       do_notify_changes(0, NULL);     /* report the keys which changed */
-       return TRUE;
-}
-
-
-void
-do_notify_callback(int argc, char **argv)
-{
-       SCDynamicStoreCallBack_v1       func  = notificationWatcher;
-
-       if ((argc == 1) && (strcmp(argv[0], "verbose") == 0)) {
-               func = notificationWatcherVerbose;
-       }
-
-       if (!SCDynamicStoreNotifyCallback(store, CFRunLoopGetCurrent(), func, "Changed detected by callback handler!")) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return;
-       }
-
-       return;
-}
-
-
-void
-do_notify_file(int argc, char **argv)
-{
-       int32_t         reqID = 0;
-       int             fd;
-       union {
-               char    data[4];
-               int32_t gotID;
-       } buf;
-       char            *bufPtr;
-       int             needed;
-
-       if (argc == 1) {
-               if ((sscanf(argv[0], "%d", &reqID) != 1)) {
-                       SCPrint(TRUE, stdout, CFSTR("invalid identifier.\n"));
-                       return;
-               }
-       }
-
-       if (!SCDynamicStoreNotifyFileDescriptor(store, reqID, &fd)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return;
-       }
-
-       bzero(buf.data, sizeof(buf.data));
-       bufPtr = &buf.data[0];
-       needed = sizeof(buf.gotID);
-       while (needed > 0) {
-               int     got;
-
-               got = read(fd, bufPtr, needed);
-               if (got == -1) {
-                       /* if error detected */
-                       SCPrint(TRUE, stdout, CFSTR("read() failed: %s.\n"), strerror(errno));
-                       break;
-               }
-
-               if (got == 0) {
-                       /* if end of file detected */
-                       SCPrint(TRUE, stdout, CFSTR("read(): detected end of file.\n"));
-                       break;
-               }
-
-               SCPrint(TRUE, stdout, CFSTR("Received %d bytes.\n"), got);
-               bufPtr += got;
-               needed -= got;
-       }
-
-       if (needed != sizeof(buf.gotID)) {
-               SCPrint(TRUE, stdout, CFSTR("  Received notification, identifier = %d.\n"), buf.gotID);
-       }
-
-       /* this utility only allows processes one notification per "n.file" request */
-       (void) SCDynamicStoreNotifyCancel(store);
-
-       (void) close(fd);       /* close my side of the file descriptor */
-
-       return;
-}
-
-
-static void
-signalCatcher(int signum)
-{
-       static int      n = 0;
-
-       SCPrint(TRUE, stdout, CFSTR("Received sig%s (#%d).\n"), sys_signame[signum], n++);
-       return;
-}
-
-
-void
-do_notify_signal(int argc, char **argv)
-{
-       int                     sig;
-       pid_t                   pid;
-       struct sigaction        nact;
-       int                     ret;
-
-       if (isdigit(*argv[0])) {
-               if ((sscanf(argv[0], "%d", &sig) != 1) || (sig <= 0) || (sig >= NSIG)) {
-                       SCPrint(TRUE, stdout, CFSTR("signal must be in the range of 1 .. %d.\n"), NSIG-1);
-                       return;
-               }
-       } else {
-               for (sig = 1; sig < NSIG; sig++) {
-                       if (strcasecmp(argv[0], sys_signame[sig]) == 0)
-                               break;
-               }
-               if (sig >= NSIG) {
-                       CFMutableStringRef      str;
-
-                       SCPrint(TRUE, stdout, CFSTR("Signal must be one of the following:\n"));
-
-                       str = CFStringCreateMutable(NULL, 0);
-                       for (sig = 1; sig < NSIG; sig++) {
-                               CFStringAppendFormat(str, NULL, CFSTR(" %-6s"), sys_signame[sig]);
-                               if ((sig % 10) == 0) {
-                                       CFStringAppendFormat(str, NULL, CFSTR("\n"));
-                               }
-                       }
-                       if ((sig % 10) != 0) {
-                               CFStringAppendFormat(str, NULL, CFSTR("\n"));
-                       }
-                       SCPrint(TRUE, stdout, CFSTR("%@"), str);
-                       CFRelease(str);
-                       return;
-               }
-
-       }
-
-       if ((argc != 2) || (sscanf(argv[1], "%d", &pid) != 1)) {
-               pid = getpid();
-       }
-
-       if (oact != NULL) {
-               ret = sigaction(osig, oact, NULL);      /* restore original signal handler */
-       } else {
-               oact = malloc(sizeof(struct sigaction));
-       }
-
-       nact.sa_handler = signalCatcher;
-       sigemptyset(&nact.sa_mask);
-       nact.sa_flags = SA_RESTART;
-       ret = sigaction(sig, &nact, oact);
-       osig = sig;
-       SCPrint(TRUE, stdout, CFSTR("signal handler started.\n"));
-
-       if (!SCDynamicStoreNotifySignal(store, pid, sig)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return;
-       }
-
-       return;
-}
-
-
-void
-do_notify_cancel(int argc, char **argv)
-{
-       int                     ret;
-
-       if (notifyRls) {
-               CFRunLoopRemoveSource(notifyRl, notifyRls, kCFRunLoopDefaultMode);
-               CFRelease(notifyRls);
-               notifyRls = NULL;
-       }
-
-       if (notifyRl) {
-               CFRunLoopStop(notifyRl);
-               notifyRl  = NULL;
-       }
-
-       if (!SCDynamicStoreNotifyCancel(store)) {
-               SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
-               return;
-       }
-
-       if (oact != NULL) {
-               ret = sigaction(osig, oact, NULL);      /* restore original signal handler */
-               free(oact);
-               oact = NULL;
-       }
-
-       return;
-}
diff --git a/scutil.tproj/notify.h b/scutil.tproj/notify.h
deleted file mode 100644 (file)
index 72bf1f2..0000000
+++ /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 <ajn@apple.com>
- * - public API conversion
- *
- * November 9, 2000            Allan Nathanson <ajn@apple.com>
- * - initial revision
- */
-
-#ifndef _NOTIFY_H
-#define _NOTIFY_H
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-void   storeCallback           (SCDynamicStoreRef      store,
-                                CFArrayRef             changedKeys,
-                                void                   *info);
-
-void   do_notify_list          (int argc, char **argv);
-void   do_notify_add           (int argc, char **argv);
-void   do_notify_remove        (int argc, char **argv);
-void   do_notify_changes       (int argc, char **argv);
-void   do_notify_watch         (int argc, char **argv);
-void   do_notify_wait          (int argc, char **argv);
-void   do_notify_callback      (int argc, char **argv);
-void   do_notify_signal        (int argc, char **argv);
-void   do_notify_file          (int argc, char **argv);
-void   do_notify_cancel        (int argc, char **argv);
-
-__END_DECLS
-
-#endif /* !_NOTIFY_H */
index f522a4296927437440abca54639c89bef3061a63..633556b92317a3e0b471f4d4f46a248f182f90a2 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 static SCPreferencesRef
 _open()
 {
 static SCPreferencesRef
 _open()
 {
-       SCPreferencesRef        prefs;
-
        prefs = SCPreferencesCreate(NULL, CFSTR("scutil"), NULL);
        prefs = SCPreferencesCreate(NULL, CFSTR("scutil"), NULL);
-       if (!prefs) {
+       if (prefs == NULL) {
                SCPrint(TRUE,
                        stdout,
                        CFSTR("SCPreferencesCreate() failed: %s\n"),
                SCPrint(TRUE,
                        stdout,
                        CFSTR("SCPreferencesCreate() failed: %s\n"),
@@ -150,7 +148,6 @@ set_ComputerName(int argc, char **argv)
 {
        CFStringEncoding        encoding;
        CFStringRef             hostname;
 {
        CFStringEncoding        encoding;
        CFStringRef             hostname;
-       SCPreferencesRef        prefs;
 
        if (argc == 0) {
                hostname = _copyStringFromSTDIN();
 
        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)
 {
 static void
 get_LocalHostName(int argc, char **argv)
 {
@@ -210,7 +268,6 @@ static void
 set_LocalHostName(int argc, char **argv)
 {
        CFStringRef             hostname = NULL;
 set_LocalHostName(int argc, char **argv)
 {
        CFStringRef             hostname = NULL;
-       SCPreferencesRef        prefs;
 
        if (argc == 0) {
                hostname = _copyStringFromSTDIN();
 
        if (argc == 0) {
                hostname = _copyStringFromSTDIN();
@@ -235,24 +292,26 @@ set_LocalHostName(int argc, char **argv)
 
 typedef void (*pref_func) (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;
        char            *pref;
        pref_func       get;
        pref_func       set;
-} prefs[] = {
+} pref_keys[] = {
        { "ComputerName",       get_ComputerName,       set_ComputerName        },
        { "ComputerName",       get_ComputerName,       set_ComputerName        },
+       { "HostName",           get_HostName,           set_HostName            },
        { "LocalHostName",      get_LocalHostName,      set_LocalHostName       }
 };
        { "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;
 
 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;
                }
        }
                        return i;
                }
        }
@@ -261,6 +320,7 @@ findPref(char *pref)
 }
 
 
 }
 
 
+__private_extern__
 void
 do_getPref(char *pref, int argc, char **argv)
 {
 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) {
 
        i = findPref(pref);
        if (i >= 0) {
-               (*prefs[i].get)(argc, argv);
+               (*pref_keys[i].get)(argc, argv);
        }
        return;
 }
 
 
        }
        return;
 }
 
 
+__private_extern__
 void
 do_setPref(char *pref, int argc, char **argv)
 {
 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) {
 
        i = findPref(pref);
        if (i >= 0) {
-               (*prefs[i].set)(argc, argv);
+               (*pref_keys[i].set)(argc, argv);
        }
        return;
 }
        }
        return;
 }
diff --git a/scutil.tproj/scutil.8 b/scutil.tproj/scutil.8
new file mode 100644 (file)
index 0000000..215ec8f
--- /dev/null
@@ -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.
index b5387111b489790e8b263a413c61c26c401fe05c..09b6f0ac0ac78a6bb4644f9580f00b94789b2fd4 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
 /*
  * Modification History
  *
+ * August 4, 2004              Allan Nathanson <ajn@apple.com>
+ * - added network configuration (prefs) support
+ *
  * September 25, 2002          Allan Nathanson <ajn@apple.com>
  * - added command line history & editing
  *
  * September 25, 2002          Allan Nathanson <ajn@apple.com>
  * - added command line history & editing
  *
 #include "scutil.h"
 #include "commands.h"
 #include "dictionary.h"
 #include "scutil.h"
 #include "commands.h"
 #include "dictionary.h"
-#include "tests.h"
+#include "net.h"
 #include "prefs.h"
 #include "prefs.h"
+#include "session.h"
+#include "tests.h"
 
 #include "SCDynamicStoreInternal.h"
 
 
 #include "SCDynamicStoreInternal.h"
 
 #define LINE_LENGTH 256
 
 
 #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'     },
 //     { "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'     },
 //     { "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,   '?'     },
        { "get",                required_argument,      NULL,   0       },
        { "help",               no_argument,            NULL,   '?'     },
+       { "net",                no_argument,            NULL,   0       },
+       { "proxy",              no_argument,            NULL,   0       },
        { "set",                required_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;
 getString(char **line)
 {
        char *s, *e, c, *string;
@@ -178,13 +188,18 @@ getString(char **line)
 }
 
 
 }
 
 
+__private_extern__
 Boolean
 process_line(InputRef src)
 {
 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;
 
        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);
        }
 
                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
        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;
        }
 
                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);
 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("\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);
 }
 
        exit (EX_USAGE);
 }
 
@@ -260,11 +286,14 @@ prompt(EditLine *el)
 int
 main(int argc, char * const argv[])
 {
 int
 main(int argc, char * const argv[])
 {
+       Boolean                 dns     = FALSE;
        char                    *get    = NULL;
        char                    *get    = NULL;
+       Boolean                 net     = FALSE;
        extern int              optind;
        int                     opt;
        int                     opti;
        const char              *prog   = argv[0];
        extern int              optind;
        int                     opt;
        int                     opti;
        const char              *prog   = argv[0];
+       Boolean                 proxy   = FALSE;
        Boolean                 reach   = FALSE;
        char                    *set    = NULL;
        InputRef                src;
        Boolean                 reach   = FALSE;
        char                    *set    = NULL;
        InputRef                src;
@@ -299,9 +328,18 @@ main(int argc, char * const argv[])
                        xStore++;
                        break;
                case 0:
                        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++;
                                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++;
                        } else if (strcmp(longopts[opti].name, "set") == 0) {
                                set = optarg;
                                xStore++;
@@ -334,6 +372,12 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
                /* 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) {
        /* 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 */
        }
 
                /* 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) {
        /* are we changing a preference value */
        if (set) {
                if (findPref(set) < 0) {
@@ -352,8 +402,25 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
                /* 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);
 
        /* allocate command input stream */
        src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
index 794530bd9f538b09ae4bba1ca5178414b4b8e4c1..cf0125670fb779fbae4aeb39a3435c4b96035b8d 100644 (file)
@@ -49,9 +49,11 @@ typedef struct {
 } Input, *InputRef;
 
 
 } Input, *InputRef;
 
 
+extern InputRef                        currentInput;
 extern int                     nesting;
 extern CFRunLoopRef            notifyRl;
 extern CFRunLoopSourceRef      notifyRls;
 extern int                     nesting;
 extern CFRunLoopRef            notifyRl;
 extern CFRunLoopSourceRef      notifyRls;
+extern SCPreferencesRef                prefs;
 extern SCDynamicStoreRef       store;
 extern CFPropertyListRef       value;
 extern CFMutableArrayRef       watchedKeys;
 extern SCDynamicStoreRef       store;
 extern CFPropertyListRef       value;
 extern CFMutableArrayRef       watchedKeys;
index 9c5d2cbd5fd14945612e07e2b4e7a453c8192de0..0cba63eea4ff40de44921ff214200517e513d3fc 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -33,8 +33,9 @@
 
 #include "scutil.h"
 #include "session.h"
 
 #include "scutil.h"
 #include "session.h"
-#include "notify.h"
+#include "notifications.h"
 
 
+__private_extern__
 void
 do_open(int argc, char **argv)
 {
 void
 do_open(int argc, char **argv)
 {
@@ -44,8 +45,24 @@ do_open(int argc, char **argv)
                CFRelease(watchedPatterns);
        }
 
                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;
        }
                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) {
 void
 do_close(int argc, char **argv)
 {
        if (notifyRls) {
-               CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
+               CFRunLoopSourceInvalidate(notifyRls);
                CFRelease(notifyRls);
                notifyRls = NULL;
        }
                CFRelease(notifyRls);
                notifyRls = NULL;
        }
@@ -83,6 +101,7 @@ do_close(int argc, char **argv)
 }
 
 
 }
 
 
+__private_extern__
 void
 do_lock(int argc, char **argv)
 {
 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)
 {
 void
 do_unlock(int argc, char **argv)
 {
index 74a404931a63e659a55c1e95574ee0fe9908416f..51c9a8b0da67ee3f792b618bb443de93b05f1f16 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -44,7 +44,9 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include <dnsinfo.h>
 
 
+__private_extern__
 void
 do_checkReachability(int argc, char **argv)
 {
 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)
 {
 void
 do_snapshot(int argc, char **argv)
 {
@@ -185,6 +271,7 @@ waitTimeout(int sigraised)
 }
 
 
 }
 
 
+__private_extern__
 void
 do_wait(char *waitKey, int timeout)
 {
 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);
        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);
                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)) {
        CFArrayAppendValue(keys, key);
 
        if (!SCDynamicStoreSetNotificationKeys(store, keys, NULL)) {
@@ -225,7 +312,7 @@ do_wait(char *waitKey, int timeout)
        }
        CFRelease(key);
 
        }
        CFRelease(key);
 
-       if (waitTimeout > 0) {
+       if (timeout > 0) {
                signal(SIGALRM, waitTimeout);
                bzero(&itv, sizeof(itv));
                itv.it_value.tv_sec = timeout;
                signal(SIGALRM, waitTimeout);
                bzero(&itv, sizeof(itv));
                itv.it_value.tv_sec = timeout;
index c13c99f51f8115f4ac7a76e966a85feab3c4f1f0..236e90f994269ddab4c96b36959def6f589fcfc6 100644 (file)
@@ -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@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 __BEGIN_DECLS
 
 
 __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
 
 
 __END_DECLS