]> 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;
-    SCPreferencesRef           session = NULL;
+    SCPreferencesRef           prefs = NULL;
     Boolean                    success = FALSE;
 
     if (applicationID == NULL) {
@@ -116,12 +116,12 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
     if (path == NULL) {
        goto done;
     }
-    session = SCPreferencesCreate(NULL, CFSTR("DHCPClientSetAppReqParams"),
-                                 CFSTR(DHCPCLIENT_PREFERENCES_ID));
-    if (session == NULL) {
+    prefs = SCPreferencesCreate(NULL, CFSTR("DHCPClientSetAppReqParams"),
+                               CFSTR(DHCPCLIENT_PREFERENCES_ID));
+    if (prefs == NULL) {
        goto done;
     }
-    dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(session, path);
+    dict = (CFMutableDictionaryRef)SCPreferencesPathGetValue(prefs, path);
     if (dict == NULL) {
        dict = CFDictionaryCreateMutable(NULL, 0,
                                         &kCFTypeDictionaryKeyCallBacks,
@@ -165,19 +165,19 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
     else {
        CFDictionaryRemoveValue(dict, CFSTR(DHCP_REQUESTED_PARAMETER_LIST));
     }
-    if (SCPreferencesLock(session, TRUE)) {
-       success = SCPreferencesPathSetValue(session, path, dict);
+    if (SCPreferencesLock(prefs, TRUE)) {
+       success = SCPreferencesPathSetValue(prefs, path, dict);
        if (success) {
-           success = SCPreferencesCommitChanges(session);
+           success = SCPreferencesCommitChanges(prefs);
            if (success) {
-               (void)SCPreferencesApplyChanges(session);
+               (void)SCPreferencesApplyChanges(prefs);
            }
        }
-       (void)SCPreferencesUnlock(session);
+       (void)SCPreferencesUnlock(prefs);
     }
  done:
-    if (session) {
-       CFRelease(session);
+    if (prefs) {
+       CFRelease(prefs);
     }
     if (path) {
        CFRelease(path);
@@ -196,7 +196,7 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID,
     UInt8 *                    options = NULL;
     CFArrayRef                 parms;
     CFStringRef                        path = NULL;
-    SCPreferencesRef           session = NULL;
+    SCPreferencesRef           prefs = NULL;
 
     if (applicationID == NULL) {
        goto done;
@@ -205,12 +205,12 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID,
     if (path == NULL) {
        goto done;
     }
-    session = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"),
-                                 CFSTR(DHCPCLIENT_PREFERENCES_ID));
-    if (session == NULL) {
+    prefs = SCPreferencesCreate(NULL, CFSTR("DHCPClientCopyAppReqParams"),
+                               CFSTR(DHCPCLIENT_PREFERENCES_ID));
+    if (prefs == NULL) {
        goto done;
     }
-    dict = SCPreferencesPathGetValue(session, path);
+    dict = SCPreferencesPathGetValue(prefs, path);
     if (dict == NULL) {
        goto done;
     }
@@ -222,8 +222,8 @@ DHCPClientPreferencesCopyApplicationOptions(CFStringRef applicationID,
     options = S_get_char_array(parms, count);
 
  done:
-    if (session) {
-       CFRelease(session);
+    if (prefs) {
+       CFRelease(prefs);
     }
     if (path) {
        CFRelease(path);
index 7ba074a5ea57fa6d70c1e11bb397e116c53b9631..5e0d0054e10a1758d904c1f1afab90898900bf8c 100644 (file)
@@ -28,7 +28,9 @@
 #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
@@ -36,15 +38,15 @@ __BEGIN_DECLS
 /*!
        @function DHCPClientPreferencesSetApplicationOptions
        @discussion Updates the DHCP client preferences to include the
-               given list of options for the given "applicationID".
+               given list of options for the given application ID.
        @param applicationID The application's preference ID, for example:
                "com.apple.SystemPreferences".
        @param options An array of 8-bit values containing the
-               DHCP option codes (see RFC 2132) for this applicationID.
+               DHCP option codes (see RFC 2132) for this application ID.
                A NULL value will clear the list of options for this
                application ID.
-       @param count The number of elements in "options".
-       @result TRUE if the operation succeeded, FALSE otherwise.
+       @param count The number of elements in the options parameter.
+       @result Returns TRUE if the operation succeeded, FALSE otherwise.
  */
 
 Boolean
@@ -55,14 +57,14 @@ DHCPClientPreferencesSetApplicationOptions(CFStringRef applicationID,
 /*!
        @function DHCPClientPreferencesCopyApplicationOptions
        @discussion Copies the requested DHCP options for the
-               given "applicationID".
+               given application ID.
        @param applicationID The application's preference ID, for example
                "com.apple.SystemPreferences".
        @param count The number of elements in the returned array.
-       @result The list of options for the given "applicationID", or
+       @result Returns the list of options for the given application ID, or
                NULL if no options are defined or an error occurred.
 
-               When done, use free() to release a non-NULL return value.
+               When you are finished, use free() to release a non-NULL return value.
  */
 
 UInt8 *
index 0ee06ce981e4c2f1fe867f178d14abb00b62d6a5..b904d0f3ba024ba30f5b7a532ddc926bad545874 100644 (file)
@@ -82,8 +82,6 @@ __DeviceOnHoldDeallocate(CFTypeRef cf)
 {
        DeviceOnHoldPrivateRef  DeviceOnHoldPrivate     = (DeviceOnHoldPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__DeviceOnHoldDeallocate:"));
-
        /* release resources */
        if (DeviceOnHoldPrivate->name)          CFRelease(DeviceOnHoldPrivate->name);
        if (DeviceOnHoldPrivate->sock != -1) {
@@ -167,27 +165,29 @@ IsDeviceOnHoldSupported(CFStringRef       deviceName,     // "modem"
        CFMutableDictionaryRef  deviceToMatch;
        uint32_t                deviceSupportsHoldValue;
        kern_return_t           kr;
-       mach_port_t             masterPort;
-       io_iterator_t           matchingServices;
+       static mach_port_t      masterPort                      = MACH_PORT_NULL;
+       io_iterator_t           matchingServices;
        CFNumberRef             num;
        CFMutableDictionaryRef  properties;
        Boolean                 result                          = FALSE;
        io_service_t            service;
 
-       if (CFStringCompare(deviceName, CFSTR("modem"), NULL) == kCFCompareEqualTo) {
-               kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
-               if (kr != KERN_SUCCESS) {
-                       goto errorExit;
+       if (CFStringCompare(deviceName, CFSTR("modem"), 0) == kCFCompareEqualTo) {
+               if (masterPort == MACH_PORT_NULL) {
+                       kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+                       if (kr != KERN_SUCCESS) {
+                               return FALSE;
+                       }
                }
 
                deviceToMatch = IOServiceMatching("InternalModemSupport");
-               if (!deviceToMatch) {
-                       goto errorExit;
+               if (deviceToMatch == NULL) {
+                       return FALSE;
                }
 
                kr = IOServiceGetMatchingServices(masterPort, deviceToMatch, &matchingServices);
                if (kr != KERN_SUCCESS) {
-                       goto errorExit;
+                       return FALSE;
                }
 
                for ( ; (service = IOIteratorNext(matchingServices)) ; IOObjectRelease(service)) {
@@ -220,10 +220,6 @@ IsDeviceOnHoldSupported(CFStringRef        deviceName,     // "modem"
        //       to know the exact driver they are searching for.
 
        return result;
-
-    errorExit:
-
-       return FALSE;
 }
 
 
@@ -235,7 +231,7 @@ DeviceOnHoldCreate(CFAllocatorRef   allocator,
        DeviceOnHoldPrivateRef  devicePrivate;
        int                     status;
 
-       if (CFStringCompare(deviceName, CFSTR("modem"), NULL) != kCFCompareEqualTo) {
+       if (CFStringCompare(deviceName, CFSTR("modem"), 0) != kCFCompareEqualTo) {
                return NULL;
        }
 
index 7cd4902bff6660cfaf5244e833313f234658d2c3..0d88c539558b1b25ead79f5d56c363e2a90a8a7f 100644 (file)
 #include <CoreFoundation/CoreFoundation.h>
 
 
+/*!
+       @header DeviceOnHold
+ */
+
+
 /*!
        @enum
        @discussion Returned status codes from DeviceOnHoldGetStatus()
diff --git a/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings b/SystemConfiguration.fproj/English.lproj/NetworkInterface.strings
new file mode 100644 (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;
-       mach_port_t             masterPort      = MACH_PORT_NULL;
+       static mach_port_t      masterPort      = MACH_PORT_NULL;
        CFMutableDictionaryRef  matchingDict;
 
        /* look for a matching interface in the IORegistry */
 
+       if (masterPort == MACH_PORT_NULL) {
+               kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
+               if (kr != KERN_SUCCESS) {
+                       return FALSE;
+               }
+       }
+
        matchingDict = IOBSDNameMatching(masterPort, 0, ifr_name);
        if (matchingDict) {
                /* Note: IOServiceGetMatchingServices consumes a reference on the 'matchingDict' */
@@ -531,7 +538,7 @@ NetworkInterfaceCopyMTU(CFStringRef interface,
 
        bzero((void *)&ifr, sizeof(ifr));
        if (_SC_cfstring_to_cstring(interface, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII) == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("could not convert inteface name"));
+               SCLog(TRUE, LOG_ERR, CFSTR("could not convert interface name"));
                goto done;
        }
 
@@ -552,38 +559,22 @@ NetworkInterfaceCopyMTU(CFStringRef       interface,
 
        /* get valid MTU range */
 
-       if (mtu_min || mtu_max) {
-               ok = __getMTULimits(ifr.ifr_name, mtu_min, mtu_max);
-               if (!ok) {
-                       struct ifreq    vifr;
-                       struct vlanreq  vreq;
-
-                       // check if this is a vlan
-
-                       bzero(&vifr, sizeof(vifr));
-                       bzero(&vreq, sizeof(vreq));
-                       strncpy(vifr.ifr_name, ifr.ifr_name, sizeof(vifr.ifr_name));
-                       vifr.ifr_data = (caddr_t)&vreq;
+       if (mtu_min != NULL || mtu_max != NULL) {
+               if (ioctl(sock, SIOCGIFDEVMTU, (caddr_t)&ifr) == 0) {
+                       struct ifdevmtu *       devmtu_p;
 
-                       if (ioctl(sock, SIOCGETVLAN, (caddr_t)&vifr) == 0) {
-                               /*
-                                * yes, pass parent device MTU settings
-                                *
-                                *   min == parent device minimum MTU
-                                *   max == parent device current MTU
-                                */
-                               if (mtu_min) {
-                                       (void) __getMTULimits(vreq.vlr_parent, mtu_min, NULL);
-                               }
-                               if (mtu_max) {
-                                       bzero(&vifr, sizeof(vifr));
-                                       strncpy(vifr.ifr_name, vreq.vlr_parent, sizeof(vifr.ifr_name));
-                                       if (ioctl(sock, SIOCGIFMTU, (caddr_t)&vifr) == 0) {
-                                               *mtu_max = vifr.ifr_mtu;
-                                       }
-                               }
+                       devmtu_p = &ifr.ifr_devmtu;
+                       if (mtu_min != NULL) {
+                               *mtu_min = (devmtu_p->ifdm_min > IF_MINMTU)
+                                       ? devmtu_p->ifdm_min : IF_MINMTU;
+                       }
+                       if (mtu_max != NULL) {
+                               *mtu_max = devmtu_p->ifdm_max;
                        }
                }
+               else {
+                       (void)__getMTULimits(ifr.ifr_name, mtu_min, mtu_max);
+               }
        }
 
        ok = TRUE;
index f33f8c714fc0555ace0eb33a0ddb72526669b4b4..cb598fda7d92f3c36f9a6384f4f2860e5841fff5 100644 (file)
@@ -28,6 +28,9 @@
 #include <sys/cdefs.h>
 #include <CoreFoundation/CoreFoundation.h>
 
+/*!
+       @header LinkConfiguration
+*/
 
 __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_key_t   tsDataKey               = NULL;
+static pthread_key_t   tsDataKey;
 
 
 static void
index 00503ab652b223a19fde5376b79a6bf6626da97c..0e12fbb20e21028fc72aff1a43bd672ea12a3b6b 100644 (file)
@@ -40,7 +40,7 @@
 #include "config.h"            /* MiG generated file */
 
 Boolean
-SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+SCDynamicStoreAddTemporaryValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
 {
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        kern_return_t                   status;
@@ -53,13 +53,77 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR
        int                             newInstance;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), value);
+       if (store == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoStoreSession);
+       }
+
+       if (storePrivate->server == MACH_PORT_NULL) {
+               /* sorry, you must have an open session to play */
+               _SCErrorSet(kSCStatusNoStoreServer);
+               return FALSE;
+       }
+
+       /* serialize the key */
+       if (!_SCSerializeString(key, &utfKey, (void **)&myKeyRef, &myKeyLen)) {
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       /* serialize the data */
+       if (!_SCSerialize(value, &xmlData, (void **)&myDataRef, &myDataLen)) {
+               CFRelease(utfKey);
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       /* send the key & data to the server */
+       status = configadd_s(storePrivate->server,
+                            myKeyRef,
+                            myKeyLen,
+                            myDataRef,
+                            myDataLen,
+                            &newInstance,
+                            (int *)&sc_status);
+
+       /* clean up */
+       CFRelease(utfKey);
+       CFRelease(xmlData);
+
+       if (status != KERN_SUCCESS) {
+#ifdef DEBUG
+               if (status != MACH_SEND_INVALID_DEST)
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddTemporaryValue configadd_s(): %s"), mach_error_string(status));
+#endif /* DEBUG */
+               (void) mach_port_destroy(mach_task_self(), storePrivate->server);
+               storePrivate->server = MACH_PORT_NULL;
+               _SCErrorSet(status);
+               return FALSE;
        }
 
-       if (!store) {
+       if (sc_status != kSCStatusOK) {
+               _SCErrorSet(sc_status);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+Boolean
+SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListRef value)
+{
+       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
+       kern_return_t                   status;
+       CFDataRef                       utfKey;         /* serialized key */
+       xmlData_t                       myKeyRef;
+       CFIndex                         myKeyLen;
+       CFDataRef                       xmlData;        /* serialized data */
+       xmlData_t                       myDataRef;
+       CFIndex                         myDataLen;
+       int                             newInstance;
+       int                             sc_status;
+
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -98,8 +162,10 @@ SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR
        CFRelease(xmlData);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configadd(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddValue configadd(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
diff --git a/SystemConfiguration.fproj/SCDAddSession.c b/SystemConfiguration.fproj/SCDAddSession.c
deleted file mode 100644 (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
 
 
-const CFStringRef kSCConsoleSessionID          = CFSTR("kCGSSessionIDKey");            /* value is CFNumber */
-const CFStringRef kSCConsoleSessionUserName    = CFSTR("kCGSSessionUserNameKey");      /* value is CFString */
-const CFStringRef kSCConsoleSessionUID         = CFSTR("kCGSSessionUserIDKey");        /* value is CFNumber */
-const CFStringRef kSCConsoleSessionConsoleSet  = CFSTR("kCGSSessionConsoleSetKey");    /* value is CFNumber */
-const CFStringRef kSCConsoleSessionOnConsole   = CFSTR("kCGSSessionOnConsoleKey");     /* value is CFBoolean */
+// from CoreGraphics (CGSession.h)
+const CFStringRef kSCConsoleSessionUserName            = CFSTR("kCGSSessionUserNameKey");              /* value is CFString */
+const CFStringRef kSCConsoleSessionUID                 = CFSTR("kCGSSessionUserIDKey");                /* value is CFNumber (a uid_t) */
+const CFStringRef kSCConsoleSessionConsoleSet          = CFSTR("kCGSSessionConsoleSetKey");            /* value is CFNumber */
+const CFStringRef kSCConsoleSessionOnConsole           = CFSTR("kCGSSessionOnConsoleKey");             /* value is CFBoolean */
+const CFStringRef kSCConsoleSessionLoginDone           = CFSTR("kCGSessionLoginDoneKey");              /* value is CFBoolean */
+
+// from CoreGraphics (CGSSession.h)
+const CFStringRef kSCConsoleSessionID                  = CFSTR("kCGSSessionIDKey");                    /* value is CFNumber */
+
+// from loginwindow
+const CFStringRef kSCConsoleSessionSystemSafeBoot      = CFSTR("kCGSSessionSystemSafeBoot");           /* value is CFBoolean */
+const CFStringRef kSCConsoleSessionLoginwindowSafeLogin        = CFSTR("kCGSSessionLoginwindowSafeLogin");     /* value is CFBoolean */
 
 
 CFStringRef
@@ -84,13 +92,12 @@ SCDynamicStoreCopyConsoleUser(SCDynamicStoreRef     store,
        CFStringRef             key;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyConsoleUser"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return NULL;
                }
                tempSession = TRUE;
@@ -153,13 +160,12 @@ SCDynamicStoreCopyConsoleInformation(SCDynamicStoreRef store)
        CFStringRef             key;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyConsoleUser"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return NULL;
                }
                tempSession = TRUE;
@@ -200,24 +206,22 @@ SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef     store,
        CFStringRef             consoleUser;
        CFMutableDictionaryRef  dict            = NULL;
        CFStringRef             key             = SCDynamicStoreKeyCreateConsoleUser(NULL);
-       CFNumberRef             num;
        Boolean                 ok              = TRUE;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreSetConsoleUser"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return FALSE;
                }
                tempSession = TRUE;
        }
 
-       if (user == NULL) {
-               ok = SCDynamicStoreRemoveValue(store, key);
+       if ((user == NULL) && (sessions == NULL)) {
+               (void) SCDynamicStoreRemoveValue(store, key);
                goto done;
        }
 
@@ -226,19 +230,25 @@ SCDynamicStoreSetConsoleInformation(SCDynamicStoreRef     store,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
 
-       consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman);
-       CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser);
-       CFRelease(consoleUser);
+       if (user != NULL) {
+               CFNumberRef     num;
 
-       num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid);
-       CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num);
-       CFRelease(num);
+               consoleUser = CFStringCreateWithCString(NULL, user, kCFStringEncodingMacRoman);
+               CFDictionarySetValue(dict, kSCPropUsersConsoleUserName, consoleUser);
+               CFRelease(consoleUser);
 
-       num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid);
-       CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num);
-       CFRelease(num);
+               num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&uid);
+               CFDictionarySetValue(dict, kSCPropUsersConsoleUserUID, num);
+               CFRelease(num);
+
+               num = CFNumberCreate(NULL, kCFNumberSInt32Type, (SInt32 *)&gid);
+               CFDictionarySetValue(dict, kSCPropUsersConsoleUserGID, num);
+               CFRelease(num);
+       }
 
-       CFDictionarySetValue(dict, kSCPropUsersConsoleSessionInfo, sessions);
+       if (sessions != NULL) {
+               CFDictionarySetValue(dict, kSCPropUsersConsoleSessionInfo, sessions);
+       }
 
        ok = SCDynamicStoreSetValue(store, key, dict);
 
@@ -264,20 +274,19 @@ SCDynamicStoreSetConsoleUser(SCDynamicStoreRef    store,
        Boolean                 ok              = TRUE;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreSetConsoleUser"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return FALSE;
                }
                tempSession = TRUE;
        }
 
        if (user == NULL) {
-               ok = SCDynamicStoreRemoveValue(store, key);
+               (void) SCDynamicStoreRemoveValue(store, key);
                goto done;
        }
 
index 1d566af5dd3c465b054a17e824779fad7850cc9d..dcc82a1e9da990171249418280af25031cd777ab 100644 (file)
@@ -59,13 +59,7 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef store,
        CFDictionaryRef                 expDict         = NULL; /* dict (un-serialized / expanded) */
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keys     = %@"), keys);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  patterns = %@"), patterns);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -108,8 +102,10 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef       store,
        if (xmlPatterns)        CFRelease(xmlPatterns);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configget_m(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple configget_m(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -118,10 +114,12 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef      store,
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDictRef, xmlDictLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyMultiple vm_deallocate(): %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
@@ -135,8 +133,6 @@ SCDynamicStoreCopyMultiple(SCDynamicStoreRef        store,
        expDict = _SCUnserializeMultiple(dict);
        CFRelease(dict);
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value    = %@"), expDict);
-
        return expDict;
 }
 
@@ -155,12 +151,7 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
        int                             newInstance;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key      = %@"), key);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -190,8 +181,10 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configget(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue configget(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -200,10 +193,12 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyValue vm_deallocate(): %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
@@ -214,7 +209,5 @@ SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key)
                return NULL;
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value    = %@"), data);
-
        return data;
 }
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@
  * 
@@ -49,18 +49,17 @@ CFStringRef
 SCDynamicStoreCopyComputerName(SCDynamicStoreRef       store,
                               CFStringEncoding         *nameEncoding)
 {
-       CFDictionaryRef         dict            = NULL;
+       CFDictionaryRef         dict;
        CFStringRef             key;
        CFStringRef             name            = NULL;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyComputerName"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return NULL;
                }
                tempSession = TRUE;
@@ -69,7 +68,7 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef      store,
        key  = SCDynamicStoreKeyCreateComputerName(NULL);
        dict = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
-       if (!dict) {
+       if (dict == NULL) {
                goto done;
        }
        if (!isA_CFDictionary(dict)) {
@@ -78,13 +77,13 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef    store,
        }
 
        name = isA_CFString(CFDictionaryGetValue(dict, kSCPropSystemComputerName));
-       if (!name) {
+       if (name == NULL) {
                _SCErrorSet(kSCStatusNoKey);
                goto done;
        }
        CFRetain(name);
 
-       if (nameEncoding) {
+       if (nameEncoding != NULL) {
                CFNumberRef     num;
 
                num = CFDictionaryGetValue(dict,
@@ -99,21 +98,21 @@ SCDynamicStoreCopyComputerName(SCDynamicStoreRef    store,
     done :
 
        if (tempSession)        CFRelease(store);
-       if (dict)               CFRelease(dict);
+       if (dict != NULL)       CFRelease(dict);
        return name;
 }
 
 
 Boolean
-SCPreferencesSetComputerName(SCPreferencesRef  session,
+SCPreferencesSetComputerName(SCPreferencesRef  prefs,
                             CFStringRef        name,
                             CFStringEncoding   encoding)
 {
        CFDictionaryRef         dict;
-       CFMutableDictionaryRef  newDict = NULL;
+       CFMutableDictionaryRef  newDict;
        CFNumberRef             num;
-       Boolean                 ok      = FALSE;
-       CFStringRef             path    = NULL;
+       Boolean                 ok;
+       CFStringRef             path;
 
        if (!isA_CFString(name)) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -126,8 +125,8 @@ SCPreferencesSetComputerName(SCPreferencesRef       session,
                                        kSCPrefSystem,
                                        kSCCompSystem);
 
-       dict = SCPreferencesPathGetValue(session, path);
-       if (dict) {
+       dict = SCPreferencesPathGetValue(prefs, path);
+       if (dict != NULL) {
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        } else {
                newDict = CFDictionaryCreateMutable(NULL,
@@ -142,13 +141,103 @@ SCPreferencesSetComputerName(SCPreferencesRef    session,
        CFDictionarySetValue(newDict, kSCPropSystemComputerNameEncoding, num);
        CFRelease(num);
 
-       ok = SCPreferencesPathSetValue(session, path, newDict);
-       if (!ok) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed"));
+       ok = SCPreferencesPathSetValue(prefs, path, newDict);
+
+       CFRelease(path);
+       CFRelease(newDict);
+
+       return ok;
+}
+
+
+#ifndef        kSCPropNetHostName
+#define        kSCPropNetHostName      CFSTR("HostName")
+#endif
+
+
+CFStringRef
+SCPreferencesGetHostName(SCPreferencesRef      prefs)
+{
+       CFDictionaryRef dict;
+       CFStringRef     name;
+       CFStringRef     path;
+
+       path = CFStringCreateWithFormat(NULL,
+                                       NULL,
+                                       CFSTR("/%@/%@"),
+                                       kSCPrefSystem,
+                                       kSCCompSystem);
+       dict = SCPreferencesPathGetValue(prefs, path);
+       CFRelease(path);
+
+       if (!isA_CFDictionary(dict)) {
+               _SCErrorSet(kSCStatusNoKey);
+               return NULL;
        }
 
-       if (path)       CFRelease(path);
-       if (newDict)    CFRelease(newDict);
+       name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetHostName));
+       if (name == NULL) {
+               _SCErrorSet(kSCStatusNoKey);
+               return NULL;
+       }
+
+       return name;
+}
+
+
+Boolean
+SCPreferencesSetHostName(SCPreferencesRef      prefs,
+                        CFStringRef            name)
+{
+       CFDictionaryRef         dict;
+       CFMutableDictionaryRef  newDict;
+       Boolean                 ok;
+       CFStringRef             path;
+
+       if (name != NULL) {
+               CFIndex len;
+
+               if (!isA_CFString(name)) {
+                       _SCErrorSet(kSCStatusInvalidArgument);
+                       return FALSE;
+               }
+
+               len = CFStringGetLength(name);
+               if (len == 0) {
+                       name = NULL;
+               }
+       }
+
+       path = CFStringCreateWithFormat(NULL,
+                                       NULL,
+                                       CFSTR("/%@/%@"),
+                                       kSCPrefSystem,
+                                       kSCCompSystem);
+
+       dict = SCPreferencesPathGetValue(prefs, path);
+       if (dict != NULL) {
+               newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
+       } else {
+               newDict = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+       }
+
+       if (name != NULL) {
+               CFDictionarySetValue(newDict, kSCPropNetHostName, name);
+       } else {
+               CFDictionaryRemoveValue(newDict, kSCPropNetHostName);
+       }
+
+       if (CFDictionaryGetCount(newDict) > 0) {
+               ok = SCPreferencesPathSetValue(prefs, path, newDict);
+       } else {
+               ok = SCPreferencesPathRemoveValue(prefs, path);
+       }
+
+       CFRelease(path);
+       CFRelease(newDict);
 
        return ok;
 }
@@ -168,18 +257,17 @@ SCDynamicStoreKeyCreateHostNames(CFAllocatorRef allocator)
 CFStringRef
 SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
 {
-       CFDictionaryRef         dict            = NULL;
+       CFDictionaryRef         dict;
        CFStringRef             key;
        CFStringRef             name            = NULL;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyLocalHostName"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return NULL;
                }
                tempSession = TRUE;
@@ -188,7 +276,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
        key  = SCDynamicStoreKeyCreateHostNames(NULL);
        dict = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
-       if (!dict) {
+       if (dict == NULL) {
                goto done;
        }
        if (!isA_CFDictionary(dict)) {
@@ -197,7 +285,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
        }
 
        name = isA_CFString(CFDictionaryGetValue(dict, kSCPropNetLocalHostName));
-       if (!name) {
+       if (name == NULL) {
                _SCErrorSet(kSCStatusNoKey);
                goto done;
        }
@@ -206,7 +294,7 @@ SCDynamicStoreCopyLocalHostName(SCDynamicStoreRef store)
     done :
 
        if (tempSession)        CFRelease(store);
-       if (dict)               CFRelease(dict);
+       if (dict != NULL)       CFRelease(dict);
        return name;
 }
 
@@ -275,21 +363,21 @@ _SC_CFStringIsValidDNSName(CFStringRef name)
 
        clean = _SC_stringIsValidDNSName(str);
 
-       if (str)        CFAllocatorDeallocate(NULL, str);
+       if (str != NULL)        CFAllocatorDeallocate(NULL, str);
        return clean;
 }
 
 
 Boolean
-SCPreferencesSetLocalHostName(SCPreferencesRef session,
+SCPreferencesSetLocalHostName(SCPreferencesRef prefs,
                              CFStringRef       name)
 {
        CFDictionaryRef         dict;
-       CFMutableDictionaryRef  newDict = NULL;
-       Boolean                 ok      = FALSE;
-       CFStringRef             path    = NULL;
+       CFMutableDictionaryRef  newDict;
+       Boolean                 ok;
+       CFStringRef             path;
 
-       if (name) {
+       if (name != NULL) {
                CFIndex len;
 
                if (!isA_CFString(name)) {
@@ -320,8 +408,8 @@ SCPreferencesSetLocalHostName(SCPreferencesRef      session,
                                        kSCCompNetwork,
                                        kSCCompHostNames);
 
-       dict = SCPreferencesPathGetValue(session, path);
-       if (dict) {
+       dict = SCPreferencesPathGetValue(prefs, path);
+       if (dict != NULL) {
                newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
        } else {
                newDict = CFDictionaryCreateMutable(NULL,
@@ -330,26 +418,20 @@ SCPreferencesSetLocalHostName(SCPreferencesRef    session,
                                                    &kCFTypeDictionaryValueCallBacks);
        }
 
-       if (name) {
+       if (name != NULL) {
                CFDictionarySetValue(newDict, kSCPropNetLocalHostName, name);
        } else {
                CFDictionaryRemoveValue(newDict, kSCPropNetLocalHostName);
        }
 
        if (CFDictionaryGetCount(newDict) > 0) {
-               ok = SCPreferencesPathSetValue(session, path, newDict);
-               if (!ok) {
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathSetValue() failed"));
-               }
+               ok = SCPreferencesPathSetValue(prefs, path, newDict);
        } else {
-               ok = SCPreferencesPathRemoveValue(session, path);
-               if (!ok) {
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesPathRemoveValue() failed"));
-               }
+               ok = SCPreferencesPathRemoveValue(prefs, path);
        }
 
-       if (path)       CFRelease(path);
-       if (newDict)    CFRelease(newDict);
+       CFRelease(path);
+       CFRelease(newDict);
 
        return ok;
 }
index 4ab3068433cfe2774efb6b451fe386d1b4e57ff6..406f85989b4b28a21d07f05356c0bc63a208460d 100644 (file)
@@ -52,12 +52,7 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern)
        int                             sc_status;
        CFArrayRef                      allKeys;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  pattern = %@"), pattern);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -87,8 +82,10 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern)
        CFRelease(utfPattern);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configlist(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList configlist(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -97,10 +94,12 @@ SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef pattern)
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyKeyList vm_deallocate(): %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
index c478dc83f1a3d015613e5144f3be1df8eccf590c..8279699bf3c3b2b5340b60c0caf1e006e858b35d 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreLock(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreLock:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -64,8 +62,10 @@ SCDynamicStoreLock(SCDynamicStoreRef store)
        status = configlock(storePrivate->server, (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configlock(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreLock configlock(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 85c2969d4ba682313aaf77333329dcbab2058d8f..04a17df578a25b1ed7467beea17bc1e7c786840d 100644 (file)
@@ -49,13 +49,7 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -84,8 +78,10 @@ SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean is
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyadd(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreAddWatchedKey notifyadd(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 41613e03d6975e113a95ba6ad8ecb8d681d4e76e..b3f139bcb5b73fd467559da68d29dbf3ba4a9d41 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCancel:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -68,17 +66,12 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
                        CFRunLoopSourceInvalidate(storePrivate->rls);
                        return TRUE;
                case Using_NotifierInformViaCallback :
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  cancel callback runloop source"));
-
-                       /* remove the run loop source */
-                       CFRunLoopRemoveSource(storePrivate->callbackRunLoop,
-                                             storePrivate->callbackRunLoopSource,
-                                             kCFRunLoopDefaultMode);
-                       CFRelease(storePrivate->callbackRunLoopSource);
-                       storePrivate->callbackRunLoop           = NULL;
-                       storePrivate->callbackRunLoopSource     = NULL;
+                       /* invalidate and release the run loop source */
+                       CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+                       CFRelease(storePrivate->callbackRLS);
+                       storePrivate->callbackRLS = NULL;
 
-                       /* invalidate port */
+                       /* invalidate and release the callback mach port */
                        CFMachPortInvalidate(storePrivate->callbackPort);
                        CFRelease(storePrivate->callbackPort);
                        storePrivate->callbackPort              = NULL;
@@ -96,8 +89,10 @@ SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
        storePrivate->notifyStatus = NotifierNotRegistered;
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCancel notifycancel(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 871131275593705c3c130ee1f7730d27b9d7c89e..6684826ce245bc708974085d15f718bd789521ff 100644 (file)
@@ -49,9 +49,7 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store)
        int                             sc_status;
        CFArrayRef                      allKeys;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -69,8 +67,10 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store)
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifychanges(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys notifychanges(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -79,10 +79,12 @@ SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store)
 
        if (sc_status != kSCStatusOK) {
                status = vm_deallocate(mach_task_self(), (vm_address_t)xmlDataRef, xmlDataLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCopyNotifiedKeys vm_deallocate(): %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                _SCErrorSet(sc_status);
                return NULL;
        }
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 */
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  notifier port closed, disabling notifier"));
+#endif /* DEBUG */
        } else if (cbFunc == NULL) {
                /* there is no (longer) a callback function, disable additional callbacks */
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  no callback function, disabling notifier"));
+#endif /* DEBUG */
        } else {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  executing notifiction function"));
+#ifdef DEBUG
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  executing notification function"));
+#endif /* DEBUG */
                if ((*cbFunc)(store, cbArg)) {
                        /*
                         * callback function returned success.
                         */
                        return;
                } else {
+#ifdef DEBUG
                        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  callback returned error, disabling notifier"));
+#endif /* DEBUG */
                }
        }
 
@@ -73,13 +81,10 @@ informCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
        }
 #endif /* DEBUG */
 
-       /* remove the run loop source */
-       CFRunLoopRemoveSource(storePrivate->callbackRunLoop,
-                             storePrivate->callbackRunLoopSource,
-                             kCFRunLoopDefaultMode);
-       CFRelease(storePrivate->callbackRunLoopSource);
-       storePrivate->callbackRunLoop           = NULL;
-       storePrivate->callbackRunLoopSource     = NULL;
+       /* invalidate the run loop source */
+       CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+       CFRelease(storePrivate->callbackRLS);
+       storePrivate->callbackRLS = NULL;
 
        /* invalidate port */
        CFMachPortInvalidate(storePrivate->callbackPort);
@@ -113,9 +118,7 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef              store,
                                                  , NULL
                                                  };
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -149,16 +152,18 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef            store,
                                                MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                                &oldNotify);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback mach_port_request_notification(): %s"), mach_error_string(status));
                CFMachPortInvalidate(storePrivate->callbackPort);
                CFRelease(storePrivate->callbackPort);
                _SCErrorSet(status);
                return FALSE;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback(): why is oldNotify != MACH_PORT_NULL?"));
+               SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyCallback(): why is oldNotify != MACH_PORT_NULL?"));
        }
+#endif /* DEBUG */
 
        /* Requesting notification via mach port */
        status = notifyviaport(storePrivate->server,
@@ -167,8 +172,10 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef             store,
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyCallback notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                CFMachPortInvalidate(storePrivate->callbackPort);
                CFRelease(storePrivate->callbackPort);
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
@@ -186,15 +193,10 @@ SCDynamicStoreNotifyCallback(SCDynamicStoreRef            store,
        storePrivate->notifyStatus              = Using_NotifierInformViaCallback;
 
        /* Creating/adding a run loop source for the port */
-       storePrivate->callbackArgument          = arg;
-       storePrivate->callbackFunction          = func;
-       storePrivate->callbackRunLoop           = runLoop;
-       storePrivate->callbackRunLoopSource =
-               CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
-
-       CFRunLoopAddSource(storePrivate->callbackRunLoop,
-                          storePrivate->callbackRunLoopSource,
-                          kCFRunLoopDefaultMode);
+       storePrivate->callbackArgument  = arg;
+       storePrivate->callbackFunction  = func;
+       storePrivate->callbackRLS       = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
+       CFRunLoopAddSource(runLoop, storePrivate->callbackRLS, kCFRunLoopDefaultMode);
 
        return TRUE;
 }
@@ -210,7 +212,9 @@ rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
 
        if (msgid == MACH_NOTIFY_NO_SENDERS) {
                /* the server died, disable additional callbacks */
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_INFO, CFSTR("  rlsCallback(), notifier port closed"));
+#endif /* DEBUG */
 
 #ifdef DEBUG
                if (port != storePrivate->callbackPort) {
@@ -218,10 +222,10 @@ rlsCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
                }
 #endif /* DEBUG */
 
-               /* remove the run loop source(s) */
-               CFRunLoopSourceInvalidate(storePrivate->callbackRunLoopSource);
-               CFRelease(storePrivate->callbackRunLoopSource);
-               storePrivate->callbackRunLoopSource = NULL;
+               /* invalidate the run loop source(s) */
+               CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+               CFRelease(storePrivate->callbackRLS);
+               storePrivate->callbackRLS = NULL;
 
                /* invalidate port */
                CFMachPortInvalidate(storePrivate->callbackPort);
@@ -242,7 +246,9 @@ rlsPortInvalidate(CFMachPortRef mp, void *info) {
        mach_port_t     port    = CFMachPortGetPort(mp);
 
        // A simple deallocate won't get rid of all the references we've accumulated
+#ifdef DEBUG
        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  invalidate = %d"), port);
+#endif /* DEBUG */
        (void)mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
 }
 
@@ -253,7 +259,9 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)info;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
+#ifdef DEBUG
        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("schedule notifications for mode %@"), mode);
+#endif /* DEBUG */
 
        if (storePrivate->rlsRefs++ == 0) {
                CFMachPortContext       context = { 0
@@ -267,22 +275,23 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
                int                     sc_status;
                kern_return_t           status;
 
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  activate callback runloop source"));
+#endif /* DEBUG */
 
                /* Allocating port (for server response) */
                status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
                        return;
                }
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  port = %d"), port);
 
                status = mach_port_insert_right(mach_task_self(),
                                                port,
                                                port,
                                                MACH_MSG_TYPE_MAKE_SEND);
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
                        (void) mach_port_destroy(mach_task_self(), port);
                        return;
                }
@@ -296,19 +305,23 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
                                                        MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                                        &oldNotify);
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
                        (void) mach_port_destroy(mach_task_self(), port);
                        return;
                }
 
+#ifdef DEBUG
                if (oldNotify != MACH_PORT_NULL) {
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("rlsSchedule(): why is oldNotify != MACH_PORT_NULL?"));
+                       SCLog(TRUE, LOG_ERR, CFSTR("rlsSchedule(): why is oldNotify != MACH_PORT_NULL?"));
                }
+#endif /* DEBUG */
 
                status = notifyviaport(storePrivate->server, port, 0, (int *)&sc_status);
                if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                        if (status != MACH_SEND_INVALID_DEST)
                                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                        (void) mach_port_destroy(mach_task_self(), port);
                        port = MACH_PORT_NULL;
                        (void) mach_port_destroy(mach_task_self(), storePrivate->server);
@@ -318,11 +331,11 @@ rlsSchedule(void *info, CFRunLoopRef rl, CFStringRef mode)
 
                storePrivate->callbackPort = CFMachPortCreateWithPort(NULL, port, rlsCallback, &context, NULL);
                CFMachPortSetInvalidationCallBack(storePrivate->callbackPort, rlsPortInvalidate);
-               storePrivate->callbackRunLoopSource = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
+               storePrivate->callbackRLS = CFMachPortCreateRunLoopSource(NULL, storePrivate->callbackPort, 0);
        }
 
-       if (storePrivate->callbackRunLoopSource) {
-               CFRunLoopAddSource(rl, storePrivate->callbackRunLoopSource, mode);
+       if (storePrivate->callbackRLS != NULL) {
+               CFRunLoopAddSource(rl, storePrivate->callbackRLS, mode);
        }
 
        return;
@@ -335,36 +348,43 @@ rlsCancel(void *info, CFRunLoopRef rl, CFStringRef mode)
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)info;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
+#ifdef DEBUG
        SCLog(_sc_verbose, LOG_DEBUG, CFSTR("cancel notifications for mode %@"), mode);
+#endif /* DEBUG */
 
-       if (storePrivate->callbackRunLoopSource) {
-               CFRunLoopRemoveSource(rl, storePrivate->callbackRunLoopSource, mode);
+       if (storePrivate->callbackRLS != NULL) {
+               CFRunLoopRemoveSource(rl, storePrivate->callbackRLS, mode);
        }
 
        if (--storePrivate->rlsRefs == 0) {
                int             sc_status;
                kern_return_t   status;
 
+#ifdef DEBUG
                SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  cancel callback runloop source"));
+#endif /* DEBUG */
 
-               if (storePrivate->callbackRunLoopSource) {
-                       /* remove the run loop source */
-                       CFRelease(storePrivate->callbackRunLoopSource);
-                       storePrivate->callbackRunLoopSource = NULL;
+               if (storePrivate->callbackRLS != NULL) {
+                       /* invalidate & remove the run loop source */
+                       CFRunLoopSourceInvalidate(storePrivate->callbackRLS);
+                       CFRelease(storePrivate->callbackRLS);
+                       storePrivate->callbackRLS = NULL;
                }
 
-               if (storePrivate->callbackPort) {
+               if (storePrivate->callbackPort != NULL) {
                        /* invalidate port */
                        CFMachPortInvalidate(storePrivate->callbackPort);
                        CFRelease(storePrivate->callbackPort);
                        storePrivate->callbackPort = NULL;
                }
 
-               if (storePrivate->server) {
+               if (storePrivate->server != MACH_PORT_NULL) {
                        status = notifycancel(storePrivate->server, (int *)&sc_status);
                        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                                if (status != MACH_SEND_INVALID_DEST)
-                               SCLog(_sc_verbose, LOG_INFO, CFSTR("notifycancel(): %s"), mach_error_string(status));
+                                       SCLog(_sc_verbose, LOG_INFO, CFSTR("notifycancel(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                                storePrivate->server = MACH_PORT_NULL;
                                return;
@@ -385,14 +405,20 @@ rlsPerform(void *info)
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)info;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  executing notifiction function"));
+#ifdef DEBUG
+       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  executing notification function"));
+#endif /* DEBUG */
 
        changedKeys = SCDynamicStoreCopyNotifiedKeys(store);
-       if (!changedKeys) {
-               /* something happened to the server */
+       if (changedKeys == NULL) {
+               /* if no changes or something happened to the server */
                return;
        }
 
+       if (CFArrayGetCount(changedKeys) == 0) {
+               goto done;
+       }
+
        rlsFunction = storePrivate->rlsFunction;
 
        if (NULL != storePrivate->rlsContext.retain) {
@@ -407,6 +433,8 @@ rlsPerform(void *info)
                context_release(context_info);
        }
 
+    done :
+
        CFRelease(changedKeys);
        return;
 }
@@ -453,9 +481,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef    allocator,
 {
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreateRunLoopSource:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return NULL;
@@ -478,7 +504,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef    allocator,
                        return NULL;
        }
 
-       if (storePrivate->rls) {
+       if (storePrivate->rls != NULL) {
                CFRetain(storePrivate->rls);
        } else {
                CFRunLoopSourceContext  context = { 0                   // version
@@ -496,7 +522,7 @@ SCDynamicStoreCreateRunLoopSource(CFAllocatorRef    allocator,
                storePrivate->rls = CFRunLoopSourceCreate(allocator, order, &context);
        }
 
-       if (!storePrivate->rls) {
+       if (storePrivate->rls == NULL) {
                _SCErrorSet(kSCStatusFailed);
                return NULL;
        }
index 7aec2213dded341904239272bc491135d13fc626..6e3521e290c1b79a343802c493b92a05a38756f7 100644 (file)
@@ -56,9 +56,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef  store,
        struct sockaddr_un              un;
        int                             sock;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyFileDescriptor:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -78,7 +76,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef  store,
 
        if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                _SCErrorSet(errno);
-               SCLog(_sc_verbose, LOG_NOTICE, CFSTR("socket: %s"), strerror(errno));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor socket(): %s"), strerror(errno));
                return FALSE;
        }
 
@@ -94,14 +92,14 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef        store,
 
        if (bind(sock, (struct sockaddr *)&un, sizeof(un)) == -1) {
                _SCErrorSet(errno);
-               SCLog(_sc_verbose, LOG_NOTICE, CFSTR("bind: %s"), strerror(errno));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor bind(): %s"), strerror(errno));
                (void) close(sock);
                return FALSE;
        }
 
        if (listen(sock, 0) == -1) {
                _SCErrorSet(errno);
-               SCLog(_sc_verbose, LOG_NOTICE, CFSTR("listen: %s"), strerror(errno));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor listen(): %s"), strerror(errno));
                (void) close(sock);
                return FALSE;
        }
@@ -113,8 +111,10 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef       store,
                             (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviafd(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyFileDescriptor notifyviafd(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -124,7 +124,7 @@ SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef        store,
        *fd = accept(sock, 0, 0);
        if (*fd == -1) {
                _SCErrorSet(errno);
-               SCLog(_sc_verbose, LOG_NOTICE, CFSTR("accept: %s"), strerror(errno));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("SCDynamicStoreNotifyFileDescriptor accept(): %s"), strerror(errno));
                (void) close(sock);
                return FALSE;
        }
index bef3896cbead994547f82c98b2cfcc02f7345b20..10b4aa0af0c5bc16c1858b6d4524894a908ee2a1 100644 (file)
@@ -47,9 +47,7 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier,
        mach_port_t                     oldNotify;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -70,18 +68,17 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier,
        /* Allocating port (for server response) */
        status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, port);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort mach_port_allocate(): %s"), mach_error_string(status));
                _SCErrorSet(status);
                return FALSE;
        }
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  port = %d"), *port);
 
        status = mach_port_insert_right(mach_task_self(),
                                        *port,
                                        *port,
                                        MACH_MSG_TYPE_MAKE_SEND);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort mach_port_insert_right(): %s"), mach_error_string(status));
                (void) mach_port_destroy(mach_task_self(), *port);
                *port = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -97,16 +94,18 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier,
                                                MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                                &oldNotify);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort mach_port_request_notification(): %s"), mach_error_string(status));
                (void) mach_port_destroy(mach_task_self(), *port);
                *port = MACH_PORT_NULL;
                _SCErrorSet(status);
                return FALSE;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): why is oldNotify != MACH_PORT_NULL?"));
+               SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): why is oldNotify != MACH_PORT_NULL?"));
        }
+#endif /* DEBUG */
 
        status = notifyviaport(storePrivate->server,
                               *port,
@@ -114,8 +113,10 @@ SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier,
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyMachPort notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), *port);
                *port = MACH_PORT_NULL;
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
index 4356c6e87627bd6d42aa2d76e37dd64b8234ae9b..96464a13a69ae2b46b8d830394ad413fd946325e 100644 (file)
@@ -47,11 +47,7 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig)
        int                             sc_status;
        task_t                          task;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal:"));
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  pid = %d"), pid);
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  sig = %d"), sig);
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -71,7 +67,7 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig)
 
        status = task_for_pid(mach_task_self(), pid, &task);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_for_pid(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal task_for_pid(): %s"), mach_error_string(status));
                _SCErrorSet(status);
                return FALSE;
        }
@@ -79,8 +75,10 @@ SCDynamicStoreNotifySignal(SCDynamicStoreRef store, pid_t pid, int sig)
        status = notifyviasignal(storePrivate->server, task, sig, (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviasignal(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifySignal notifyviasignal(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 06f81b9ee059526f14cd6f8e92aae04f96340171..5278a57da987c14a3c33623b62aa724aca57dc38 100644 (file)
@@ -49,13 +49,7 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -84,8 +78,10 @@ SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyremove(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveWatchedKey notifyremove(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index c9eb908ad009b2415486b6036ce691f9e23a754c..ad5626d48031d5557f84dbbccb0960af4c659e35 100644 (file)
@@ -52,13 +52,7 @@ SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef  store,
        CFIndex                         myPatternsLen   = 0;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keys     = %@"), keys);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  patterns = %@"), patterns);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -99,8 +93,10 @@ SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef  store,
        if (xmlPatterns)        CFRelease(xmlPatterns);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyset(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetNotificationKeys notifyset(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
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) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("waitForMachMessage vm_allocate(): %s"), mach_error_string(status));
                return -1;
        }
 
@@ -61,7 +61,7 @@ waitForMachMessage(mach_port_t port)
                          MACH_MSG_TIMEOUT_NONE,        /* timeout */
                          MACH_PORT_NULL);              /* notify */
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_msg(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("waitForMachMessage mach_msg(): %s"), mach_error_string(status));
                return -1;
        }
 
@@ -79,9 +79,7 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store)
        int                             sc_status;
        mach_msg_id_t                   msgid;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -102,18 +100,17 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store)
        /* Allocating port (for server response) */
        status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_allocate(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait mach_port_allocate(): %s"), mach_error_string(status));
                _SCErrorSet(status);
                return FALSE;
        }
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  port = %d"), port);
 
        status = mach_port_insert_right(mach_task_self(),
                                        port,
                                        port,
                                        MACH_MSG_TYPE_MAKE_SEND);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_insert_right(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait mach_port_insert_right(): %s"), mach_error_string(status));
                (void) mach_port_destroy(mach_task_self(), port);
                _SCErrorSet(status);
                return FALSE;
@@ -128,25 +125,28 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store)
                                                MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                                &oldNotify);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait mach_port_request_notification(): %s"), mach_error_string(status));
                (void) mach_port_destroy(mach_task_self(), port);
                _SCErrorSet(status);
                return FALSE;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait(): why is oldNotify != MACH_PORT_NULL?"));
+               SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyWait(): why is oldNotify != MACH_PORT_NULL?"));
        }
+#endif /* DEBUG */
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Requesting notification via mach port %d"), port);
        status = notifyviaport(storePrivate->server,
                               port,
                               0,
                               (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifyviaport(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait notifyviaport(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -161,8 +161,6 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store)
        /* set notifier active */
        storePrivate->notifyStatus = Using_NotifierWait;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Waiting..."));
-
        msgid = waitForMachMessage(port);
 
        /* set notifier inactive */
@@ -170,26 +168,32 @@ SCDynamicStoreNotifyWait(SCDynamicStoreRef store)
 
        if (msgid == MACH_NOTIFY_NO_SENDERS) {
                /* the server closed the notifier port */
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  notifier port closed, destroying port %d"), port);
+#ifdef DEBUG
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait notifier port closed, destroying port %d"), port);
+#endif /* DEBUG */
                _SCErrorSet(kSCStatusNoStoreServer);
                return FALSE;
        }
 
        if (msgid == -1) {
                /* one of the mach routines returned an error */
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  communication with server failed, destroying port %d"), port);
+#ifdef DEBUG
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait communication with server failed, destroying port %d"), port);
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), port);
                _SCErrorSet(kSCStatusNoStoreServer);
                return FALSE;
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("Something changed, cancelling notification request"));
+       // something changed, cancelling notification request
        status = notifycancel(storePrivate->server,
                              (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("notifycancel(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyWait notifycancel(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 409523b13204829074cf9c864f1cd7a87a5ad718..c06615b8e425789f017c1676537dc024800241d9 100644 (file)
@@ -47,12 +47,7 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef  store,
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -80,8 +75,10 @@ SCDynamicStoreNotifyValue(SCDynamicStoreRef  store,
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("confignotify(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreNotifyValue confignotify(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
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@
  * 
@@ -32,6 +32,8 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include <mach/mach.h>
 #include <mach/mach_error.h>
 #include <servers/bootstrap.h>
 #include "SCDynamicStoreInternal.h"
 #include "config.h"            /* MiG generated file */
 
+
+static int             _sc_active      = 0;
+static CFStringRef     _sc_bundleID    = NULL;
+static pthread_mutex_t _sc_lock        = PTHREAD_MUTEX_INITIALIZER;
+static mach_port_t     _sc_server      = MACH_PORT_NULL;
+
+
 static CFStringRef
 __SCDynamicStoreCopyDescription(CFTypeRef cf) {
-       CFAllocatorRef          allocator       = CFGetAllocator(cf);
-       CFMutableStringRef      result;
+       CFAllocatorRef                  allocator       = CFGetAllocator(cf);
+       CFMutableStringRef              result;
+       SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)cf;
 
        result = CFStringCreateMutable(allocator, 0);
-       CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> {\n"), cf, allocator);
-       CFStringAppendFormat(result, NULL, CFSTR("}"));
+       CFStringAppendFormat(result, NULL, CFSTR("<SCDynamicStore %p [%p]> { "), cf, allocator);
+       if (storePrivate->server != MACH_PORT_NULL) {
+               CFStringAppendFormat(result, NULL, CFSTR("server port=%d"), storePrivate->server);
+       } else {
+               CFStringAppendFormat(result, NULL, CFSTR("server not (no longer) available"));
+       }
+       if (storePrivate->locked) {
+               CFStringAppendFormat(result, NULL, CFSTR(", locked"));
+       }
+       switch (storePrivate->notifyStatus) {
+               case Using_NotifierWait :
+                       CFStringAppendFormat(result, NULL, CFSTR(", waiting for a notification"));
+                       break;
+               case Using_NotifierInformViaMachPort :
+                       CFStringAppendFormat(result, NULL, CFSTR(", mach port notifications"));
+                       break;
+               case Using_NotifierInformViaFD :
+                       CFStringAppendFormat(result, NULL, CFSTR(", FD notifications"));
+                       break;
+               case Using_NotifierInformViaSignal :
+                       CFStringAppendFormat(result, NULL, CFSTR(", BSD signal notifications"));
+                       break;
+               case Using_NotifierInformViaRunLoop :
+               case Using_NotifierInformViaCallback :
+                       if (storePrivate->notifyStatus == Using_NotifierInformViaRunLoop) {
+                               CFStringAppendFormat(result, NULL, CFSTR(", runloop notifications"));
+                               CFStringAppendFormat(result, NULL, CFSTR(" (func=0x%8.8x"), storePrivate->rlsFunction);
+                               CFStringAppendFormat(result, NULL, CFSTR(", info=0x%8.8x"), storePrivate->rlsContext.info);
+                               CFStringAppendFormat(result, NULL, CFSTR(", rls=0x%8.8x" ), storePrivate->rls);
+                               CFStringAppendFormat(result, NULL, CFSTR(", refs=%d"     ), storePrivate->rlsRefs);
+                       } else {
+                               CFStringAppendFormat(result, NULL, CFSTR(", mach port/callback notifications"));
+                               CFStringAppendFormat(result, NULL, CFSTR(" (func=0x%8.8x"), storePrivate->callbackFunction);
+                               CFStringAppendFormat(result, NULL, CFSTR(", info=0x%8.8x"), storePrivate->callbackArgument);
+                       }
+                       if (storePrivate->callbackRLS != NULL) {
+                               CFStringAppendFormat(result, NULL, CFSTR(", notify rls=%@" ), storePrivate->callbackRLS);
+                       }
+                       CFStringAppendFormat(result, NULL, CFSTR(")"));
+                       break;
+               default :
+                       CFStringAppendFormat(result, NULL, CFSTR(", notification delivery not requested%s"),
+                                            storePrivate->rlsFunction ? " (yet)" : "");
+                       break;
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(" }"));
 
        return result;
 }
@@ -63,23 +117,23 @@ __SCDynamicStoreDeallocate(CFTypeRef cf)
        SCDynamicStoreRef               store           = (SCDynamicStoreRef)cf;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate:"));
-
        (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldThreadState);
 
        /* Remove/cancel any outstanding notification requests. */
        (void) SCDynamicStoreNotifyCancel(store);
 
-       if (storePrivate->server && storePrivate->locked) {
+       if ((storePrivate->server != MACH_PORT_NULL) && storePrivate->locked) {
                (void) SCDynamicStoreUnlock(store);     /* release the lock */
        }
 
        if (storePrivate->server != MACH_PORT_NULL) {
                status = configclose(storePrivate->server, (int *)&sc_status);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
                        if (status != MACH_SEND_INVALID_DEST)
-                               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configclose(): %s"), mach_error_string(status));
+                               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreDeallocate configclose(): %s"), mach_error_string(status));
                }
+#endif /* DEBUG */
 
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
@@ -89,14 +143,24 @@ __SCDynamicStoreDeallocate(CFTypeRef cf)
        pthread_testcancel();
 
        /* release any callback context info */
-       if (storePrivate->rlsContext.release) {
-               storePrivate->rlsContext.release(storePrivate->rlsContext.info);
+       if (storePrivate->rlsContext.release != NULL) {
+               (*storePrivate->rlsContext.release)(storePrivate->rlsContext.info);
        }
 
        /* release any keys being watched */
        CFRelease(storePrivate->keys);
        CFRelease(storePrivate->patterns);
 
+       /* cleanup */
+       pthread_mutex_lock(&_sc_lock);
+       _sc_active--;                   /* drop the number of active dynamic store sessions */
+       if ((_sc_active == 0) && (_sc_server != MACH_PORT_NULL)) {
+               /* release the [last] reference to the server */
+               (void)mach_port_deallocate(mach_task_self(), _sc_server);
+               _sc_server = MACH_PORT_NULL;
+       }
+       pthread_mutex_unlock(&_sc_lock);
+
        return;
 }
 
@@ -117,11 +181,54 @@ static const CFRuntimeClass __SCDynamicStoreClass = {
 };
 
 
+static void
+childForkHandler()
+{
+       /* the process has forked (and we are the child process) */
+       
+       _sc_active = 0;
+       _sc_server = MACH_PORT_NULL;
+
+       return;
+}
+
+
 static pthread_once_t initialized      = PTHREAD_ONCE_INIT;
 
 static void
 __SCDynamicStoreInitialize(void) {
+       CFBundleRef     bundle;
+
+       /* register with CoreFoundation */
        __kSCDynamicStoreTypeID = _CFRuntimeRegisterClass(&__SCDynamicStoreClass);
+
+       /* add handler to cleanup after fork() */
+       (void) pthread_atfork(NULL, NULL, childForkHandler);
+
+       /* get the application/executable/bundle name */
+       bundle = CFBundleGetMainBundle();
+       if (bundle != NULL) {
+               _sc_bundleID = CFBundleGetIdentifier(bundle);
+               if (_sc_bundleID != NULL) {
+                       CFRetain(_sc_bundleID);
+               } else {
+                       CFURLRef        url;
+
+                       url = CFBundleCopyExecutableURL(bundle);
+                       if (url != NULL) {
+                               _sc_bundleID = CFURLCopyPath(url);
+                               CFRelease(url);
+                       }
+               }
+
+               if (_sc_bundleID != NULL) {
+                       if (CFEqual(_sc_bundleID, CFSTR("/"))) {
+                               CFRelease(_sc_bundleID);
+                               _sc_bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%d)"), getpid());
+                       }
+               }
+       }
+
        return;
 }
 
@@ -132,6 +239,7 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef                allocator,
                             SCDynamicStoreCallBack     callout,
                             SCDynamicStoreContext      *context)
 {
+       int                             sc_status       = kSCStatusOK;
        uint32_t                        size;
        SCDynamicStorePrivateRef        storePrivate;
 
@@ -144,15 +252,17 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef              allocator,
                                                                          __kSCDynamicStoreTypeID,
                                                                          size,
                                                                          NULL);
-       if (!storePrivate) {
+       if (storePrivate == NULL) {
+               _SCErrorSet(kSCStatusFailed);
                return NULL;
        }
 
        /* server side of the "configd" session */
-       storePrivate->server = MACH_PORT_NULL;
+       storePrivate->server                            = MACH_PORT_NULL;
 
        /* flags */
-       storePrivate->locked = FALSE;
+       storePrivate->locked                            = FALSE;
+       storePrivate->useSessionKeys                    = FALSE;
 
        /* Notification status */
        storePrivate->notifyStatus                      = NotifierNotRegistered;
@@ -167,8 +277,8 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef                allocator,
        storePrivate->rlsContext.copyDescription        = NULL;
        if (context) {
                bcopy(context, &storePrivate->rlsContext, sizeof(SCDynamicStoreContext));
-               if (context->retain) {
-                       storePrivate->rlsContext.info = (void *)context->retain(context->info);
+               if (context->retain != NULL) {
+                       storePrivate->rlsContext.info = (void *)(*context->retain)(context->info);
                }
        }
 
@@ -176,8 +286,7 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef                allocator,
        storePrivate->callbackFunction                  = NULL;
        storePrivate->callbackArgument                  = NULL;
        storePrivate->callbackPort                      = NULL;
-       storePrivate->callbackRunLoop                   = NULL;
-       storePrivate->callbackRunLoopSource             = NULL;
+       storePrivate->callbackRLS                       = NULL;
 
        /* "server" information associated with SCDynamicStoreSetNotificationKeys() */
        storePrivate->keys                              = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
@@ -195,135 +304,150 @@ __SCDynamicStoreCreatePrivate(CFAllocatorRef            allocator,
        storePrivate->notifySignal                      = 0;
        storePrivate->notifySignalTask                  = TASK_NULL;
 
+       /* initialize global state */
+
+       pthread_mutex_lock(&_sc_lock);
+
+       /* get the server port */
+       if (_sc_server == MACH_PORT_NULL) {
+               char            *server_name;
+               kern_return_t   status;
+
+               server_name = getenv("SCD_SERVER");
+               if (!server_name) {
+                       server_name = SCD_SERVER;
+               }
+
+               status = bootstrap_look_up(bootstrap_port, server_name, &_sc_server);
+               switch (status) {
+                       case BOOTSTRAP_SUCCESS :
+                               /* service currently registered, "a good thing" (tm) */
+                               break;
+                       case BOOTSTRAP_UNKNOWN_SERVICE :
+                               /* service not currently registered, try again later */
+                               sc_status = status;
+                               goto done;
+                       default :
+#ifdef DEBUG
+                               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate[WithOptions] bootstrap_look_up() failed: status=%d"), status);
+#endif /* DEBUG */
+                               sc_status = status;
+                               goto done;
+               }
+       }
+
+       /* bump the number of active dynamic store sessions */
+       _sc_active++;
+
+    done :
+
+       pthread_mutex_unlock(&_sc_lock);
+
+       if (sc_status != kSCStatusOK) {
+               _SCErrorSet(sc_status);
+               CFRelease(storePrivate);
+               storePrivate = NULL;
+       }
+
        return storePrivate;
 }
 
 
+const CFStringRef      kSCDynamicStoreUseSessionKeys   = CFSTR("UseSessionKeys");      /* CFBoolean */
+
+
 SCDynamicStoreRef
-SCDynamicStoreCreate(CFAllocatorRef            allocator,
-                    CFStringRef                name,
-                    SCDynamicStoreCallBack     callout,
-                    SCDynamicStoreContext      *context)
+SCDynamicStoreCreateWithOptions(CFAllocatorRef         allocator,
+                               CFStringRef             name,
+                               CFDictionaryRef         storeOptions,
+                               SCDynamicStoreCallBack  callout,
+                               SCDynamicStoreContext   *context)
 {
        SCDynamicStorePrivateRef        storePrivate;
        kern_return_t                   status;
-       mach_port_t                     bootstrap_port;
-       CFBundleRef                     bundle;
-       CFStringRef                     bundleID        = NULL;
-       mach_port_t                     server;
-       char                            *server_name;
        CFDataRef                       utfName;                /* serialized name */
        xmlData_t                       myNameRef;
        CFIndex                         myNameLen;
-       int                             sc_status;
-
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreCreate:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  name = %@"), name);
-       }
+       CFDataRef                       xmlOptions      = NULL; /* serialized options */
+       xmlData_t                       myOptionsRef    = NULL;
+       CFIndex                         myOptionsLen    = 0;
+       int                             sc_status       = kSCStatusFailed;
 
        /*
         * allocate and initialize a new session
         */
        storePrivate = __SCDynamicStoreCreatePrivate(allocator, name, callout, context);
-
-       status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
-       if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
-               CFRelease(storePrivate);
-               _SCErrorSet(status);
+       if (storePrivate == NULL) {
                return NULL;
        }
 
-       server_name = getenv("SCD_SERVER");
-       if (!server_name) {
-               server_name = SCD_SERVER;
-       }
-
-       status = bootstrap_look_up(bootstrap_port, server_name, &server);
-       switch (status) {
-               case BOOTSTRAP_SUCCESS :
-                       /* service currently registered, "a good thing" (tm) */
-                       break;
-               case BOOTSTRAP_UNKNOWN_SERVICE :
-                       /* service not currently registered, try again later */
-                       CFRelease(storePrivate);
-                       _SCErrorSet(status);
-                       return NULL;
-                       break;
-               default :
-#ifdef DEBUG
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("bootstrap_look_up() failed: status=%d"), status);
-#endif /* DEBUG */
-                       CFRelease(storePrivate);
-                       _SCErrorSet(status);
-                       return NULL;
-       }
-
-       /* serialize the name */
-       bundle = CFBundleGetMainBundle();
-       if (bundle) {
-               bundleID = CFBundleGetIdentifier(bundle);
-               if (bundleID) {
-                       CFRetain(bundleID);
-               } else {
-                       CFURLRef        url;
-
-                       url = CFBundleCopyExecutableURL(bundle);
-                       if (url) {
-                               bundleID = CFURLCopyPath(url);
-                               CFRelease(url);
-                       }
-               }
-       }
-
-       if (bundleID) {
+       if (_sc_bundleID != NULL) {
                CFStringRef     fullName;
 
-               if (CFEqual(bundleID, CFSTR("/"))) {
-                       CFRelease(bundleID);
-                       bundleID = CFStringCreateWithFormat(NULL, NULL, CFSTR("(%d)"), getpid());
-               }
-
-               fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), bundleID, name);
+               fullName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@:%@"), _sc_bundleID, name);
                name = fullName;
-               CFRelease(bundleID);
        } else {
                CFRetain(name);
        }
 
        if (!_SCSerializeString(name, &utfName, (void **)&myNameRef, &myNameLen)) {
                CFRelease(name);
-               _SCErrorSet(kSCStatusFailed);
-               return NULL;
+               goto done;
        }
        CFRelease(name);
 
+       /* serialize the options */
+       if (storeOptions) {
+               if (!_SCSerialize(storeOptions, &xmlOptions, (void **)&myOptionsRef, &myOptionsLen)) {
+                       CFRelease(utfName);
+                       goto done;
+               }
+       }
+
        /* open a new session with the server */
-       status = configopen(server, myNameRef, myNameLen, &storePrivate->server, (int *)&sc_status);
+       status = configopen(_sc_server,
+                           myNameRef,
+                           myNameLen,
+                           myOptionsRef,
+                           myOptionsLen,
+                           &storePrivate->server,
+                           (int *)&sc_status);
 
        /* clean up */
        CFRelease(utfName);
+       if (xmlOptions) CFRelease(xmlOptions);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configopen(): %s"), mach_error_string(status));
-               CFRelease(storePrivate);
-               _SCErrorSet(status);
-               return NULL;
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreCreate[WithOptions] configopen(): %s"), mach_error_string(status));
+#endif /* DEBUG */
+               sc_status = status;
+               goto done;
        }
 
+    done :
+
        if (sc_status != kSCStatusOK) {
-               CFRelease(storePrivate);
                _SCErrorSet(sc_status);
-               return NULL;
+               CFRelease(storePrivate);
+               storePrivate = NULL;
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  server port = %d"), storePrivate->server);
        return (SCDynamicStoreRef)storePrivate;
 }
 
 
+SCDynamicStoreRef
+SCDynamicStoreCreate(CFAllocatorRef            allocator,
+                    CFStringRef                name,
+                    SCDynamicStoreCallBack     callout,
+                    SCDynamicStoreContext      *context)
+{
+       return SCDynamicStoreCreateWithOptions(allocator, name, NULL, callout, context);
+}
+
+
 CFTypeID
 SCDynamicStoreGetTypeID(void) {
        pthread_once(&initialized, __SCDynamicStoreInitialize); /* initialize runtime */
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@
  * 
@@ -135,6 +135,9 @@ reaper(int sigraised)
                          MACH_PORT_NULL,               /* rcv_name */
                          0,                            /* timeout */
                          MACH_PORT_NULL);              /* notify */
+       if (status == MACH_SEND_TIMED_OUT) {
+               mach_msg_destroy(&msg.header);
+       }
 
        return;
 }
@@ -298,19 +301,9 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack       callout,
 
                case 0 : {      /* if child */
 
-                       uid_t   curUID  = geteuid();
-                       gid_t   curGID  = getegid();
                        int     i;
                        int     status;
 
-                       if (curUID != uid) {
-                               (void) setuid(uid);
-                       }
-
-                       if (curGID != gid) {
-                               (void) setgid(gid);
-                       }
-
                        if (setup) {
                                (setup)(pid, setupContext);
                        } else {
@@ -321,6 +314,14 @@ _SCDPluginExecCommand2(SCDPluginExecCallBack       callout,
                                dup(0);
                        }
 
+                       if (gid != getegid()) {
+                               (void) setgid(gid);
+                       }
+
+                       if (uid != geteuid()) {
+                               (void) setuid(uid);
+                       }
+
                        /* ensure that our PATH environment variable is somewhat reasonable */
                        if (setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin", 0) == -1) {
                                printf("setenv() failed: %s\n", strerror(errno));
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.
-       @param verbose A boolean value indicating whether verbose logging has
+       @param bundleVerbose A boolean value indicating whether verbose logging has
                been enabled for this bundle.
  */
 typedef void   (*SCDynamicStoreBundleLoadFunction)     (CFBundleRef    bundle,
@@ -86,6 +92,19 @@ typedef void (*SCDynamicStoreBundleStartFunction)    (const char     *bundleName,
 typedef void   (*SCDynamicStoreBundlePrimeFunction)    ();
 
 
+/*!
+       @typedef SCDynamicStoreBundleStopFunction
+       @discussion Type of the stop() termination function that will be
+               called when configd has been requested to shut down.
+       @param stopRls A run loop source which should be signaled using
+               CFRunLoopSourceSignal() when the plugin has been shut down.
+
+       Note: a plugin can delay shut down of the daemon by no more than
+               30 seconds.
+ */
+typedef void   (*SCDynamicStoreBundleStopFunction)     (CFRunLoopSourceRef     stopRls);
+
+
 /*!
        @typedef SCDPluginExecCallBack
        @discussion Type of the callback function used when a child process
@@ -97,10 +116,10 @@ typedef void       (*SCDynamicStoreBundlePrimeFunction)    ();
        @param context The callback argument specified on the call
                to _SCDPluginExecCommand().
  */
-typedef void (*SCDPluginExecCallBack)  (pid_t          pid,
-                                        int            status,
-                                        struct rusage  *rusage,
-                                        void           *context);
+typedef void   (*SCDPluginExecCallBack)                (pid_t          pid,
+                                                        int            status,
+                                                        struct rusage  *rusage,
+                                                        void           *context);
 
 
 /*!
@@ -111,8 +130,8 @@ typedef void (*SCDPluginExecCallBack)       (pid_t          pid,
        @param setupContext The setup argument specified on the call
                to _SCDPluginExecCommand2().
  */
-typedef        void (*SCDPluginExecSetup)      (pid_t          pid,
-                                        void           *setupContext);
+typedef        void    (*SCDPluginExecSetup)                   (pid_t          pid,
+                                                        void           *setupContext);
 
 
 __BEGIN_DECLS
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@
  * 
 #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>
@@ -59,7 +66,13 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi
                               0,
                               &len);
 
-       if (!buf) {
+       if (buf) {
+               /* check the size of the provided buffer */
+               if (bufLen < (len + 1)) {
+                       return NULL;    /* if too small */
+               }
+       } else {
+               /* allocate a buffer */
                bufLen = len + 1;
                buf = CFAllocatorAllocate(NULL, bufLen, 0);
                if (!buf) {
@@ -67,10 +80,6 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi
                }
        }
 
-       if (len >= bufLen) {
-               len = bufLen - 1;
-       }
-
        (void)CFStringGetBytes(cfstr,
                               CFRangeMake(0, len),
                               encoding,
@@ -85,19 +94,70 @@ _SC_cfstring_to_cstring(CFStringRef cfstr, char *buf, int bufLen, CFStringEncodi
 }
 
 
+void
+_SC_sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
+{
+       bzero(buf, bufLen);
+       switch (address->sa_family) {
+               case AF_INET :
+                       (void)inet_ntop(((struct sockaddr_in *)address)->sin_family,
+                                       &((struct sockaddr_in *)address)->sin_addr,
+                                       buf,
+                                       bufLen);
+                       break;
+               case AF_INET6 : {
+                       (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family,
+                                       &((struct sockaddr_in6 *)address)->sin6_addr,
+                                       buf,
+                                       bufLen);
+                       if (((struct sockaddr_in6 *)address)->sin6_scope_id != 0) {
+                               int     n;
+
+                               n = strlen(buf);
+                               if ((n+IF_NAMESIZE+1) <= (int)bufLen) {
+                                       buf[n++] = '%';
+                                       if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]);
+                               }
+                       }
+                       break;
+               }
+               case AF_LINK :
+                       if (((struct sockaddr_dl *)address)->sdl_len < bufLen) {
+                               bufLen = ((struct sockaddr_dl *)address)->sdl_len;
+                       } else {
+                               bufLen = bufLen - 1;
+                       }
+
+                       bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen);
+                       break;
+               default :
+                       snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
+                       break;
+       }
+
+       return;
+}
+
+
 Boolean
 _SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dataLen)
 {
        CFDataRef       myXml;
+       CFWriteStreamRef        stream;
 
        if (!xml && !(dataRef && dataLen)) {
                /* if not keeping track of allocated space */
                return FALSE;
        }
 
-       myXml = CFPropertyListCreateXMLData(NULL, obj);
+       stream = CFWriteStreamCreateWithAllocatedBuffers(NULL, NULL);
+       CFWriteStreamOpen(stream);
+       CFPropertyListWriteToStream(obj, stream, kCFPropertyListBinaryFormat_v1_0, NULL);
+       CFWriteStreamClose(stream);
+       myXml = CFWriteStreamCopyProperty(stream, kCFStreamPropertyDataWritten);
+       CFRelease(stream);
        if (!myXml) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("_SCSerialize() failed"));
                if (xml)        *xml     = NULL;
                if (dataRef)    *dataRef = NULL;
                if (dataLen)    *dataLen = 0;
@@ -118,10 +178,7 @@ _SCSerialize(CFPropertyListRef obj, CFDataRef *xml, void **dataRef, CFIndex *dat
                *dataLen = CFDataGetLength(myXml);
                status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE);
                if (status != KERN_SUCCESS) {
-                       SCLog(TRUE,
-                             LOG_ERR,
-                             CFSTR("vm_allocate(): %s"),
-                             mach_error_string(status));
+                       SCLog(TRUE, LOG_ERR, CFSTR("_SCSerialize(): %s"), mach_error_string(status));
                        CFRelease(myXml);
                        *dataRef = NULL;
                        *dataLen = 0;
@@ -153,7 +210,7 @@ _SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dat
 
                status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserialize(): %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
        } else {
@@ -165,10 +222,7 @@ _SCUnserialize(CFPropertyListRef *obj, CFDataRef xml, void *dataRef, CFIndex dat
 
        if (*obj == NULL) {
                if (xmlError) {
-                       SCLog(TRUE,
-                             LOG_ERR,
-                             CFSTR("CFPropertyListCreateFromXMLData() failed: %@"),
-                             xmlError);
+                       SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserialize(): %@"), xmlError);
                        CFRelease(xmlError);
                }
                _SCErrorSet(kSCStatusFailed);
@@ -196,7 +250,7 @@ _SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *da
 
        myData = CFStringCreateExternalRepresentation(NULL, str, kCFStringEncodingUTF8, 0);
        if (!myData) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateExternalRepresentation() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeString() failed"));
                if (data)       *data    = NULL;
                if (dataRef)    *dataRef = NULL;
                if (dataLen)    *dataLen = 0;
@@ -217,10 +271,7 @@ _SCSerializeString(CFStringRef str, CFDataRef *data, void **dataRef, CFIndex *da
                *dataLen = CFDataGetLength(myData);
                status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE);
                if (status != KERN_SUCCESS) {
-                       SCLog(TRUE,
-                             LOG_ERR,
-                             CFSTR("vm_allocate(): %s"),
-                             mach_error_string(status));
+                       SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeString(): %s"), mach_error_string(status));
                        CFRelease(myData);
                        *dataRef = NULL;
                        *dataLen = 0;
@@ -247,7 +298,7 @@ _SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex da
 
                status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
                if (status != KERN_SUCCESS) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserializeString(): %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
        } else {
@@ -255,7 +306,7 @@ _SCUnserializeString(CFStringRef *str, CFDataRef utf8, void *dataRef, CFIndex da
        }
 
        if (*str == NULL) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFStringCreateFromExternalRepresentation() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("_SCUnserializeString() failed"));
                return FALSE;
        }
 
@@ -276,10 +327,7 @@ _SCSerializeData(CFDataRef data, void **dataRef, CFIndex *dataLen)
        *dataLen = CFDataGetLength(data);
        status = vm_allocate(mach_task_self(), (void *)dataRef, *dataLen, TRUE);
        if (status != KERN_SUCCESS) {
-               SCLog(TRUE,
-                     LOG_ERR,
-                     CFSTR("vm_allocate(): %s"),
-                     mach_error_string(status));
+               SCLog(TRUE, LOG_ERR, CFSTR("_SCSerializeData(): %s"), mach_error_string(status));
                *dataRef = NULL;
                *dataLen = 0;
                return FALSE;
@@ -299,7 +347,7 @@ _SCUnserializeData(CFDataRef *data, void *dataRef, CFIndex dataLen)
        *data = CFDataCreate(NULL, dataRef, dataLen);
        status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
        if (status != KERN_SUCCESS) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCUnserializeData(): %s"), mach_error_string(status));
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
@@ -391,7 +439,7 @@ _SCUnserializeMultiple(CFDictionaryRef dict)
 
                CFDictionaryGetKeysAndValues(dict, keys, values);
                for (i = 0; i < nElements; i++) {
-                       if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, NULL)) {
+                       if (!_SCUnserialize((CFPropertyListRef *)&pLists[i], values[i], NULL, 0)) {
                                goto done;
                        }
                }
@@ -424,6 +472,153 @@ _SCUnserializeMultiple(CFDictionaryRef dict)
 }
 
 
+__private_extern__ void
+_SC_signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList)
+{
+       CFRunLoopRef    rl      = NULL;
+       CFRunLoopRef    rl1     = NULL;
+       CFIndex         i;
+       CFIndex         n       = CFArrayGetCount(rlList);
+
+       if (n == 0) {
+               return;
+       }
+
+       /* get first runLoop for this object */
+       for (i = 0; i < n; i += 3) {
+               if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+                       continue;
+               }
+
+               rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
+               break;
+       }
+
+       if (!rl1) {
+               /* if not scheduled */
+               return;
+       }
+
+       /* check if we have another runLoop for this object */
+       rl = rl1;
+       for (i = i+3; i < n; i += 3) {
+               CFRunLoopRef    rl2;
+
+               if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+                       continue;
+               }
+
+               rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
+               if (!CFEqual(rl1, rl2)) {
+                       /* we've got more than one runLoop */
+                       rl = NULL;
+                       break;
+               }
+       }
+
+       if (rl) {
+               /* if we only have one runLoop */
+               CFRunLoopWakeUp(rl);
+               return;
+       }
+
+       /* more than one different runLoop, so we must pick one */
+       for (i = 0; i < n; i+=3) {
+               CFStringRef     rlMode;
+
+               if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
+                       continue;
+               }
+
+               rl     = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
+               rlMode = CFRunLoopCopyCurrentMode(rl);
+               if (rlMode && CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode)) {
+                       /* we've found a runLoop that's "ready" */
+                       CFRelease(rlMode);
+                       CFRunLoopWakeUp(rl);
+                       return;
+               }
+               if (rlMode) CFRelease(rlMode);
+       }
+
+       /* didn't choose one above, so choose first */
+       CFRunLoopWakeUp(rl1);
+       return;
+}
+
+
+__private_extern__ Boolean
+_SC_isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
+{
+       CFIndex i;
+       CFIndex n       = CFArrayGetCount(rlList);
+
+       for (i = 0; i < n; i += 3) {
+               if (obj         && !CFEqual(obj,         CFArrayGetValueAtIndex(rlList, i))) {
+                       continue;
+               }
+               if (runLoop     && !CFEqual(runLoop,     CFArrayGetValueAtIndex(rlList, i+1))) {
+                       continue;
+               }
+               if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
+                       continue;
+               }
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+__private_extern__ void
+_SC_schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
+{
+       CFArrayAppendValue(rlList, obj);
+       CFArrayAppendValue(rlList, runLoop);
+       CFArrayAppendValue(rlList, runLoopMode);
+
+       return;
+}
+
+
+__private_extern__ Boolean
+_SC_unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
+{
+       CFIndex i       = 0;
+       Boolean found   = FALSE;
+       CFIndex n       = CFArrayGetCount(rlList);
+
+       while (i < n) {
+               if (obj         && !CFEqual(obj,         CFArrayGetValueAtIndex(rlList, i))) {
+                       i += 3;
+                       continue;
+               }
+               if (runLoop     && !CFEqual(runLoop,     CFArrayGetValueAtIndex(rlList, i+1))) {
+                       i += 3;
+                       continue;
+               }
+               if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
+                       i += 3;
+                       continue;
+               }
+
+               found = TRUE;
+
+               CFArrayRemoveValueAtIndex(rlList, i + 2);
+               CFArrayRemoveValueAtIndex(rlList, i + 1);
+               CFArrayRemoveValueAtIndex(rlList, i);
+
+               if (!all) {
+                       return found;
+               }
+
+               n -= 3;
+       }
+
+       return found;
+}
+
+
 void
 __showMachPortStatus()
 {
index b523f567de491853c3df9ab7d964fd028fe6a988..d3a997c2df249b587cd7ed63d016b2a3c4890265 100644 (file)
@@ -49,12 +49,7 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key      = %@"), key);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -82,8 +77,10 @@ SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key)
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configremove(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreRemoveValue configremove(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index aba8569882fcfa2c0cf7984228de7d69d95c0d8f..5b26a4c9b80b972faa2f8aa0760346b3e04197ce 100644 (file)
@@ -59,22 +59,15 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store,
        CFIndex                         myNotifyLen     = 0;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToSet    = %@"), keysToSet);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToRemove = %@"), keysToRemove);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToNotify = %@"), keysToNotify);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
-               return NULL;
+               return FALSE;
        }
 
        if (storePrivate->server == MACH_PORT_NULL) {
                _SCErrorSet(kSCStatusNoStoreServer);
-               return NULL;    /* you must have an open session to play */
+               return FALSE;   /* you must have an open session to play */
        }
 
        /* serialize the key/value pairs to set*/
@@ -85,7 +78,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef   store,
                newInfo = _SCSerializeMultiple(keysToSet);
                if (!newInfo) {
                        _SCErrorSet(kSCStatusFailed);
-                       return NULL;
+                       return FALSE;
                }
 
                ok = _SCSerialize(newInfo, &xmlSet, (void **)&mySetRef, &mySetLen);
@@ -93,7 +86,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef   store,
 
                if (!ok) {
                        _SCErrorSet(kSCStatusFailed);
-                       return NULL;
+                       return FALSE;
                }
        }
 
@@ -102,7 +95,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef  store,
                if (!_SCSerialize(keysToRemove, &xmlRemove, (void **)&myRemoveRef, &myRemoveLen)) {
                        if (xmlSet)     CFRelease(xmlSet);
                        _SCErrorSet(kSCStatusFailed);
-                       return NULL;
+                       return FALSE;
                }
        }
 
@@ -112,7 +105,7 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef store,
                        if (xmlSet)     CFRelease(xmlSet);
                        if (xmlRemove)  CFRelease(xmlRemove);
                        _SCErrorSet(kSCStatusFailed);
-                       return NULL;
+                       return FALSE;
                }
        }
 
@@ -132,8 +125,10 @@ SCDynamicStoreSetMultiple(SCDynamicStoreRef        store,
        if (xmlNotify)  CFRelease(xmlNotify);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configset_m(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetMultiple configset_m(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
@@ -162,13 +157,7 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR
        int                             sc_status;
        int                             newInstance;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreSetValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), value);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -208,8 +197,10 @@ SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFPropertyListR
        CFRelease(xmlData);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configset(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSetValue configset(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 13e069d14ed4852167576507e93ab63ee6ce13a2..5f69bb748e668fcbc21bdf36b54aeeeb8e2fbd1e 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSnapshot:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -63,8 +61,10 @@ SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        status = snapshot(storePrivate->server, (int *)&sc_status);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("snapshot(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreSnapshot snapshot(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index 4450e9ed361ec9d02cc48b5148bc860daf7ab2f6..8b71a7bea0aa7c6daf9b2d47ecca3b28bad2273f 100644 (file)
@@ -49,12 +49,7 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
        CFIndex                         myKeyLen;
        int                             sc_status;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
-       }
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -82,8 +77,10 @@ SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
        CFRelease(utfKey);
 
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configtouch(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreTouchValue configtouch(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index c847c3fe1abc86aedcf8040602eb611768ad962a..d90117128a0bff315eb7092aa560ac5ffd215c02 100644 (file)
@@ -46,9 +46,7 @@ SCDynamicStoreUnlock(SCDynamicStoreRef store)
        kern_return_t                   status;
        int                             sc_status;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreUnlock:"));
-
-       if (!store) {
+       if (store == NULL) {
                /* sorry, you must provide a session */
                _SCErrorSet(kSCStatusNoStoreSession);
                return FALSE;
@@ -63,8 +61,10 @@ SCDynamicStoreUnlock(SCDynamicStoreRef store)
        /* (attempt to) release the servers lock */
        status = configunlock(storePrivate->server, (int *)&sc_status);
        if (status != KERN_SUCCESS) {
+#ifdef DEBUG
                if (status != MACH_SEND_INVALID_DEST)
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("configunlock(): %s"), mach_error_string(status));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCDynamicStoreUnlock configunlock(): %s"), mach_error_string(status));
+#endif /* DEBUG */
                (void) mach_port_destroy(mach_task_self(), storePrivate->server);
                storePrivate->server = MACH_PORT_NULL;
                _SCErrorSet(status);
index ea0d504e7f4839965c9c8a73d30be8877939db7a..babb95c4c92be425e3f8c74b0a58b9642f1b2672 100644 (file)
 #define _SCDYNAMICSTORE_H
 
 #include <sys/cdefs.h>
-#include <sys/syslog.h>
-#include <mach/message.h>
 #include <CoreFoundation/CoreFoundation.h>
 
-
 /*!
        @header SCDynamicStore
-       The SystemConfiguration framework provides access to the
-       data used to configure a running system.  The APIs provided
-       by this framework communicate with the "configd" daemon.
-
-       The "configd" daemon manages a "dynamic store" reflecting the
-       desired configuration settings as well as the current state
-       of the system.  The daemon provides a notification mechanism
-       for user-level processes that need to be aware of changes
-       made to the data.  Lastly, the daemon loads a number of
-       bundles (or plug-ins) that monitor low-level kernel events
-       and, via a set of policy modules, keep the state data up
-       to date.
+       @discussion The SCDynamicStore API provides access to the key-value
+               pairs in the dynamic store of a running system.  The dynamic
+               store contains, among other items, a copy of the configuration
+               settings for the currently active set (which is sometimes
+               refered to as the location) and information about the current
+               network state.
+
+               The functions in the SCDynamicStore API allow you to find
+               key-value pairs, add or remove key-value pairs, add or change
+               values, and request notifications.
+
+               To use the functions of the SCDynamicStore API, you must first
+               establish a dynamic store session using the SCDynamicStoreCreate
+               function.  When you are finished with the session, use CFRelease
+               to close it.
  */
 
 
 /*!
        @typedef SCDynamicStoreRef
-       @discussion This is the handle to an open "dynamic store" session
+       @discussion This is the handle to an open a dynamic store session
                with the system configuration daemon.
  */
 typedef const struct __SCDynamicStore *        SCDynamicStoreRef;
 
 /*!
        @typedef SCDynamicStoreContext
+       Structure containing user-specified data and callbacks for an
+       SCDynamicStore session.
+       @field version The version number of the structure type being passed
+               in as a parameter to the SCDynamicStore creation function.
+               This structure is version 0.
+       @field info A C pointer to a user-specified block of data.
+       @field retain The callback used to add a retain for the info field.
+               If this parameter is not a pointer to a function of the correct
+               prototype, the behavior is undefined.  The value may be NULL.
+       @field release The calllback used to remove a retain previously added
+               for the info field.  If this parameter is not a pointer to a
+               function of the correct prototype, the behavior is undefined.
+               The value may be NULL.
+       @field copyDescription The callback used to provide a description of
+               the info field.
  */
 typedef struct {
        CFIndex         version;
@@ -67,11 +82,11 @@ typedef struct {
 
 /*!
        @typedef SCDynamicStoreCallBack
-       @discussion Type of the callback function used when a
-               dynamic store change is delivered.
-       @param store The "dynamic store" session.
+       @discussion Type of callback function used when notification of
+               changes to the dynamic store is delivered.
+       @param store The dynamic store session.
        @param changedKeys The list of changed keys.
-       @param info ....
+       @param info A C pointer to a user-specified block of data.
  */
 typedef void (*SCDynamicStoreCallBack) (
                                        SCDynamicStoreRef       store,
@@ -84,7 +99,7 @@ __BEGIN_DECLS
 
 /*!
        @function SCDynamicStoreGetTypeID
-       Returns the type identifier of all SCDynamicStore instances.
+       @discussion Returns the type identifier of all SCDynamicStore instances.
  */
 CFTypeID
 SCDynamicStoreGetTypeID                        (void);
@@ -93,21 +108,21 @@ SCDynamicStoreGetTypeID                    (void);
 /*!
        @function SCDynamicStoreCreate
        @discussion Creates a new session used to interact with the dynamic
-               store maintained by the SystemConfiguration server.
-       @param allocator The CFAllocator which should be used to allocate
-               memory for the local "dynamic store" and its storage for
-               values.
+               store maintained by the System Configuration server.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for the local dynamic store object.
                This parameter may be NULL in which case the current
                default CFAllocator is used. If this reference is not
                a valid CFAllocator, the behavior is undefined.
        @param name A string that describes the name of the calling
                process or plug-in of the caller.
        @param callout The function to be called when a watched value
-               in the "dynamic store" is changed.
+               in the dynamic store is changed.
                A NULL value can be specified if no callouts are
                desired.
        @param context The SCDynamicStoreContext associated with the callout.
-       @result A reference to the new SCDynamicStore.
+       @result Returns a reference to the new SCDynamicStore session.
+               You must release the returned value.
  */
 SCDynamicStoreRef
 SCDynamicStoreCreate                   (
@@ -118,23 +133,71 @@ SCDynamicStoreCreate                      (
                                        );
 
 /*!
-       @function SCDynamicStoreCreateRunLoopSource
+       @function SCDynamicStoreCreateWithOptions
        @discussion Creates a new session used to interact with the dynamic
-               store maintained by the SystemConfiguration server.
-       @param allocator The CFAllocator which should be used to allocate
-               memory for the local "dynamic store" and its storage for
-               values.
+               store maintained by the System Configuration server.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for the local dynamic store object.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param name A string that describes the name of the calling
+               process or plug-in of the caller.
+       @param storeOptions A CFDictionary containing options for the
+               dynamic store session (such as whether all keys added or set
+               into the dynamic store should be per-session keys).
+
+               Currently available options include:
+
+               <TABLE BORDER>
+               <TR>
+                       <TH>key</TD>
+                       <TH>value</TD>
+               </TR>
+               <TR>
+                       <TD>kSCDynamicStoreUseSessionKeys</TD>
+                       <TD>CFBooleanRef</TD>
+               </TR>
+               </TABLE>
+
+               A NULL value can be specified if no options are desired.
+       @param callout The function to be called when a watched value
+               in the dynamic store is changed.
+               A NULL value can be specified if no callouts are
+               desired.
+       @param context The SCDynamicStoreContext associated with the callout.
+       @result Returns a reference to the new SCDynamicStore session.
+               You must release the returned value.
+ */
+SCDynamicStoreRef
+SCDynamicStoreCreateWithOptions                (
+                                       CFAllocatorRef                  allocator,
+                                       CFStringRef                     name,
+                                       CFDictionaryRef                 storeOptions,
+                                       SCDynamicStoreCallBack          callout,
+                                       SCDynamicStoreContext           *context
+                                       );
+
+extern const CFStringRef       kSCDynamicStoreUseSessionKeys;  /* CFBoolean */
+
+/*!
+       @function SCDynamicStoreCreateRunLoopSource
+       @discussion Creates a CFRunLoopSource object that can be added to the
+               application's run loop.  All dynamic store notifications are
+               delivered using this run loop source.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this run loop source.
                This parameter may be NULL in which case the current
                default CFAllocator is used. If this reference is not
                a valid CFAllocator, the behavior is undefined.
-       @param store The "dynamic store" session.
-       @param order On platforms which support it, this parameter
-               determines the order in which the sources which are
-               ready to be processed are handled.  A lower order
-               number causes processing before higher order number
-               sources. It is inadvisable to depend on the order
-               number for any architectural or design aspect of
-               code. In the absence of any reason to do otherwise,
+       @param store A reference to the dynamic store session.
+       @param order On platforms which support it, for source versions
+               which support it, this parameter determines the order in
+               which the sources which are ready to be processed are
+               handled. A lower order number causes processing before
+               higher order number sources. It is inadvisable to depend
+               on the order number for any architectural or design aspect
+               of code. In the absence of any reason to do otherwise,
                zero should be used.
        @result A reference to the new CFRunLoopSource.
                You must release the returned value.
@@ -150,14 +213,13 @@ SCDynamicStoreCreateRunLoopSource (
 /*!
        @function SCDynamicStoreCopyKeyList
        @discussion Returns an array of CFString keys representing the
-               configuration "dynamic store" entries that match a
-               specified pattern.
-       @param store The "dynamic store" session.
-       @param pattern A regex(3) regular expression pattern that
-               will be used to match the "dynamic store" keys.
-       @result The list of matching keys.
+               current dynamic store entries that match a specified pattern.
+       @param store The dynamic store session.
+       @param pattern A regex(3) regular expression pattern
+               used to match the dynamic store keys.
+       @result Returns the list of matching keys; NULL if an error was
+               encountered.
                You must release the returned value.
-               A NULL value will be returned if the list could not be obtained.
  */
 CFArrayRef
 SCDynamicStoreCopyKeyList              (
@@ -167,13 +229,13 @@ SCDynamicStoreCopyKeyList         (
 
 /*!
        @function SCDynamicStoreAddValue
-       @discussion Adds the key-value pair to the "dynamic store" if no
+       @discussion Adds the key-value pair to the dynamic store if no
                such key already exists.
-       @param store The "dynamic store" session.
-       @param key The key of the value to add to the "dynamic store".
-       @param value The value to add to the "dynamic store".
-       @result TRUE if the key was added; FALSE if the key was already
-               present in the "dynamic store" or if an error was encountered.
+       @param store The dynamic store session.
+       @param key The key of the value to add to the dynamic store.
+       @param value The value to add to the dynamic store.
+       @result Returns TRUE if the key was added; FALSE if the key was already
+               present in the dynamic store or if an error was encountered.
  */
 Boolean
 SCDynamicStoreAddValue                 (
@@ -184,15 +246,15 @@ SCDynamicStoreAddValue                    (
 
 /*!
        @function SCDynamicStoreAddTemporaryValue
-       @discussion Adds the key-value pair on a temporary basis to the
-               "dynamic store" if no such key already exists.  This entry
-               will, unless updated by another session, automatically be
-               removed when the session is closed.
-       @param store The "dynamic store" session.
-       @param key The key of the value to add to the "dynamic store".
-       @param value The value to add to the "dynamic store".
-       @result TRUE if the key was added; FALSE if the key was already
-               present in the "dynamic store" or if an error was encountered.
+       @discussion Temporarily adds the key-value pair to the dynamic store
+               if no such key already exists.  Unless the key is updated by another
+               session, the key-value pair will be removed automatically when the
+               session is closed.
+       @param store The dynamic store session.
+       @param key The key of the value to add to the dynamic store.
+       @param value The value to add to the dynamic store.
+       @result Returns TRUE if the key was added; FALSE if the key was already
+               present in the dynamic store or if an error was encountered.
  */
 Boolean
 SCDynamicStoreAddTemporaryValue                (
@@ -203,15 +265,12 @@ SCDynamicStoreAddTemporaryValue           (
 
 /*!
        @function SCDynamicStoreCopyValue
-       @discussion Obtains a value from the "dynamic store" for the
-               specified key.
-       @param store The "dynamic store" session.
-       @param key The key you wish to obtain.
-       @result The value from the store that is associated with the
-               given key.  The value is returned as a Core Foundation
-               Property List data type.
+       @discussion Gets the value of the specified key from the dynamic store.
+       @param store The dynamic store session.
+       @param key The key associated with the value you want to get.
+       @result Returns the value from the dynamic store that is associated with the given
+               key; NULL if no value was located or an error was encountered.
                You must release the returned value.
-               If no value was located, NULL is returned.
  */
 CFPropertyListRef
 SCDynamicStoreCopyValue                        (
@@ -221,15 +280,15 @@ SCDynamicStoreCopyValue                   (
 
 /*!
        @function SCDynamicStoreCopyMultiple
-       @discussion Fetches multiple values in the "dynamic store".
-       @param store The "dynamic store" session.
-       @param keys The keys to be fetched; NULL if no specific keys
-               are requested.
-       @param patterns The regex(3) pattern strings to be fetched; NULL
+       @discussion Gets the values of multiple keys in the dynamic store.
+       @param store The dynamic store session.
+       @param keys The keys associated with the values you want to get; NULL if no specific
+               keys are requested.
+       @param patterns An array of regex(3) pattern strings used to match the keys; NULL
                if no key patterns are requested.
-       @result A dictionary containing the specific keys which were found
-               in the "dynamic store" and any keys which matched the specified
-               patterns; NULL is returned if an error was encountered.
+       @result Returns a dictionary containing the key-value pairs of specific keys and the
+               key-value pairs of keys that matched the specified patterns;
+               NULL if an error was encountered.
                You must release the returned value.
  */
 CFDictionaryRef
@@ -241,12 +300,12 @@ SCDynamicStoreCopyMultiple                (
 
 /*!
        @function SCDynamicStoreSetValue
-       @discussion Adds or replaces a value in the "dynamic store" for
+       @discussion Adds or replaces a value in the dynamic store for
                the specified key.
-       @param store The "dynamic store" session.
-       @param key The key you wish to set.
-       @param value The value to add to or replace in the "dynamic store".
-       @result TRUE if the key was updated; FALSE if an error was encountered.
+       @param store The dynamic store session.
+       @param key The key you want to set.
+       @param value The value to add to or replace in the dynamic store.
+       @result Returns TRUE if the key was updated; FALSE if an error was encountered.
  */
 Boolean
 SCDynamicStoreSetValue                 (
@@ -257,12 +316,12 @@ SCDynamicStoreSetValue                    (
 
 /*!
        @function SCDynamicStoreSetMultiple
-       @discussion Updates multiple values in the "dynamic store".
-       @param store The "dynamic store" session.
-       @param keysToSet Key/value pairs you wish to set into the "dynamic store".
-       @param keysToRemove A list of keys you wish to remove from the "dynamic store".
-       @param keysToNotify A list of keys to flag as changed (without actually changing the data).
-       @result TRUE if the dynamic store updates were successful; FALSE if an error was encountered.
+       @discussion Updates multiple values in the dynamic store.
+       @param store The dynamic store session.
+       @param keysToSet A dictionary of key-value pairs you want to set into the dynamic store.
+       @param keysToRemove An array of keys you want to remove from the dynamic store.
+       @param keysToNotify An array of keys to flag as changed (without changing their values).
+       @result Returns TRUE if the dynamic store updates were successful; FALSE if an error was encountered.
  */
 Boolean
 SCDynamicStoreSetMultiple              (
@@ -275,10 +334,10 @@ SCDynamicStoreSetMultiple         (
 /*!
        @function SCDynamicStoreRemoveValue
        @discussion Removes the value of the specified key from the
-               "dynamic store".
-       @param store The "dynamic store" session.
-       @param key The key of the value you wish to remove.
-       @result TRUE if the key was removed; FALSE if no value was
+               dynamic store.
+       @param store The dynamic store session.
+       @param key The key of the value you want to remove.
+       @result Returns TRUE if the key was removed; FALSE if no value was
                located or an error was encountered.
  */
 Boolean
@@ -291,9 +350,11 @@ SCDynamicStoreRemoveValue          (
        @function SCDynamicStoreNotifyValue
        @discussion Triggers a notification to be delivered for the
                specified key in the dynamic store.
-       @param store The "dynamic store" session.
-       @param key The key which should be flagged as changed (without actually changing the data).
-       @result TRUE if the value was updated; FALSE if an error was encountered.
+       @param store The dynamic store session.
+       @param key The key that should be flagged as changed.  Any dynamic store sessions
+               that are monitoring this key will received a notification.  Note that the
+               key's value is not updated.
+       @result Returns TRUE if the notification was processed; FALSE if an error was encountered.
  */
 Boolean
 SCDynamicStoreNotifyValue              (
@@ -304,14 +365,14 @@ SCDynamicStoreNotifyValue         (
 /*!
        @function SCDynamicStoreSetNotificationKeys
        @discussion Specifies a set of specific keys and key patterns
-               which should be monitored for changes.
-       @param store The "dynamic store" session being watched.
-       @param keys The keys to be monitored; NULL if no specific keys
+               that should be monitored for changes.
+       @param store The dynamic store session being watched.
+       @param keys An array of keys to be monitored; NULL if no specific keys
                are to be monitored.
-       @param patterns The regex(3) pattern strings to be monitored; NULL
-               if no key patterns are to be monitored.
-       @result TRUE if the monitored keys were set; FALSE if an error
-               was encountered.
+       @param patterns An array of regex(3) pattern strings used to match keys to be monitored;
+               NULL if no key patterns are to be monitored.
+       @result Returns TRUE if the set of notification keys and patterns was successfully
+               updated; FALSE if an error was encountered.
  */
 Boolean
 SCDynamicStoreSetNotificationKeys      (
@@ -323,12 +384,14 @@ SCDynamicStoreSetNotificationKeys (
 /*!
        @function SCDynamicStoreCopyNotifiedKeys
        @discussion Returns an array of CFString keys representing the
-               "dynamic store" entries that have changed since this
-               function was last called.
-       @param store The "dynamic store" session.
-       @result The list of changed keys.
+               dynamic store entries that have changed since this
+               function was last called.  If possible, your application should
+               use the notification functions instead of polling for the list
+               of changed keys returned by this function.
+       @param store The dynamic store session.
+       @result Returns the list of changed keys;
+               NULL if an error was encountered.
                You must release the returned value.
-               A NULL value will be returned if the list could not be obtained.
  */
 CFArrayRef
 SCDynamicStoreCopyNotifiedKeys         (
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
-       @discussion Copies the DHCP/BOOTP information dictionary for the
-               requested serviceID, or the primary service if
-               serviceID == NULL.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+       @discussion Copies the DHCP information for the requested serviceID,
+               or the primary service if serviceID == NULL.
+       @param store An SCDynamicStoreRef representing the dynamic store session
+               that should be used for communication with the server.
                If NULL, a temporary session will be used.
        @param serviceID A CFStringRef containing the requested service.
                If NULL, returns information for the primary service.
-       @result A dictionary containing DHCP/BOOTP information if successful,
+       @result Returns a dictionary containing DHCP information if successful;
                NULL otherwise.
-               Use the DHCPInfoGetOption() to retrieve
+               Use the DHCPInfoGetOption function to retrieve
                individual options from the returned dictionary.
 
                A non-NULL return value must be released using CFRelease().
@@ -60,14 +60,14 @@ SCDynamicStoreCopyDHCPInfo(SCDynamicStoreRef store, CFStringRef serviceID);
 
 /*!
        @function DHCPInfoGetOptionData
-       @discussion Returns a non-NULL CFDataRef containing the BOOTP/DHCP
-               option data if present, NULL otherwise.
+       @discussion Returns a non-NULL CFDataRef containing the DHCP
+               option data, if present.
        @param info The non-NULL DHCP information dictionary returned by
                calling SCDynamicStoreCopyDHCPInfo.
-       @param code The DHCP/BOOTP option code (see RFC 2132) to return
+       @param code The DHCP option code (see RFC 2132) to return
                data for.
-       @result A non-NULL CFDataRef containing the option data,
-               NULL otherwise.
+       @result Returns a non-NULL CFDataRef containing the option data;
+               NULL if the requested option data is not present.
 
                The return value must NOT be released.
  */
@@ -77,11 +77,12 @@ DHCPInfoGetOptionData(CFDictionaryRef info, UInt8 code);
 /*!
        @function DHCPInfoGetLeaseStartTime
        @discussion Returns a CFDateRef corresponding to the lease start time,
-               if present, NULL otherwise.  A NULL return value is returned
-               if the configuration method is BOOTP.
+               if present.
        @param info The non-NULL DHCP information dictionary returned by
                calling SCDynamicStoreCopyDHCPInfo.
-       @result A non-NULL CFDateRef if present, NULL otherwise.
+       @result Returns a non-NULL CFDateRef if lease start time information is
+               present; NULL if the information is not present or if the
+               configuration method is not DHCP.
 
                The return value must NOT be released.
  */
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@
  * 
 #define _SCDYNAMICSTORECOPYSPECIFIC_H
 
 #include <sys/cdefs.h>
+#include <sys/types.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 /*!
        @header SCDynamicStoreCopySpecific
-       The following APIs allow an application to determine specific
-       configuration information about the current system (e.g. the
-       computer/sharing name, the currently logged in user, etc).
+       @discussion The functions of the SCDynamicStoreCopySpecific API
+               allow an application to determine specific configuration
+               information about the current system (for example, the
+               computer or sharing name, the currently logged-in user, etc.).
  */
 
 
@@ -41,13 +43,14 @@ __BEGIN_DECLS
 
 /*!
        @function SCDynamicStoreCopyComputerName
-       @discussion Gets the current computer/host name.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+       @discussion Gets the current computer name.
+       @param store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
                If NULL, a temporary session will be used.
        @param nameEncoding A pointer to memory that, if non-NULL, will be
-               filled with the encoding associated with the computer/host name.
-       @result The current computer/host name;
+               filled with the encoding associated with the computer or
+               host name.
+       @result Returns the current computer name;
                NULL if the name has not been set or if an error was encountered.
                You must release the returned value.
  */
@@ -60,17 +63,22 @@ SCDynamicStoreCopyComputerName              (
 /*!
        @function SCDynamicStoreCopyConsoleUser
        @discussion Gets the name, user ID, and group ID of the currently
-               logged in user.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+               logged-in user.
+
+               Note: this function only provides information about the
+                     primary console.  It does not provide any details
+                     about console sessions that have fast user switched
+                     out or about other consoles.
+       @param store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
                If NULL, a temporary session will be used.
        @param uid A pointer to memory that will be filled with the user ID
-               of the current "Console" user. If NULL, this value will not
+               of the current console user. If NULL, this value will not
                be returned.
        @param gid A pointer to memory that will be filled with the group ID
-               of the current "Console" user. If NULL, this value will not be
+               of the current console user. If NULL, this value will not be
                returned.
-       @result The current user logged into the system;
+       @result Returns the user currently logged into the system;
                NULL if no user is logged in or if an error was encountered.
                You must release the returned value.
  */
@@ -84,13 +92,10 @@ SCDynamicStoreCopyConsoleUser               (
 /*!
        @function SCDynamicStoreCopyLocalHostName
        @discussion Gets the current local host name.
-
-               See SCDynamicStoreKeyCreateHostNames() for notification
-               key information.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+       @param store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
                If NULL, a temporary session will be used.
-       @result The current local host name;
+       @result Returns the current local host name;
                NULL if the name has not been set or if an error was encountered.
                You must release the returned value.
  */
@@ -101,12 +106,12 @@ SCDynamicStoreCopyLocalHostName           (
 
 /*!
        @function SCDynamicStoreCopyLocation
-       @discussion Gets the current "location" identifier.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+       @discussion Gets the current location identifier.
+       @param store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
                If NULL, a temporary session will be used.
-       @result A string representing the current "location" identifier;
-               NULL if no "location" identifier has been defined or if an error
+       @result Returns a string representing the current location identifier;
+               NULL if no location identifier has been defined or if an error
                was encountered.
                You must release the returned value.
  */
@@ -118,12 +123,81 @@ SCDynamicStoreCopyLocation                (
 /*!
        @function SCDynamicStoreCopyProxies
        @discussion Gets the current internet proxy settings.
-       @param store An SCDynamicStoreRef that should be used for communication
-               with the server.
+               The returned proxy settings dictionary includes:
+
+               <TABLE BORDER>
+               <TR>
+                       <TH>key</TD>
+                       <TH>type</TD>
+                       <TH>description</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesExceptionsList</TD>
+                       <TD>CFArray[CFString]</TD>
+                       <TD>Host name patterns which should bypass the proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPEnable</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enables/disables the use of an HTTP proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPProxy</TD>
+                       <TD>CFString</TD>
+                       <TD>The proxy host</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPPort</TD>
+                       <TD>CFNumber</TD>
+                       <TD>The proxy port number</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPSEnable</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enables/disables the use of an HTTPS proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPSProxy</TD>
+                       <TD>CFString</TD>
+                       <TD>The proxy host</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesHTTPSPort</TD>
+                       <TD>CFNumber</TD>
+                       <TD>The proxy port number</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPEnable</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enables/disables the use of an FTP proxy</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPProxy</TD>
+                       <TD>CFString</TD>
+                       <TD>The proxy host</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPPort</TD>
+                       <TD>CFNumber</TD>
+                       <TD>The proxy port number</TD>
+               </TR>
+               <TR>
+                       <TD>kSCPropNetProxiesFTPPassive</TD>
+                       <TD>CFNumber (0 or 1)</TD>
+                       <TD>Enable passive mode operation for use behind connection
+                       filter-ing firewalls.</TD>
+               </TR>
+               </TABLE>
+
+               Other key-value pairs are defined in the SCSchemaDefinitions.h
+               header file.
+       @param store An SCDynamicStoreRef representing the dynamic store
+               session that should be used for communication with the server.
                If NULL, a temporary session will be used.
-       @result A dictionary with key/value pairs representing the current
-               internet proxy settings (HTTP, FTP, etc);
-               NULL if no proxy settings have been defined or if an error was encountered.
+       @result Returns a dictionary containing key-value pairs that represent
+               the current internet proxy settings;
+               NULL if no proxy settings have been defined or if an error
+               was encountered.
                You must release the returned value.
  */
 CFDictionaryRef
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
  */
-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
index 51f28b239d01f0f9829d3bd58972ce5d0eac5a3c..6017d207d70aa19b01c0e24e5c0e02ecc4b5adc2 100644 (file)
@@ -56,10 +56,7 @@ typedef struct {
 
        /* per-session flags */
        Boolean                         locked;
-
-       /* SCDynamicStoreKeys being watched */
-       CFMutableSetRef                 keys;
-       CFMutableSetRef                 patterns;
+       Boolean                         useSessionKeys;
 
        /* current status of notification requests */
        __SCDynamicStoreNotificationStatus      notifyStatus;
@@ -74,8 +71,11 @@ typedef struct {
        SCDynamicStoreCallBack_v1       callbackFunction;
        void                            *callbackArgument;
        CFMachPortRef                   callbackPort;
-       CFRunLoopRef                    callbackRunLoop;
-       CFRunLoopSourceRef              callbackRunLoopSource;
+       CFRunLoopSourceRef              callbackRLS;
+
+       /* "server" SCDynamicStoreKeys being watched */
+       CFMutableSetRef                 keys;
+       CFMutableSetRef                 patterns;
 
        /* "server" information associated with SCDynamicStoreNotifyMachPort() */
        mach_port_t                     notifyPort;
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@
  * 
 
 /*!
        @header SCDynamicStoreKey
+       @discussion The SCDynamicStoreKey API provides convenience functions
+               that an application can use to create a correctly formatted
+               dynamic store key for accessing specific items in the dynamic
+               store.  An application can then use the resulting string in
+               any function that requires a dynamic store key.
  */
 
 
 __BEGIN_DECLS
 
 /*
- * SCDynamicStoreKeyCreate*
+ * SCDynamicStoreKeyCreate
  * - convenience routines that create a CFString key for an item in the store
  */
 
 /*!
        @function SCDynamicStoreKeyCreate
-       @discussion Creates a store key using the given format.
+       @discussion Creates a dynamic store key using the given format.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param fmt A CFStringRef describing the format for this key.
+       @result Returns a string containing the formatted key.
  */
 CFStringRef
 SCDynamicStoreKeyCreate                                (
@@ -53,6 +65,21 @@ SCDynamicStoreKeyCreate                              (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkGlobalEntity
+       @discussion Creates a dynamic store key that can be used to access
+               a specific global (as opposed to a per-service or per-interface)
+               network configuration entity.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param domain A string specifying the desired domain, such as the
+               requested configuration (kSCDynamicStoreDomainSetup) or the
+               actual state (kSCDynamicStoreDomainState).
+       @param entity A string containing the specific global entity, such
+               as IPv4 (kSCEntNetIPv4) or DNS (kSCEntNetDNS).
+       @result Returns a string containing the formatted key.
+
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkGlobalEntity     (
@@ -63,6 +90,19 @@ SCDynamicStoreKeyCreateNetworkGlobalEntity   (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkInterface
+       @discussion Creates a dynamic store key that can be used to access
+               the network interface configuration information stored in
+               the dynamic store.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param domain A string specifying the desired domain, such as the
+               requested configuration (kSCDynamicStoreDomainSetup) or the
+               actual state (kSCDynamicStoreDomainState).
+       @result Returns a string containing the formatted key.
+
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkInterface                (
@@ -72,6 +112,23 @@ SCDynamicStoreKeyCreateNetworkInterface             (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkInterfaceEntity
+       @discussion Creates a dynamic store key that can be used to access
+               the per-interface network configuration information stored in
+               the dynamic store.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param domain A string specifying the desired domain, such as the
+               requested configuration (kSCDynamicStoreDomainSetup) or the
+               actual state (kSCDynamicStoreDomainState).
+       @param ifname A string containing the interface name or a regular
+               expression pattern.
+       @param entity A string containing the specific global entity, such
+               as IPv4 (kSCEntNetIPv4) or DNS (kSCEntNetDNS).
+       @result Returns a string containing the formatted key.
+
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkInterfaceEntity  (
@@ -83,6 +140,24 @@ SCDynamicStoreKeyCreateNetworkInterfaceEntity       (
 
 /*!
        @function SCDynamicStoreKeyCreateNetworkServiceEntity
+       @discussion Creates a dynamic store key that can be used to access
+               the per-service network configuration information stored in
+               the dynamic store.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @param domain A string specifying the desired domain, such as the
+               requested configuration (kSCDynamicStoreDomainSetup) or the
+               actual state (kSCDynamicStoreDomainState).
+       @param serviceID A string containing the service ID or a regular
+               expression pattern.
+       @param entity A string containing the specific global entity, such
+               as IPv4 (kSCEntNetIPv4) or DNS (kSCEntNetDNS).
+       @result Returns a string containing the formatted key.
+
+
  */
 CFStringRef
 SCDynamicStoreKeyCreateNetworkServiceEntity    (
@@ -94,10 +169,16 @@ SCDynamicStoreKeyCreateNetworkServiceEntity        (
 
 /*!
        @function SCDynamicStoreKeyCreateComputerName
-       @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
-               function to receive notifications when the current
-               computer/host name changes.
-       @result A notification string for the current computer/host name.
+       @discussion Creates a key that can be used in conjuntion with
+               SCDynamicStoreSetNotificationKeys function to receive
+               notifications when the current computer name changes.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @result Returns a notification string for the current computer or
+               host name.
 */
 CFStringRef
 SCDynamicStoreKeyCreateComputerName            (
@@ -106,10 +187,15 @@ SCDynamicStoreKeyCreateComputerName               (
 
 /*!
        @function SCDynamicStoreKeyCreateConsoleUser
-       @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
-               function to receive notifications when the current "Console"
-               user changes.
-       @result A notification string for the current "Console" user.
+       @discussion Creates a key that can be used in conjunction with
+               SCDynamicStoreSetNotificationKeys function to receive
+               notifications when the current console user changes.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @result Returns a notification string for the current console user.
 */
 CFStringRef
 SCDynamicStoreKeyCreateConsoleUser             (
@@ -118,11 +204,16 @@ SCDynamicStoreKeyCreateConsoleUser                (
 
 /*!
        @function SCDynamicStoreKeyCreateHostNames
-       @discussion Creates a key that can be used in conjunction with
-               SCDynamicStoreSetNotificationKeys() to receive
+       @discussion Creates a key that can be used in conjunction with the
+               SCDynamicStoreSetNotificationKeys function to receive
                notifications when the HostNames entity changes.  The
-               HostNames entity contains the LocalHostName.
-       @result A notification string for the HostNames entity.
+               HostNames entity includes the local host name.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @result Returns a notification string for the HostNames entity.
 */
 CFStringRef
 SCDynamicStoreKeyCreateHostNames               (
@@ -131,10 +222,16 @@ SCDynamicStoreKeyCreateHostNames          (
 
 /*!
        @function SCDynamicStoreKeyCreateLocation
-       @discussion Creates a key that can be used in conjunction with
-               SCDynamicStoreSetNotificationKeys() to receive
-               notifications when the "location" identifier changes.
-       @result A notification string for the current "location" identifier.
+       @discussion Creates a key that can be used in conjunction with the
+               SCDynamicStoreSetNotificationKeys function to receive
+               notifications when the location identifier changes.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @result Returns a notification string for the current location
+               identifier.
 */
 CFStringRef
 SCDynamicStoreKeyCreateLocation                        (
@@ -143,10 +240,16 @@ SCDynamicStoreKeyCreateLocation                   (
 
 /*!
        @function SCDynamicStoreKeyCreateProxies
-       @discussion Creates a key that can be used by the SCDynamicStoreSetNotificationKeys()
-               function to receive notifications when the current network proxy
-               settings (HTTP, FTP, ...) are changed.
-       @result A notification string for the current proxy settings.
+       @discussion Creates a key that can be used in conjunction with
+               the SCDynamicStoreSetNotificationKeys function to receive
+               notifications when the current network proxy settings
+               (such as HTTP or FTP) are changed.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this key.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used. If this reference is not
+               a valid CFAllocator, the behavior is undefined.
+       @result Returns a notification string for the current proxy settings.
 */
 CFStringRef
 SCDynamicStoreKeyCreateProxies                 (
index ebf7b284e0d85b83ff7fca4ae51d1e88c07b36e1..7ea34c27ca77581f075942f891d0205a06b84d55 100644 (file)
 #define _SCDYNAMICSTOREPRIVATE_H
 
 #include <sys/cdefs.h>
-#include <sys/types.h>
-#include <regex.h>
+#include <mach/message.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
+/*!
+       @header SCDynamicStorePrivate
+ */
+
 /*!
        @typedef SCDynamicStoreCallBack
        @discussion Type of the callback function used when a
                dynamic store change is delivered.
        @param store The "dynamic store" session.
-       @param changedKeys The list of changed keys.
        @param info ....
  */
 typedef boolean_t (*SCDynamicStoreCallBack_v1) (
@@ -138,7 +140,7 @@ SCDynamicStoreRemoveWatchedKey              (SCDynamicStoreRef              store,
 
        @param store The "dynamic store" session.
        @param runLoop A pointer to the run loop.
-       @param funct The callback function to call for each notification.
+       @param func The callback function to call for each notification.
                If this parameter is not a pointer to a function of the
                correct prototype, the behavior is undefined.
        @param context A pointer-sized user-defined value, that is passed as
index 76f8c90ae32766711a4e10c061b3e9a0cfb0081f..81e7f87d18cefa47e9b042b62b09ca6c9e5f296c 100644 (file)
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
+/*!
+       @header SCDynamicStoreSetSpecificPrivate
+ */
+
 __BEGIN_DECLS
 
 /*!
index 06dd8699af97466f01a34a40a4a6f75cccfaf560..602ab547dfdc406b1363082bed2e8422626f2351 100644 (file)
@@ -47,12 +47,12 @@ SCDynamicStoreCopyLocation(SCDynamicStoreRef store)
        CFStringRef             location        = NULL;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyLocation"),
                                             NULL,
                                             NULL);
-               if (!store) {
+               if (store == NULL) {
                        SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
                        return NULL;
                }
index e5f1671604f70c981ba563869c7991e9b0ca12a3..23f6648cc3f1b4615ea237c5c7cc436bc01d2832 100644 (file)
@@ -81,7 +81,7 @@ SCNetworkCheckReachabilityByName(const char                   *nodename,
                                 SCNetworkConnectionFlags       *flags)
 {
        SCNetworkReachabilityRef        networkAddress;
-       Boolean         ok;
+       Boolean                         ok;
 
        if (!nodename) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -98,25 +98,22 @@ Boolean
 SCNetworkInterfaceRefreshConfiguration(CFStringRef ifName)
 {
        CFStringRef             key;
-       Boolean                 ret = FALSE;
-       SCDynamicStoreRef       store = NULL;
+       Boolean                 ret     = FALSE;
+       SCDynamicStoreRef       store;
 
        store = SCDynamicStoreCreate(NULL,
                                     CFSTR("SCNetworkInterfaceRefreshConfiguration"),
                                     NULL, NULL);
        if (store == NULL) {
-               goto done;
+               return FALSE;
        }
+
        key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                            kSCDynamicStoreDomainState,
                                                            ifName,
                                                            kSCEntNetRefreshConfiguration);
        ret = SCDynamicStoreNotifyValue(store, key);
        CFRelease(key);
-
- done:
-       if (store != NULL) {
-               CFRelease(store);
-       }
+       CFRelease(store);
        return (ret);
 }
index b9c9ee1019ed9a4c0396e36a10f497e3f8d25e09..8dae0e8f4a564fe9093b547fae102ce375930bcb 100644 (file)
 
 /*!
        @header SCNetwork
-
-       SCNetworkCheckReachabilityXXX()
-
-       The SCNetworkCheckReachabilityXXX() APIs allow an application to
-       determine the status of the system's current network configuration
-       and the accessibility of a target host/address.
-
-       The term "reachable" reflects whether a data packet, sent by
-       an application into the network stack, can be sent to the
-       the target host/address.  Please note that their is no
-       guarantee that the data packet will actually be received by
-       the host.
-
-
-       SCNetworkInterfaceRefreshConfiguration()
-
-       This API sends a notification to interested network configuration
-       agents to retry their configuraton immediately. For example, calling
-       this API will cause the DHCP client to contact the DHCP server
-       immediately rather than waiting until its timeout has expired.
-       The utility of this API is to allow the caller to give a hint to
-       the system that the network infrastructure/configuration has changed.
+       @discussion The SCNetwork API contains functions an application can
+               use to determine remote host reachability and notify the
+               system of configuration changes.
+
+               The two SCNetworkCheckReachability functions allow an
+               application to determine the status of the system's current
+               network configuration and the reachability of a target host
+               or address.
+
+               "Reachability" reflects whether a data packet, sent by an
+               application into the network stack, can leave the local
+               computer.  Note that reachability does <i>not</i> guarantee
+               that the data packet will actually be received by the host.
+
+               The SCNetworkInterfaceRefreshConfiguration function sends a
+               notification to interested network configuration agents to
+               retry their configuration immediately. For example, calling
+               this function will cause the DHCP client to contact the DHCP
+               server immediately rather than waiting until its timeout has
+               expired.  The utility of this function is to allow the caller
+               to give a hint to the system that the network infrastructure
+               or configuration has changed.
  */
 
 /*!
        @enum SCNetworkConnectionFlags
        @discussion Flags that indicate whether the specified network
-               nodename/address is reachable, requires a connection,
-               requires some user intervention in establishing the
-               connection, and whether the calling application must
-               initiate the connection using the (TBD???) API.
-
+               nodename or address is reachable, whether a connection is
+               required, and whether some user intervention may be required
+               when establishing a connection.
        @constant kSCNetworkFlagsTransientConnection
-               This flag indicates that the specified nodename/address can
-               be reached via a transient (e.g. PPP) connection.
-
+               This flag indicates that the specified nodename or address can
+               be reached via a transient connection, such as PPP.
        @constant kSCNetworkFlagsReachable
-               This flag indicates that the specified nodename/address can
+               This flag indicates that the specified nodename or address can
                be reached using the current network configuration.
-
        @constant kSCNetworkFlagsConnectionRequired
-               This flag indicates that the specified nodename/address can
-               be reached using the current network configuration but a
+               This flag indicates that the specified nodename or address can
+               be reached using the current network configuration, but a
                connection must first be established.
 
                As an example, this status would be returned for a dialup
-               connection that was not currently active but could handle
+               connection that was not currently active, but could handle
                network traffic for the target system.
-
        @constant kSCNetworkFlagsConnectionAutomatic
-               This flag indicates that the specified nodename/address can
-               be reached using the current network configuration but a
+               This flag indicates that the specified nodename or address can
+               be reached using the current network configuration, but a
                connection must first be established.  Any traffic directed
-               to the specified name/address will initiate the connection.
-
+               to the specified name or address will initiate the connection.
        @constant kSCNetworkFlagsInterventionRequired
-               This flag indicates that the specified nodename/address can
-               be reached using the current network configuration but a
+               This flag indicates that the specified nodename or address can
+               be reached using the current network configuration, but a
                connection must first be established.  In addition, some
-               form of user intervention will be required to establish
-               this connection (e.g. providing a password, authentication
-               token, etc.).
-
+               form of user intervention will be required to establish this
+               connection, such as providing a password, an authentication
+               token, etc.
+
+               Note: At the present time, this flag will only be returned
+               in the case where you have a dial-on-traffic configuration
+               (ConnectionAutomatic), where an attempt to connect has
+               already been made, and where some error (e.g. no dial tone,
+               no answer, bad password, ...) was encountered during the
+               automatic connection attempt.  In this case the PPP controller
+               will stop attempting to establish a connection until the user
+               has intervened.
        @constant kSCNetworkFlagsIsLocalAddress
-               This flag indicates that the specified nodename/address
+               This flag indicates that the specified nodename or address
                is one associated with a network interface on the current
                system.
-
        @constant kSCNetworkFlagsIsDirect
                This flag indicates that network traffic to the specified
-               nodename/address will not go through a gateway but is routed
-               directly to one of the interfaces in the system.
+               nodename or address will not go through a gateway, but is
+               routed directly to one of the interfaces in the system.
  */
 enum {
        kSCNetworkFlagsTransientConnection      = 1<<0,
@@ -127,8 +128,8 @@ __BEGIN_DECLS
        @param flags A pointer to memory that will be filled with a
                set of SCNetworkConnectionFlags detailing the reachability
                of the specified address.
-       @result TRUE if the network connection flags are valid; FALSE if the
-               status could not be determined.
+       @result Returns TRUE if the network connection flags are valid;
+               FALSE if the status could not be determined.
  */
 Boolean
 SCNetworkCheckReachabilityByAddress    (
@@ -139,35 +140,39 @@ SCNetworkCheckReachabilityByAddress       (
 
 /*!
        @function SCNetworkCheckReachabilityByName
-       @discussion Determines if the given network host/node name is
+       @discussion Determines if the given network host or node name is
                reachable using the current network configuration.
        @param nodename The node name of the desired host. This name would
-               be the same as that passed to gethostbyname() or getaddrinfo().
+               be the same as that passed to the gethostbyname(3) or
+               getaddrinfo(3) functions.
        @param flags A pointer to memory that will be filled with a
                set of SCNetworkConnectionFlags detailing the reachability
                of the specified node name.
-       @result TRUE if the network connection flags are valid; FALSE if the
-               status could not be determined.
+       @result Returns TRUE if the network connection flags are valid;
+               FALSE if the status could not be determined.
  */
 Boolean
 SCNetworkCheckReachabilityByName       (
                                        const char                      *nodename,
                                        SCNetworkConnectionFlags        *flags
                                        );
+
 /*!
        @function SCNetworkInterfaceRefreshConfiguration
        @discussion Sends a notification to interested configuration agents
                to have them immediately retry their configuration over a
                particular network interface.
-               Note: This API must be invoked by root (uid == 0).
 
-       @param ifName The BSD name of the network interface e.g. CFSTR("en0").
-       @result TRUE if the notification was sent; FALSE otherwise.
+               Note: This function must be invoked by root (uid == 0).
+       @param ifName The BSD name of the network interface, such as
+               CFSTR("en0").
+       @result Returns TRUE if the notification was sent; FALSE otherwise.
  */
 Boolean
 SCNetworkInterfaceRefreshConfiguration (
                                        CFStringRef ifName
                                        );
+
 __END_DECLS
 
 #endif /* _SCNETWORK_H */
diff --git a/SystemConfiguration.fproj/SCNetworkConfiguration.h b/SystemConfiguration.fproj/SCNetworkConfiguration.h
new file mode 100644 (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@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
+ * April 14, 2004              Christophe Allie <callie@apple.com>
+ * - use mach messages
+
  * December 20, 2002           Christophe Allie <callie@apple.com>
  * - initial revision
  */
 #include <SystemConfiguration/SCPrivate.h>
 #include <SystemConfiguration/SCValidation.h>
 
+#include <servers/bootstrap.h>
+
 #include <pthread.h>
+#include <notify.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <arpa/nameser.h>
 #include <netdb.h>
-#include <resolv.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
 
-#include "ppp.h"
-
+#include <ppp/ppp_msg.h>
+#include <ppp/PPPControllerPriv.h>
+#include "pppcontroller.h"
+#include <ppp/pppcontroller_types.h>
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 typedef struct {
 
        /* base CFType information */
-       CFRuntimeBase   cfBase;
+       CFRuntimeBase                   cfBase;
 
        /* service ID */
-       CFStringRef     serviceID;              /* serviceID */
+       CFStringRef                     serviceID;
+
+       /* ref to PPP controller for control messages */
+       mach_port_t                     session_port;
 
-       int             eventRef;               /* ref to PPP controller for event messages */
-       CFSocketRef     eventRefCF;             /* ref to PPP controller for event messages */
-       int             controlRef;             /* ref to PPP controller for control messages */
-       //u_int32_t     status;                 /* current status of the connection */
-       //char          ifname[IFNAMSIZ];       /* ppp interface used for this connection */
+       /* ref to PPP controller for notification messages */
+       CFMachPortRef                   notify_port;
 
        /* run loop source, callout, context, rl scheduling info */
        CFRunLoopSourceRef              rls;
@@ -78,6 +84,9 @@ typedef struct {
        SCNetworkConnectionContext      rlsContext;
        CFMutableArrayRef               rlList;
 
+       /* misc info */
+       int                             debug;
+
 } SCNetworkConnectionPrivate, *SCNetworkConnectionPrivateRef;
 
 /* -------------------------------------------------------------------------------------------
@@ -95,9 +104,9 @@ isA_SCNetworkConnection(CFTypeRef obj)
 static CFStringRef
 __SCNetworkConnectionCopyDescription(CFTypeRef cf)
 {
-       CFAllocatorRef                  allocator = CFGetAllocator(cf);
+       CFAllocatorRef                  allocator               = CFGetAllocator(cf);
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)cf;
        CFMutableStringRef              result;
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)cf;
 
        result = CFStringCreateMutable(allocator, 0);
        CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkConnection, %p [%p]> {\n"), cf, allocator);
@@ -109,37 +118,34 @@ __SCNetworkConnectionCopyDescription(CFTypeRef cf)
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
+
 static void
 __SCNetworkConnectionDeallocate(CFTypeRef cf)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionDeallocate:"));
+       if (connectionPrivate->debug) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionDeallocate (0x%x)"), connectionPrivate);
+       }
 
        /* release resources */
-       if (connectionPrivate->eventRef != -1) {
-               while (CFArrayGetCount(connectionPrivate->rlList)) {
-                       CFRunLoopRef    runLoop;
-                       CFStringRef             runLoopMode;
-
-                       runLoop = (CFRunLoopRef)CFArrayGetValueAtIndex(connectionPrivate->rlList, 1);
-                       runLoopMode = CFArrayGetValueAtIndex(connectionPrivate->rlList, 2);
-                       CFRunLoopRemoveSource(runLoop, connectionPrivate->rls, runLoopMode);
-
-                       CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 2);
-                       CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 1);
-                       CFArrayRemoveValueAtIndex(connectionPrivate->rlList, 0);
-               }
+       if (connectionPrivate->rlList != NULL) {
+               CFRunLoopSourceInvalidate(connectionPrivate->rls);
                CFRelease(connectionPrivate->rls);
                CFRelease(connectionPrivate->rlList);
-               //PPPDispose(connectionPrivate->eventRef);
-               CFSocketInvalidate(connectionPrivate->eventRefCF);
-               CFRelease(connectionPrivate->eventRefCF);
-       }
-       if (connectionPrivate->controlRef != -1)
-               PPPDispose(connectionPrivate->controlRef);
-       if (connectionPrivate->rlsContext.release)
-               connectionPrivate->rlsContext.release(connectionPrivate->rlsContext.info);
+       }
+
+       if (connectionPrivate->notify_port != NULL) {
+               CFMachPortInvalidate(connectionPrivate->notify_port);
+               CFRelease(connectionPrivate->notify_port);
+       }
+
+       if (connectionPrivate->session_port != MACH_PORT_NULL)
+               mach_port_destroy(mach_task_self(), connectionPrivate->session_port);
+
+       if (connectionPrivate->rlsContext.release != NULL)
+               (*connectionPrivate->rlsContext.release)(connectionPrivate->rlsContext.info);
+
        if (connectionPrivate->serviceID)
                CFRelease(connectionPrivate->serviceID);
 
@@ -175,26 +181,130 @@ __SCNetworkConnectionInitialize(void)
        return;
 }
 
+/* -------------------------------------------------------------------------------------------
+------------------------------------------------------------------------------------------- */
+
+static SCNetworkConnectionStatus
+__SCNetworkConnectionConvertStatus (int state)
+{
+       SCNetworkConnectionStatus       status = kSCNetworkConnectionDisconnected;
+
+       switch (state) {
+               case PPP_INITIALIZE:
+               case PPP_CONNECTLINK:
+               case PPP_ESTABLISH:
+               case PPP_AUTHENTICATE:
+               case PPP_CALLBACK:
+               case PPP_NETWORK:
+               case PPP_WAITONBUSY:
+                       status = kSCNetworkConnectionConnecting;
+                       break;
+               case PPP_TERMINATE:
+               case PPP_DISCONNECTLINK:
+                       status = kSCNetworkConnectionDisconnecting;
+                       break;
+               case PPP_RUNNING:
+               case PPP_ONHOLD:
+                       status = kSCNetworkConnectionConnected;
+                       break;
+               case PPP_IDLE:
+               case PPP_DORMANT:
+               case PPP_HOLDOFF:
+               default:
+                       status = kSCNetworkConnectionDisconnected;
+       }
+       return status;
+}
+
+/* -------------------------------------------------------------------------------------------
+------------------------------------------------------------------------------------------- */
+
+static void
+__SCNetworkConnectionCallBack(CFMachPortRef port, void * msg, CFIndex size, void * info)
+{
+       mach_msg_empty_rcv_t *          buf                     = msg;
+       SCNetworkConnectionRef          connection              = (SCNetworkConnectionRef)info;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       void                            *context_info;
+       void                            (*context_release)(const void *);
+       int                             error                   = kSCStatusFailed;
+       mach_msg_id_t                   msgid                   = buf->header.msgh_id;
+       int                             phase                   = PPP_IDLE;
+       SCNetworkConnectionCallBack     rlsFunction;
+       kern_return_t                   status;
+       SCNetworkConnectionStatus       scstatus;
+
+       if (msgid == MACH_NOTIFY_NO_SENDERS) {
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionCallBack: PPPController server died"));
+       } else {
+               status = pppcontroller_getstatus(connectionPrivate->session_port, &phase, &error);
+       }
+
+       if (connectionPrivate->rls == NULL) {
+               return;
+       }
+
+       rlsFunction = connectionPrivate->rlsFunction;
+       if (rlsFunction == NULL) {
+               return;
+       }
+
+       if ((connectionPrivate->rlsContext.retain != NULL) && (connectionPrivate->rlsContext.info != NULL)) {
+               context_info    = (void *)(*connectionPrivate->rlsContext.retain)(connectionPrivate->rlsContext.info);
+               context_release = connectionPrivate->rlsContext.release;
+       } else {
+               context_info    = connectionPrivate->rlsContext.info;
+               context_release = NULL;
+       }
+
+       scstatus = __SCNetworkConnectionConvertStatus(phase);
+
+       (*rlsFunction)(connection, scstatus, context_info);
+       if ((context_release != NULL) && (context_info != NULL)) {
+               (*context_release)(context_info);
+       }
+
+       return;
+}
+
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 static SCNetworkConnectionPrivateRef
-__SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef serviceID)
+__SCNetworkConnectionCreatePrivate(CFAllocatorRef              allocator,
+                                  CFStringRef                  serviceID,
+                                  SCNetworkConnectionCallBack  callout,
+                                  SCNetworkConnectionContext   *context)
 {
-       SCNetworkConnectionPrivateRef   connectionPrivate = 0;
+       boolean_t                       active;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = NULL;
+       void                            *data;
+       CFIndex                         dataLen;
+       CFDataRef                       dataRef                 = NULL;
+       char                            *envdebug;
+       int                             error                   = kSCStatusFailed;
+       CFMachPortContext               mach_context            = {0, NULL, NULL, NULL, NULL};
+       mach_port_t                     notify_port             = MACH_PORT_NULL;
+       mach_port_t                     port_old;
+       mach_port_t                     server;
        uint32_t                        size;
-       struct ppp_status               *stats = 0;
-       int                             error = kSCStatusFailed;
+       kern_return_t                   status;
+       mach_port_t                     unpriv_bootstrap_port;
 
        /* initialize runtime */
        pthread_once(&initialized, __SCNetworkConnectionInitialize);
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkConnectionCreatePrivate:"));
+       if ((bootstrap_status (bootstrap_port, PPPCONTROLLER_SERVER, &active) != BOOTSTRAP_SUCCESS) ||
+           (bootstrap_look_up(bootstrap_port, PPPCONTROLLER_SERVER, &server) != BOOTSTRAP_SUCCESS)) {
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("PPP Controller server not found"));
+               goto fail;
+       }
 
        /* allocate NetworkConnection */
        size = sizeof(SCNetworkConnectionPrivate) - sizeof(CFRuntimeBase);
-       connectionPrivate = (SCNetworkConnectionPrivateRef)_CFRuntimeCreateInstance(allocator, __kSCNetworkConnectionTypeID,size, NULL);
-       if (connectionPrivate == 0)
+       connectionPrivate = (SCNetworkConnectionPrivateRef)_CFRuntimeCreateInstance(allocator, __kSCNetworkConnectionTypeID, size, NULL);
+       if (connectionPrivate == NULL) {
                goto fail;
+       }
 
        /* zero the data structure */
        bzero(((u_char*)connectionPrivate)+sizeof(CFRuntimeBase), size);
@@ -202,30 +312,80 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef service
        /* save the serviceID */
        connectionPrivate->serviceID = CFStringCreateCopy(NULL, serviceID);
 
-       connectionPrivate->controlRef = -1;
-       connectionPrivate->eventRef = -1;
+       /* get the debug environment variable */
+       envdebug = getenv("PPPDebug");
+       if (envdebug) {
+               if (sscanf(envdebug, "%d", &connectionPrivate->debug) != 1)
+                       connectionPrivate->debug = 1; /* PPPDebug value is invalid, set debug to 1 */
+       }
+
+       if (callout != NULL) {
+               connectionPrivate->rlsFunction = callout;
+
+               mach_context.info = (void*)connectionPrivate;
+               connectionPrivate->notify_port = CFMachPortCreate(NULL, __SCNetworkConnectionCallBack, &mach_context, NULL);
+               if (connectionPrivate->notify_port == NULL) {
+                       goto fail;
+               }
 
-       if (PPPInit(&connectionPrivate->controlRef))
+               notify_port = CFMachPortGetPort(connectionPrivate->notify_port);
+               status = mach_port_request_notification(mach_task_self(),
+                                                       notify_port, MACH_NOTIFY_NO_SENDERS, 1,
+                                                       notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &port_old);
+               if (status != KERN_SUCCESS) {
+                       goto fail;
+               }
+       }
+
+       if (context) {
+               bcopy(context, &connectionPrivate->rlsContext, sizeof(SCNetworkConnectionContext));
+               if (context->retain != NULL) {
+                       connectionPrivate->rlsContext.info = (void *)(*context->retain)(context->info);
+               }
+       }
+
+       if (!_SCSerializeString(serviceID, &dataRef, &data, &dataLen)) {
                goto fail;
+       }
 
-       if (PPPStatus(connectionPrivate->controlRef, serviceID, 0, &stats)) {
-               error = kSCStatusInvalidArgument;       // XXX can't get status, invalid service id
+       status = bootstrap_unprivileged(bootstrap_port, &unpriv_bootstrap_port);
+       if (status != BOOTSTRAP_SUCCESS) {
                goto fail;
        }
 
-       CFAllocatorDeallocate(NULL, stats);
-       stats = 0;
+       status = pppcontroller_attach(server, data, dataLen, unpriv_bootstrap_port, notify_port,
+                                     &connectionPrivate->session_port, &error);
+
+       mach_port_deallocate(mach_task_self(), unpriv_bootstrap_port);
+       CFRelease(dataRef);
+       dataRef = NULL;
+
+       if (status != KERN_SUCCESS) {
+               goto fail;
+       }
+
+       if (error != kSCStatusOK) {
+               goto fail;
+       }
+
+       if (connectionPrivate->debug) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCreate (0x%x) succeeded for service ID: %@"), connectionPrivate, serviceID);
+       }
 
        /* success, return the connection reference */
        return connectionPrivate;
 
     fail:
 
+
        /* failure, clean up and leave */
-       if (connectionPrivate)
+       if (connectionPrivate != NULL) {
+               if (connectionPrivate->debug)
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCreate (0x%x) failed for service ID: %@"), connectionPrivate, serviceID);
                CFRelease(connectionPrivate);
-       if (stats)
-               CFAllocatorDeallocate(NULL, stats);
+       }
+
+       if (dataRef)            CFRelease(dataRef);
        _SCErrorSet(error);
        return NULL;
 }
@@ -234,53 +394,19 @@ __SCNetworkConnectionCreatePrivate(CFAllocatorRef allocator, CFStringRef service
 ------------------------------------------------------------------------------------------- */
 
 CFTypeID
-SCNetworkConnectionGetTypeID (void) {
+SCNetworkConnectionGetTypeID(void) {
        pthread_once(&initialized, __SCNetworkConnectionInitialize);    /* initialize runtime */
        return __kSCNetworkConnectionTypeID;
 }
 
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-static SCNetworkConnectionStatus
-__SCNetworkConnectionConvertStatus (int state)
-{
-       SCNetworkConnectionStatus       status = kSCNetworkConnectionDisconnected;
-
-       switch (state) {
-               case PPP_INITIALIZE:
-               case PPP_CONNECTLINK:
-               case PPP_ESTABLISH:
-               case PPP_AUTHENTICATE:
-               case PPP_CALLBACK:
-               case PPP_NETWORK:
-               case PPP_WAITONBUSY:
-                       status = kSCNetworkConnectionConnecting;
-                       break;
-               case PPP_TERMINATE:
-               case PPP_DISCONNECTLINK:
-               case PPP_HOLDOFF:
-                       status = kSCNetworkConnectionDisconnecting;
-                       break;
-               case PPP_RUNNING:
-               case PPP_ONHOLD:
-                       status = kSCNetworkConnectionConnected;
-                       break;
-               case PPP_IDLE:
-               case PPP_STATERESERVED:
-               default:
-                       status = kSCNetworkConnectionDisconnected;
-       }
-       return status;
-}
-
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 SCNetworkConnectionRef
-SCNetworkConnectionCreateWithServiceID (CFAllocatorRef                 allocator,
-                                       CFStringRef                     serviceID,
-                                       SCNetworkConnectionCallBack     callout,
-                                       SCNetworkConnectionContext      *context)
+SCNetworkConnectionCreateWithServiceID(CFAllocatorRef                  allocator,
+                                      CFStringRef                      serviceID,
+                                      SCNetworkConnectionCallBack      callout,
+                                      SCNetworkConnectionContext       *context)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate;
 
@@ -289,17 +415,7 @@ SCNetworkConnectionCreateWithServiceID (CFAllocatorRef                     allocator,
                return NULL;
        }
 
-       connectionPrivate = __SCNetworkConnectionCreatePrivate(allocator, serviceID);
-
-       if (connectionPrivate) {
-               connectionPrivate->rlsFunction = callout;
-               if (context) {
-                       bcopy(context, &connectionPrivate->rlsContext, sizeof(SCNetworkConnectionContext));
-                       if (context->retain) {
-                               connectionPrivate->rlsContext.info = (void *)context->retain(context->info);
-                       }
-               }
-       }
+       connectionPrivate = __SCNetworkConnectionCreatePrivate(allocator, serviceID, callout, context);
 
        return (SCNetworkConnectionRef)connectionPrivate;
 }
@@ -308,7 +424,7 @@ SCNetworkConnectionCreateWithServiceID (CFAllocatorRef                      allocator,
 ------------------------------------------------------------------------------------------- */
 
 CFStringRef
-SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyServiceID(SCNetworkConnectionRef connection)
 {
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -322,67 +438,40 @@ SCNetworkConnectionCopyServiceID (SCNetworkConnectionRef connection)
 ------------------------------------------------------------------------------------------- */
 
 CFDictionaryRef
-SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyStatistics(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       void                            *data                   = NULL;
+       int                             datalen;
        int                             error                   = kSCStatusFailed;
-       struct ppp_status               *stats                  = 0;
-       CFMutableDictionaryRef          dict                    = 0;
-       CFMutableDictionaryRef          statsdict               = 0;
-
-#define ADDNUMBER(d, k, n)                                     \
-{                                                              \
-       CFNumberRef num;                                        \
-       num = CFNumberCreate(NULL, kCFNumberSInt32Type, n);     \
-       if (num) {                                              \
-               CFDictionaryAddValue(d, k, num);                \
-               CFRelease(num);                                 \
-       }                                                       \
-}
+       CFPropertyListRef               statistics              = NULL;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return NULL;
        }
 
-       /* get status and check connected state */
-       if (PPPStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &stats))
-               goto fail;
-
-       if (__SCNetworkConnectionConvertStatus(stats->status) != kSCNetworkConnectionConnected)
+       status = pppcontroller_copystatistics(connectionPrivate->session_port, (xmlDataOut_t *)&data, &datalen, &error);
+       if (status != KERN_SUCCESS) {
                goto fail;
+       }
 
-       /* create dictionaries */
-       if ((statsdict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0)
+       if (error != kSCStatusOK) {
                goto fail;
+       }
 
-       if ((dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == 0)
+       if ((data == NULL) ||
+           !_SCUnserialize(&statistics, NULL, data, datalen) ||
+           !isA_CFDictionary(statistics)) {
                goto fail;
+       }
 
-       /* add statistics */
-       ADDNUMBER(dict, kSCNetworkConnectionBytesIn, &stats->s.run.inBytes);
-       ADDNUMBER(dict, kSCNetworkConnectionBytesOut, &stats->s.run.outBytes);
-       ADDNUMBER(dict, kSCNetworkConnectionPacketsIn, &stats->s.run.inPackets);
-       ADDNUMBER(dict, kSCNetworkConnectionPacketsOut, &stats->s.run.outPackets);
-       ADDNUMBER(dict, kSCNetworkConnectionErrorsIn, &stats->s.run.inErrors);
-       ADDNUMBER(dict, kSCNetworkConnectionErrorsOut, &stats->s.run.outErrors);
-
-       /* add the PPP dictionary to the statistics dictionary */
-       CFDictionaryAddValue(statsdict, kSCEntNetPPP, dict);
-       CFRelease(dict);
-
-       /* done */
-       CFAllocatorDeallocate(NULL, stats);
-       return statsdict;
+       return statistics;
 
     fail:
 
-       if (stats)
-               CFAllocatorDeallocate(NULL, stats);
-       if (dict)
-               CFRelease(dict);
-       if (statsdict)
-               CFRelease(statsdict);
+       if (statistics) CFRelease(statistics);
        _SCErrorSet(error);
        return NULL;
 }
@@ -391,59 +480,67 @@ SCNetworkConnectionCopyStatistics (SCNetworkConnectionRef connection)
 ------------------------------------------------------------------------------------------- */
 
 SCNetworkConnectionStatus
-SCNetworkConnectionGetStatus (SCNetworkConnectionRef connection)
+SCNetworkConnectionGetStatus(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
-       struct ppp_status               *stats                  = 0;
-       SCNetworkConnectionStatus       status;
+       int                             error                   = kSCStatusFailed;
+       int                             phase;
+       SCNetworkConnectionStatus       scstatus;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
-               return NULL;
+               return kSCNetworkConnectionInvalid;
        }
 
-       if (PPPStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &stats))
-               return kSCNetworkConnectionDisconnected; // XXX
-
-       status = __SCNetworkConnectionConvertStatus(stats->status);
+       status = pppcontroller_getstatus(connectionPrivate->session_port, &phase, &error);
+       if ((status != KERN_SUCCESS) || (error != kSCStatusOK)) {
+               return kSCNetworkConnectionDisconnected;
+       }
 
-       CFAllocatorDeallocate(NULL, stats);
-       return status;
+       scstatus = __SCNetworkConnectionConvertStatus(phase);
+       return scstatus;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
+
 CFDictionaryRef
-SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyExtendedStatus(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
-       CFPropertyListRef               status                  = 0;
-       void                            *data                   = 0;
-       u_int32_t                       datalen;
+       void                            *data                   = NULL;
+       int                             datalen;
+       int                             error                   = kSCStatusFailed;
+       CFPropertyListRef               extstatus               = NULL;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return NULL;
        }
 
-       if (PPPExtendedStatus(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &data, &datalen))
+       status = pppcontroller_copyextendedstatus(connectionPrivate->session_port, (xmlDataOut_t *)&data, &datalen, &error);
+       if (status != KERN_SUCCESS) {
                goto fail;
+       }
 
-       if (!data
-           || !(status = PPPUnserialize(data, datalen))
-           || !isA_CFDictionary(status))
+       if (error != kSCStatusOK) {
                goto fail;
+       }
 
-       CFAllocatorDeallocate(NULL, data);
-       return status;
+       if ((data == NULL) ||
+           !_SCUnserialize(&extstatus, NULL, data, datalen) ||
+           !isA_CFDictionary(extstatus)) {
+               goto fail;
+       }
+
+       return extstatus;
 
     fail:
 
-       _SCErrorSet(kSCStatusFailed);
-       if (status)
-               CFRelease(status);
-       if (data)
-               CFAllocatorDeallocate(NULL, data);
+       if (extstatus)  CFRelease(extstatus);
+       _SCErrorSet(error);
        return NULL;
 }
 
@@ -451,37 +548,97 @@ SCNetworkConnectionCopyExtendedStatus (SCNetworkConnectionRef connection)
 ------------------------------------------------------------------------------------------- */
 
 Boolean
-SCNetworkConnectionStart (SCNetworkConnectionRef       connection,
-                         CFDictionaryRef               userOptions,
-                         Boolean                       linger)
+SCNetworkConnectionStart(SCNetworkConnectionRef        connection,
+                        CFDictionaryRef        userOptions,
+                        Boolean                linger)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
-       CFDataRef                       dataref                 = 0;
-       void                            *data                   = 0;
-       u_int32_t                       datalen                 = 0;
+       CFDataRef                       dataref                 = NULL;
+       void                            *data                   = NULL;
+       CFIndex                         datalen                 = 0;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
-               return NULL;
+               return FALSE;
        }
 
-       if (userOptions && !(dataref = PPPSerialize(userOptions, &data, &datalen)))
+       if (connectionPrivate->debug) {
+               CFMutableDictionaryRef  mdict = NULL, mdict1;
+               CFDictionaryRef dict;
+
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStart (0x%x)"), connectionPrivate);
+
+               if (userOptions) {
+                       /* special code to remove secret information */
+                       mdict = CFDictionaryCreateMutableCopy(0, 0, userOptions);
+                       if (mdict) {
+                               dict = CFDictionaryGetValue(mdict, kSCEntNetPPP);
+                               if (isA_CFDictionary(dict)) {
+                                       mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict);
+                                       if (mdict1) {
+                                               CFDictionaryReplaceValue(mdict1, kSCPropNetPPPAuthPassword, CFSTR("******"));
+                                               CFDictionarySetValue(mdict, kSCEntNetPPP, mdict1);
+                                               CFRelease(mdict1);
+                                       }
+                               }
+
+                               dict = CFDictionaryGetValue(mdict, kSCEntNetL2TP);
+                               if (isA_CFDictionary(dict)) {
+                                       mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict);
+                                       if (mdict1) {
+                                               CFDictionaryReplaceValue(mdict1, kSCPropNetL2TPIPSecSharedSecret, CFSTR("******"));
+                                               CFDictionarySetValue(mdict, kSCEntNetL2TP, mdict1);
+                                               CFRelease(mdict1);
+                                       }
+                               }
+
+                               dict = CFDictionaryGetValue(mdict, kSCEntNetIPSec);
+                               if (isA_CFDictionary(dict)) {
+                                       mdict1 = CFDictionaryCreateMutableCopy(0, 0, dict);
+                                       if (mdict1) {
+                                               CFDictionaryReplaceValue(mdict1, kSCPropNetIPSecSharedSecret, CFSTR("******"));
+                                               CFDictionarySetValue(mdict, kSCEntNetIPSec, mdict1);
+                                               CFRelease(mdict1);
+                                       }
+                               }
+                       }
+               }
+
+               SCLog(TRUE, LOG_DEBUG, CFSTR("User options: %@"), mdict);
+               if (mdict)
+                       CFRelease(mdict);
+       }
+
+       if (userOptions && !_SCSerialize(userOptions, &dataref, &data, &datalen)) {
                goto fail;
+       }
 
-       if (PPPConnect(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, data, datalen, linger))
+       status = pppcontroller_start(connectionPrivate->session_port, data, datalen, linger, &error);
+       if (status != KERN_SUCCESS) {
                goto fail;
+       }
 
-       if (dataref)
+       if (dataref) {
                CFRelease(dataref);
+               dataref = NULL;
+       }
+
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStart (0x%x), return: %d"), connectionPrivate, error);
+
+       if (error != kSCStatusOK) {
+               goto fail;
+       }
 
        /* connection is now started */
        return TRUE;
 
     fail:
 
-       if (dataref)
-               CFRelease(dataref);
-       _SCErrorSet(kSCStatusFailed);   // XXX
+       if (dataref)    CFRelease(dataref);
+       _SCErrorSet(error);
        return FALSE;
 }
 
@@ -489,280 +646,214 @@ SCNetworkConnectionStart (SCNetworkConnectionRef        connection,
 ------------------------------------------------------------------------------------------- */
 
 Boolean
-SCNetworkConnectionStop (SCNetworkConnectionRef        connection,
-                        Boolean                forceDisconnect)
+SCNetworkConnectionStop(SCNetworkConnectionRef connection,
+                       Boolean                 forceDisconnect)
 {
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
        }
 
-       if (PPPDisconnect(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, forceDisconnect)) {
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStop (0x%x)"), connectionPrivate);
+
+       status = pppcontroller_stop(connectionPrivate->session_port, forceDisconnect, &error);
+       if (status != KERN_SUCCESS) {
+               goto fail;
+       }
+
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionStop (0x%x), return: %d"), connectionPrivate, error);
+
+       if (error != kSCStatusOK) {
+               goto fail;
        }
 
        /* connection is now disconnecting */
        return TRUE;
+
+    fail:
+
+       _SCErrorSet(error);
+       return FALSE;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 Boolean
-SCNetworkConnectionSuspend (SCNetworkConnectionRef connection)
+SCNetworkConnectionSuspend(SCNetworkConnectionRef connection)
 {
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
-               return NULL;
+               return FALSE;
        }
 
-       if (PPPSuspend(connectionPrivate->controlRef, connectionPrivate->serviceID, 0)) {
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionSuspend (0x%x)"), connectionPrivate);
+
+       status = pppcontroller_suspend(connectionPrivate->session_port, &error);
+       if (status != KERN_SUCCESS) {
+               goto fail;
+       }
+
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionSuspend (0x%x), return: %d"), connectionPrivate, error);
+
+       if (error != kSCStatusOK) {
+               goto fail;
        }
 
        /* connection is now suspended */
        return TRUE;
+
+    fail:
+
+       _SCErrorSet(error);
+       return FALSE;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 Boolean
-SCNetworkConnectionResume (SCNetworkConnectionRef connection)
+SCNetworkConnectionResume(SCNetworkConnectionRef connection)
 {
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
-               return NULL;
+               return FALSE;
        }
 
-       if (PPPResume(connectionPrivate->controlRef, connectionPrivate->serviceID, 0)) {
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionResume (0x%x)"), connectionPrivate);
+
+       status = pppcontroller_resume(connectionPrivate->session_port, &error);
+       if (status != KERN_SUCCESS) {
+               goto fail;
+       }
+
+       if (connectionPrivate->debug)
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionResume (0x%x), return: %d"), connectionPrivate, error);
+
+       if (error != kSCStatusOK) {
+               goto fail;
        }
 
        /* connection is now resume */
        return TRUE;
+
+    fail:
+
+       _SCErrorSet(error);
+       return FALSE;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
 CFDictionaryRef
-SCNetworkConnectionCopyUserOptions (SCNetworkConnectionRef connection)
+SCNetworkConnectionCopyUserOptions(SCNetworkConnectionRef connection)
 {
        SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
-       void                            *data                   = 0;
-       u_int32_t                       datalen;
-       CFPropertyListRef               userOptions             = 0;
+       void                            *data                   = NULL;
+       int                             datalen;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
+       CFPropertyListRef               userOptions             = NULL;
 
        if (!isA_SCNetworkConnection(connection)) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return NULL;
        }
 
-       if (PPPGetConnectData(connectionPrivate->controlRef, connectionPrivate->serviceID, 0, &data, &datalen))
+       status = pppcontroller_copyuseroptions(connectionPrivate->session_port, (xmlDataOut_t *)&data, &datalen, &error);
+       if (status != KERN_SUCCESS) {
                goto fail;
+       }
+
+       if (error != kSCStatusOK) {
+               goto fail;
+       }
 
        // no data were used, return an empty dictionary
-       if (data == 0) {
+       if (data == NULL) {
                CFDictionaryRef dict;
 
                dict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-               if (dict == 0)
+               if (dict == NULL) {
                        _SCErrorSet(kSCStatusFailed); // XXX
+               }
                return dict;
        }
 
-       userOptions = PPPUnserialize(data, datalen);
-       if (!isA_CFDictionary(userOptions))
+       if (!_SCUnserialize(&userOptions, NULL, data, datalen) ||
+           !isA_CFDictionary(userOptions)) {
                goto fail;
+       }
 
-       CFAllocatorDeallocate(NULL, data);
        return userOptions;
 
     fail:
 
-       _SCErrorSet(kSCStatusFailed);
-       if (userOptions)
-               CFRelease(userOptions);
-       if (data)
-               CFAllocatorDeallocate(NULL, data);
+       if (userOptions)        CFRelease(userOptions);
+       _SCErrorSet(error);
        return NULL;
 }
 
 /* -------------------------------------------------------------------------------------------
 ------------------------------------------------------------------------------------------- */
 
-static Boolean
-__isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
-       CFIndex i;
-       CFIndex n       = CFArrayGetCount(rlList);
-
-       for (i = 0; i < n; i += 3) {
-               if (obj         && !CFEqual(obj,         CFArrayGetValueAtIndex(rlList, i))) {
-                       continue;
-               }
-               if (runLoop     && !CFEqual(runLoop,     CFArrayGetValueAtIndex(rlList, i+1))) {
-                       continue;
-               }
-               if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
-                       continue;
-               }
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-static void
-__schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
-       CFArrayAppendValue(rlList, obj);
-       CFArrayAppendValue(rlList, runLoop);
-       CFArrayAppendValue(rlList, runLoopMode);
-
-       return;
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-static Boolean
-__unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
-{
-       CFIndex i       = 0;
-       Boolean found   = FALSE;
-       CFIndex n       = CFArrayGetCount(rlList);
-
-       while (i < n) {
-               if (obj         && !CFEqual(obj,         CFArrayGetValueAtIndex(rlList, i))) {
-                       i += 3;
-                       continue;
-               }
-               if (runLoop     && !CFEqual(runLoop,     CFArrayGetValueAtIndex(rlList, i+1))) {
-                       i += 3;
-                       continue;
-               }
-               if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
-                       i += 3;
-                       continue;
-               }
-
-               found = TRUE;
-
-               CFArrayRemoveValueAtIndex(rlList, i + 2);
-               CFArrayRemoveValueAtIndex(rlList, i + 1);
-               CFArrayRemoveValueAtIndex(rlList, i);
-
-               if (!all) {
-                       return found;
-               }
-
-               n -= 3;
-       }
-
-       return found;
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-
-static void
-__SCNetworkConnectionCallBack(CFSocketRef              inref,
-                             CFSocketCallBackType      type,
-                             CFDataRef                 address,
-                             const void                *data,
-                             void                      *info)
-{
-       void                            *context_info;
-       void                            (*context_release)(const void *);
-       SCNetworkConnectionRef          connection              = (SCNetworkConnectionRef)info;
-       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
-       SCNetworkConnectionCallBack     rlsFunction;
-       SCNetworkConnectionStatus       status;
-       int                             pppstatus;
-       int                             err;
-
-       err = PPPReadEvent(connectionPrivate->eventRef, &pppstatus);
-       if (err)
-               return;
-
-       rlsFunction = connectionPrivate->rlsFunction;
-       if (connectionPrivate->rlsContext.retain && connectionPrivate->rlsContext.info) {
-               context_info    = (void *)connectionPrivate->rlsContext.retain(connectionPrivate->rlsContext.info);
-               context_release = connectionPrivate->rlsContext.release;
-       }
-       else {
-               context_info    = connectionPrivate->rlsContext.info;
-               context_release = NULL;
-       }
-
-       status = __SCNetworkConnectionConvertStatus(pppstatus);
-
-       (*rlsFunction)(connection, status, context_info);
-       if (context_release && context_info) {
-               context_release(context_info);
-       }
-}
-
-/* -------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------- */
-
 Boolean
 SCNetworkConnectionScheduleWithRunLoop(SCNetworkConnectionRef  connection,
                                       CFRunLoopRef             runLoop,
                                       CFStringRef              runLoopMode)
 {
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
-       //CFSocketRef                   ref;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
        }
 
-       if (connectionPrivate->rlsFunction == 0) {
+       if (connectionPrivate->rlsFunction == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
        }
 
-       if (connectionPrivate->rlList
-           && __isScheduled(NULL, runLoop, runLoopMode, connectionPrivate->rlList)) {
+       if ((connectionPrivate->rlList != NULL) &&
+           _SC_isScheduled(NULL, runLoop, runLoopMode, connectionPrivate->rlList)) {
                /* already scheduled */
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
 
-       if (connectionPrivate->eventRef == -1) {
-               CFSocketContext context = { 0, (void*)connection, CFRetain, CFRelease, CFCopyDescription };
-
-               if (PPPInit(&connectionPrivate->eventRef)) {
-                       _SCErrorSet(kSCStatusFailed);
+       if (connectionPrivate->rlList == NULL) {
+               status = pppcontroller_notification(connectionPrivate->session_port, 1, &error);
+               if ((status != KERN_SUCCESS) || (error != kSCStatusOK)) {
+                       _SCErrorSet(error);
                        return FALSE;
                }
 
-               PPPEnableEvents(connectionPrivate->eventRef, connectionPrivate->serviceID, 0, 1);
-
-               connectionPrivate->eventRefCF = CFSocketCreateWithNative(NULL, connectionPrivate->eventRef,
-                                                                        kCFSocketReadCallBack, __SCNetworkConnectionCallBack, &context);
-               connectionPrivate->rls = CFSocketCreateRunLoopSource(NULL, connectionPrivate->eventRefCF, 0);
+               connectionPrivate->rls = CFMachPortCreateRunLoopSource(NULL, connectionPrivate->notify_port, 0);
                connectionPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-               //CFRelease(ref);
        }
 
        CFRunLoopAddSource(runLoop, connectionPrivate->rls, runLoopMode);
-       __schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList);
+       _SC_schedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList);
 
        return TRUE;
 }
@@ -775,15 +866,17 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef           connection,
                                         CFRunLoopRef                   runLoop,
                                         CFStringRef                    runLoopMode)
 {
-       SCNetworkConnectionPrivateRef   connectionPrivate = (SCNetworkConnectionPrivateRef)connection;
+       SCNetworkConnectionPrivateRef   connectionPrivate       = (SCNetworkConnectionPrivateRef)connection;
+       int                             error                   = kSCStatusFailed;
+       kern_return_t                   status;
 
        if (!isA_SCNetworkConnection(connection) || runLoop == NULL || runLoopMode == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return FALSE;
        }
 
-       if (connectionPrivate->rlList == NULL
-           || !__unschedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList, FALSE)) {
+       if ((connectionPrivate->rlList == NULL) ||
+           !_SC_unschedule(connectionPrivate, runLoop, runLoopMode, connectionPrivate->rlList, FALSE)) {
                /* if not currently scheduled */
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
@@ -796,11 +889,12 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef           connection,
                connectionPrivate->rls = NULL;
                CFRelease(connectionPrivate->rlList);
                connectionPrivate->rlList = NULL;
-               //PPPDispose(connectionPrivate->eventRef);
-               CFSocketInvalidate(connectionPrivate->eventRefCF);
-               CFRelease(connectionPrivate->eventRefCF);
-               connectionPrivate->eventRefCF = 0;
-               connectionPrivate->eventRef = -1;
+
+               status = pppcontroller_notification(connectionPrivate->session_port, 0, &error);
+               if ((status != KERN_SUCCESS) || (error != kSCStatusOK)) {
+                       _SCErrorSet(error);
+                       return FALSE;
+               }
        }
 
        return TRUE;
@@ -810,6 +904,7 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef             connection,
 //************************* USER LEVEL DIAL API **********************************
 
 
+#define k_NetworkConnect_Notification  "com.apple.networkConnect"
 #define k_NetworkConnect_Pref_File     CFSTR("com.apple.networkConnect")
 #define k_InterentConnect_Pref_File    CFSTR("com.apple.internetconnect")
 
@@ -822,58 +917,286 @@ SCNetworkConnectionUnscheduleFromRunLoop(SCNetworkConnectionRef          connection,
 static Boolean SCNetworkConnectionPrivateCopyDefaultServiceIDForDial   (SCDynamicStoreRef session, CFStringRef *serviceID);
 static Boolean SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore (SCDynamicStoreRef session, CFStringRef *serviceID);
 static Boolean SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptionsArray, CFDictionaryRef *userOptions);
-static Boolean SCNetworkConnectionPrivateIsPPPService                  (SCDynamicStoreRef session, CFStringRef serviceID);
-static void addPasswordFromKeychain(CFDictionaryRef *userOptions);
-static CFArrayRef copyKeychainEnumerator(CFStringRef uniqueIdentifier);
+static Boolean SCNetworkConnectionPrivateIsPPPService                  (SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2);
+static void addPasswordFromKeychain                                    (SCDynamicStoreRef session, CFStringRef serviceID, CFDictionaryRef *userOptions);
+static CFStringRef copyPasswordFromKeychain                            (CFStringRef uniqueID);
+static CFArrayRef copyKeychainEnumerator                               (CFStringRef uniqueIdentifier);
+
+static uint32_t notify_userprefs_token = -1;
+
+/*
+ *     return TRUE if domain1 ends with domain2, and will check for trailing "."
+ */
+static Boolean
+domainEndsWithDomain(CFStringRef domain1, CFStringRef domain2)
+{
+       CFRange         range;
+       Boolean         ret             = FALSE;
+       CFStringRef     s1              = NULL;
+       Boolean         s1_created      = FALSE;
+       CFStringRef     s2              = NULL;
+       Boolean         s2_created      = FALSE;
+
+       if (CFStringHasSuffix(domain1, CFSTR("."))) {
+               range.location = 0;
+               range.length = CFStringGetLength(domain1) - 1;
+               s1 = CFStringCreateWithSubstring(NULL, domain1, range);
+               if (s1 == NULL) {
+                       goto done;
+               }
+               s1_created = TRUE;
+       } else {
+               s1 = domain1;
+       }
+
+       if (CFStringHasSuffix(domain2, CFSTR("."))) {
+               range.location = 0;
+               range.length = CFStringGetLength(domain2) - 1;
+               s2 = CFStringCreateWithSubstring(NULL, domain2, range);
+               if (s2 == NULL) {
+                       goto done;
+               }
+               s2_created = TRUE;
+       } else {
+               s2 = domain2;
+       }
+
+       ret = CFStringHasSuffix(s1, s2);
+
+    done :
+
+       if (s1_created) CFRelease(s1);
+       if (s2_created) CFRelease(s2);
+       return ret;
+}
+
 
 Boolean
-SCNetworkConnectionCopyUserPreferences (CFDictionaryRef        selectionOptions,
-                                       CFStringRef     *serviceID,
-                                       CFDictionaryRef *userOptions)
+SCNetworkConnectionCopyUserPreferences(CFDictionaryRef selectionOptions,
+                                      CFStringRef      *serviceID,
+                                      CFDictionaryRef  *userOptions)
 {
-       SCDynamicStoreRef       session = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkConnection"), NULL, NULL);
-       Boolean                 success = FALSE;
+       int                     debug           = 0;
+       char                    *envdebug;
+       int                     prefsChanged;
+       SCDynamicStoreRef       session;
+       Boolean                 success         = FALSE;
+       int                     status;
+
+       envdebug = getenv("PPPDebug");
+       if (envdebug) {
+               if (sscanf(envdebug, "%d", &debug) != 1)
+                       debug = 1; /* PPPDebug value is invalid, set debug to 1 */
+       }
+
+       if (notify_userprefs_token == -1) {
+               status = notify_register_check(k_NetworkConnect_Notification, &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
 
-       if (session != NULL) {
-               // (1) Figure out which service ID we care about, allocate it into passed "serviceID"
-               success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(session, serviceID);
-
-               if (success && (*serviceID != NULL)) {
-                       // (2) Get the list of user data for this service ID
-                       CFPropertyListRef userServices = CFPreferencesCopyValue(*serviceID,
-                                                                               k_NetworkConnect_Pref_File,
-                                                                               kCFPreferencesCurrentUser,
-                                                                               kCFPreferencesCurrentHost);
-
-                       // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't
-                       if (userServices != NULL) {
-                               if (isA_CFArray(userServices)) {
-                                       // (4) Get the default set of user options for this service
-                                       success =  SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(
-                                                                         (CFArrayRef)userServices,
-                                                                       userOptions);
-                                       if(success && userOptions != NULL)
-                                       {
-                                           addPasswordFromKeychain(userOptions);
+       *serviceID = NULL;
+       *userOptions = NULL;
+
+       session = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkConnection"), NULL, NULL);
+       if (session == NULL) {
+               fprintf(stderr, "Error,  SCNetworkConnectionCopyUserPreferences, SCDynamicStoreCreate() returned NULL!\n");
+               return FALSE;
+       }
+
+       if (selectionOptions) {
+               Boolean         catchAllFound   = FALSE;
+               CFIndex         catchAllService = 0;
+               CFIndex         catchAllConfig  = 0;
+               CFStringRef     hostName        = NULL;
+               CFStringRef     priority        = NULL;
+               CFArrayRef      serviceNames    = NULL;
+               CFDictionaryRef services        = NULL;
+               CFIndex         serviceIndex;
+               CFIndex         servicesCount;
+
+               hostName = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandHostName);
+               if (!isA_CFString(hostName))
+                       hostName = NULL;
+
+               // can't select anything
+               if (hostName == NULL)
+                       goto done_selection;
+
+               priority = CFDictionaryGetValue(selectionOptions, kSCPropNetPPPOnDemandPriority);
+               if (!isA_CFString(priority))
+                       priority = kSCValNetPPPOnDemandPriorityDefault;
+
+
+               if (!isA_CFArray(serviceNames))
+                       goto done_selection;
+
+
+               if (!isA_CFDictionary(services))
+                       goto done_selection;
+
+               servicesCount = CFArrayGetCount(serviceNames);
+               for (serviceIndex = 0; serviceIndex < servicesCount; serviceIndex++) {
+                       CFIndex         configIndex;
+                       CFIndex         configsCount;
+                       CFArrayRef      serviceConfigs;
+                       CFStringRef     serviceName;
+                       int             val;
+
+                       serviceName = CFArrayGetValueAtIndex(serviceNames, serviceIndex);
+                       if (!isA_CFString(serviceName))
+                               continue;
+
+                       serviceConfigs = CFDictionaryGetValue(services, serviceName);
+                       if (!isA_CFArray(serviceConfigs))
+                               continue;
+
+                       configsCount = CFArrayGetCount(serviceConfigs);
+                       for (configIndex = 0; configIndex < configsCount; configIndex++) {
+                               CFNumberRef     autodial;
+                               CFDictionaryRef config;
+                               CFDictionaryRef pppConfig;
+
+                               config = CFArrayGetValueAtIndex(serviceConfigs, configIndex);
+                               if (!isA_CFDictionary(config))
+                                       continue;
+
+                               pppConfig = CFDictionaryGetValue(config, kSCEntNetPPP);
+                               if (!isA_CFDictionary(pppConfig))
+                                       continue;
+
+                               autodial = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandEnabled);
+                               if (!isA_CFNumber(autodial))
+                                       continue;
+
+                               CFNumberGetValue(autodial, kCFNumberIntType, &val);
+                               if (val) {
+                                       CFArrayRef      autoDomains;
+                                       CFIndex         domainIndex;
+                                       CFIndex         domainsCount;
+
+                                       /* we found an conditional connection enabled configuration */
+
+                                       /* check domain */
+                                       autoDomains = CFDictionaryGetValue(pppConfig, kSCPropNetPPPOnDemandDomains);
+                                       if (!isA_CFArray(autoDomains))
+                                               continue;
+
+                                       domainsCount = CFArrayGetCount(autoDomains);
+                                       for (domainIndex = 0; domainIndex < domainsCount; domainIndex++) {
+                                               CFStringRef     domain;
+
+                                               domain = CFArrayGetValueAtIndex(autoDomains, domainIndex);
+                                               if (!isA_CFString(domain))
+                                                       continue;
+
+                                               if (!catchAllFound &&
+                                                   (CFStringCompare(domain, CFSTR(""), 0) == kCFCompareEqualTo
+                                                       || CFStringCompare(domain, CFSTR("."), 0) == kCFCompareEqualTo)) {
+                                                       // found a catch all
+                                                       catchAllFound = TRUE;
+                                                       catchAllService = serviceIndex;
+                                                       catchAllConfig = configIndex;
+                                               }
+
+                                               if (domainEndsWithDomain(hostName, domain)) {
+                                                       // found matching configuration
+                                                       *serviceID = serviceName;
+                                                       CFRetain(*serviceID);
+                                                       *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
+                                                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandHostName, hostName);
+                                                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
+                                                       addPasswordFromKeychain(session, *serviceID, userOptions);
+                                                       success = TRUE;
+                                                       goto done_selection;
+                                               }
                                        }
-                               } else {
-                                       fprintf(stderr, "Error, userServices are not of type CFArray!\n");
                                }
-
-                               CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL
                        }
                }
 
+               // config not found, do we have a catchall ?
+               if (catchAllFound) {
+                       CFDictionaryRef config;
+                       CFArrayRef      serviceConfigs;
+                       CFStringRef     serviceName;
+
+                       serviceName = CFArrayGetValueAtIndex(serviceNames, catchAllService);
+                       serviceConfigs = CFDictionaryGetValue(services, serviceName);
+                       config = CFArrayGetValueAtIndex(serviceConfigs, catchAllConfig);
+
+                       *serviceID = serviceName;
+                       CFRetain(*serviceID);
+                       *userOptions = CFDictionaryCreateMutableCopy(NULL, 0, config);
+                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandHostName, hostName);
+                       CFDictionarySetValue((CFMutableDictionaryRef)*userOptions, kSCPropNetPPPOnDemandPriority, priority);
+                       addPasswordFromKeychain(session, *serviceID, userOptions);
+                       success = TRUE;
+                       goto done_selection;
+               }
+
+           done_selection:
+
+               if (serviceNames)
+                       CFRelease(serviceNames);
+               if (services)
+                       CFRelease(services);
                CFRelease(session);
-       } else {
-               fprintf(stderr, "Error,  SCNetworkConnectionCopyUserPreferences, SCDynamicStoreCreate() returned NULL!\n");
+
+               if (debug > 1) {
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@"), success ? CFSTR("succeeded") : CFSTR("failed"));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("Selection options: %@"), selectionOptions);
+               }
+
+               return success;
        }
 
+       /* we don't have selection options */
+
+       // (1) Figure out which service ID we care about, allocate it into passed "serviceID"
+       success = SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(session, serviceID);
+
+       if (success && (*serviceID != NULL)) {
+               // (2) Get the list of user data for this service ID
+               CFPropertyListRef       userServices    = NULL;
+
+
+               // (3) We are expecting an array if the user has defined records for this service ID or NULL if the user hasn't
+               if (userServices != NULL) {
+                       if (isA_CFArray(userServices)) {
+                               // (4) Get the default set of user options for this service
+                               success = SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray((CFArrayRef)userServices,
+                                                                                                   userOptions);
+                               if(success && (userOptions != NULL)) {
+                                       addPasswordFromKeychain(session, *serviceID, userOptions);
+                               }
+                       } else {
+                               fprintf(stderr, "Error, userServices are not of type CFArray!\n");
+                       }
+
+                       CFRelease(userServices); // this is OK because SCNetworkConnectionPrivateISExpectedCFType() checks for NULL
+               }
+       }
+
+       if (debug > 1) {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("SCNetworkConnectionCopyUserPreferences %@, no selection options"), success ? CFSTR("succeeded") : CFSTR("failed"));
+       }
+
+       CFRelease(session);
        return success;
 }
 
+
 //*******************************************************************************************
 // SCNetworkConnectionPrivateCopyDefaultServiceIDForDial
 // ----------------------------------------------------
@@ -887,19 +1210,11 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
        Boolean                 foundService            = FALSE;
        CFPropertyListRef       lastServiceSelectedInIC = NULL;
 
-       // NULL out the pointer
-       *serviceID = NULL;
-
-       // read out the last service from the Internet Connect preference file
-       lastServiceSelectedInIC = CFPreferencesCopyValue(k_Last_Service_Id_Key,
-                                                        k_InterentConnect_Pref_File,
-                                                        kCFPreferencesCurrentUser,
-                                                        kCFPreferencesAnyHost);
 
        // we found the service the user last had open in IC
        if (lastServiceSelectedInIC != NULL) {
                // make sure its a PPP service
-               if (SCNetworkConnectionPrivateIsPPPService(session, lastServiceSelectedInIC)) {
+               if (SCNetworkConnectionPrivateIsPPPService(session, lastServiceSelectedInIC, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
                        // make sure the service that we found is valid
                        CFDictionaryRef dict;
                        CFStringRef     key;
@@ -910,10 +1225,10 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
                                                                          kSCEntNetInterface);
                        dict = SCDynamicStoreCopyValue(session, key);
                        CFRelease(key);
-                       if (dict) {
+                       if (dict != NULL) {
+                               CFRelease(dict);
                                *serviceID = CFRetain(lastServiceSelectedInIC);
                                foundService = TRUE;
-                               CFRelease(dict);
                        }
                }
                CFRelease(lastServiceSelectedInIC);
@@ -934,10 +1249,10 @@ SCNetworkConnectionPrivateCopyDefaultServiceIDForDial(SCDynamicStoreRef session,
 static Boolean
 SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef session, CFStringRef *serviceID)
 {
-       Boolean         success         = FALSE;
-       CFStringRef     key             = NULL;
        CFDictionaryRef dict            = NULL;
+       CFStringRef     key             = NULL;
        CFArrayRef      serviceIDs      = NULL;
+       Boolean         success         = FALSE;
 
        *serviceID = NULL;
 
@@ -952,17 +1267,14 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                }
 
                dict = SCDynamicStoreCopyValue(session, key);
-               if (dict == NULL) {
-                       fprintf(stderr, "Error, Dictionary for setup key == NULL!\n");
+               if (!isA_CFDictionary(dict)) {
+                       fprintf(stderr, "no global IPv4 entity\n");
                        break;
                }
 
                serviceIDs = CFDictionaryGetValue(dict, kSCPropNetServiceOrder); // array of service id's
-               if (isA_CFArray(serviceIDs) == NULL) {
-                       if (serviceIDs == NULL)
-                               fprintf(stderr, "Error, Array of service IDs == NULL!\n");
-                       else
-                               fprintf(stderr, "Error, serviceIds are not of type CFArray!\n");
+               if (!isA_CFArray(serviceIDs)) {
+                       fprintf(stderr, "service order not specified\n");
                        break;
                }
 
@@ -970,7 +1282,7 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                for (i = 0; i < count; i++) {
                        CFStringRef service = CFArrayGetValueAtIndex(serviceIDs, i);
 
-                       if (SCNetworkConnectionPrivateIsPPPService(session, service)) {
+                       if (SCNetworkConnectionPrivateIsPPPService(session, service, kSCValNetInterfaceSubTypePPPSerial, kSCValNetInterfaceSubTypePPPoE)) {
                                *serviceID = CFRetain(service);
                                success = TRUE;
                                break;
@@ -978,11 +1290,8 @@ SCNetworkConnectionPrivateGetPPPServiceFromDynamicStore(SCDynamicStoreRef sessio
                }
        } while (FALSE);
 
-       if (key != NULL)
-               CFRelease(key);
-
-       if (dict != NULL)
-               CFRelease(dict);
+       if (key != NULL)        CFRelease(key);
+       if (dict != NULL)       CFRelease(dict);
 
        return success;
 }
@@ -998,16 +1307,15 @@ SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptions
        CFIndex count   = CFArrayGetCount(userOptionsArray);
        int     i;
 
-       *userOptions = NULL;
-
        for (i = 0; i < count; i++) {
                // (1) Find the dictionary
                CFPropertyListRef propertyList = CFArrayGetValueAtIndex(userOptionsArray, i);
 
                if (isA_CFDictionary(propertyList) != NULL) {
                        // See if there's a value for dial on demand
-                       CFPropertyListRef value = CFDictionaryGetValue((CFDictionaryRef)propertyList,
-                                                                      k_Dial_Default_Key);
+                       CFPropertyListRef value;
+
+                       value = CFDictionaryGetValue((CFDictionaryRef)propertyList, k_Dial_Default_Key);
                        if (isA_CFBoolean(value) != NULL) {
                                if (CFBooleanGetValue(value)) {
                                        // we found the default user options
@@ -1023,78 +1331,164 @@ SCNetworkConnectionPrivateCopyDefaultUserOptionsFromArray(CFArrayRef userOptions
 }
 
 //********************************************************************************
-// SCNetworkConnectionPrivateIsPPPService
+// SCNetworkConnectionPrivateIsServiceType
 // --------------------------------------
-// Check and see if the service is a PPP service
+// Check and see if the service is a PPP service of the given types
 //********************************************************************************
 static Boolean
-SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID)
+SCNetworkConnectionPrivateIsPPPService(SCDynamicStoreRef session, CFStringRef serviceID, CFStringRef subType1, CFStringRef subType2)
 {
        CFStringRef     entityKey;
-       Boolean         isPPPService    = FALSE;
-       Boolean         isModemOrPPPoE  = FALSE;
+       Boolean         isPPPService            = FALSE;
+       Boolean         isMatchingSubType       = FALSE;
+       CFDictionaryRef serviceDict;
 
        entityKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                                kSCDynamicStoreDomainSetup,
                                                                serviceID,
                                                                kSCEntNetInterface);
-       if (entityKey != NULL) {
-               CFDictionaryRef serviceDict;
-
-               serviceDict = SCDynamicStoreCopyValue(session, entityKey);
-               if (serviceDict != NULL) {
-                       if (isA_CFDictionary(serviceDict)) {
-                               CFStringRef     type;
-                               CFStringRef     subtype;
-
-                               type = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceType);
-                               if (isA_CFString(type)) {
-                                       isPPPService = CFEqual(type, kSCValNetInterfaceTypePPP);
-                               }
+       if (entityKey == NULL) {
+               return FALSE;
+       }
 
-                               subtype = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceSubType);
-                               if (isA_CFString(subtype)) {
-                                       isModemOrPPPoE = (CFEqual(subtype, kSCValNetInterfaceSubTypePPPSerial) ||
-                                                         CFEqual(subtype, kSCValNetInterfaceSubTypePPPoE));
-                               }
+       serviceDict = SCDynamicStoreCopyValue(session, entityKey);
+       if (serviceDict != NULL) {
+               if (isA_CFDictionary(serviceDict)) {
+                       CFStringRef     type;
+                       CFStringRef     subtype;
+
+                       type = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceType);
+                       if (isA_CFString(type)) {
+                               isPPPService = CFEqual(type, kSCValNetInterfaceTypePPP);
+                       }
+
+                       subtype = CFDictionaryGetValue(serviceDict, kSCPropNetInterfaceSubType);
+                       if (isA_CFString(subtype)) {
+                               isMatchingSubType = CFEqual(subtype, subType1);
+                               if (!isMatchingSubType && subType2)
+                                       isMatchingSubType = CFEqual(subtype, subType2);
                        }
-                       CFRelease(serviceDict);
                }
-               CFRelease(entityKey);
+               CFRelease(serviceDict);
        }
+       CFRelease(entityKey);
 
-       return (isPPPService && isModemOrPPPoE);
+       return (isPPPService && isMatchingSubType);
 }
 
 //********************************************************************************
 // addPasswordFromKeychain
 // --------------------------------------
-// Get the password out of the keychain and add it to the PPP dictionary
+// Get the password and shared secret out of the keychain and add
+// them to the PPP and IPSec dictionaries
 //********************************************************************************
 static void
-addPasswordFromKeychain(CFDictionaryRef *userOptions)
+addPasswordFromKeychain(SCDynamicStoreRef session, CFStringRef serviceID, CFDictionaryRef *userOptions)
 {
-       CFArrayRef              enumerator;
-       CFIndex                 n;
-       CFDictionaryRef         oldDict;
-       CFPropertyListRef       uniqueID        = NULL;
+       CFPropertyListRef       uniqueID;
+       CFStringRef             password;
+       CFStringRef             sharedsecret    = NULL;
+
+       /* user options must exist */
+       if (*userOptions == NULL)
+               return;
 
-       oldDict = *userOptions;
-       if(oldDict == NULL) {
-               return;         // if no userOptions
+       /* first, get the unique identifier used to store passwords in the keychain */
+       uniqueID = CFDictionaryGetValue(*userOptions, k_Unique_Id_Key);
+       if (!isA_CFString(uniqueID))
+               return;
+
+       /* first, get the PPP password */
+       password = copyPasswordFromKeychain(uniqueID);
+
+       /* then, if necessary, get the IPSec Shared Secret */
+       if (SCNetworkConnectionPrivateIsPPPService(session, serviceID, kSCValNetInterfaceSubTypeL2TP, 0)) {
+               CFMutableStringRef      uniqueIDSS;
+
+               uniqueIDSS = CFStringCreateMutableCopy(NULL, 0, uniqueID);
+               CFStringAppend(uniqueIDSS, CFSTR(".SS"));
+               sharedsecret = copyPasswordFromKeychain(uniqueIDSS);
+               CFRelease(uniqueIDSS);
        }
 
-       uniqueID = CFDictionaryGetValue(oldDict, k_Unique_Id_Key);
-       if(!isA_CFString(uniqueID)) {
-               return;         // if no unique ID
+       /* did we find our information in the key chain ? */
+       if ((password != NULL) || (sharedsecret != NULL)) {
+               CFMutableDictionaryRef  newOptions;
+
+               newOptions = CFDictionaryCreateMutableCopy(NULL, 0, *userOptions);
+
+               /* PPP password */
+               if (password != NULL) {
+                       CFDictionaryRef         entity;
+                       CFMutableDictionaryRef  newEntity;
+
+                       entity = CFDictionaryGetValue(*userOptions, kSCEntNetPPP);
+                       if (isA_CFDictionary(entity))
+                               newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+                       else
+                               newEntity = CFDictionaryCreateMutable(NULL,
+                                                                     0,
+                                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                                     &kCFTypeDictionaryValueCallBacks);
+
+
+                       /* set the PPP password */
+                       CFDictionarySetValue(newEntity, kSCPropNetPPPAuthPassword, password);
+                       CFRelease(password);
+
+                       /* update the PPP entity */
+                       CFDictionarySetValue(newOptions, kSCEntNetPPP, newEntity);
+                       CFRelease(newEntity);
+               }
+
+               /* IPSec Shared Secret */
+               if (sharedsecret != NULL) {
+                       CFDictionaryRef         entity;
+                       CFMutableDictionaryRef  newEntity;
+
+                       entity = CFDictionaryGetValue(*userOptions, kSCEntNetIPSec);
+                       if (isA_CFDictionary(entity))
+                               newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity);
+                       else
+                               newEntity = CFDictionaryCreateMutable(NULL,
+                                                                     0,
+                                                                     &kCFTypeDictionaryKeyCallBacks,
+                                                                     &kCFTypeDictionaryValueCallBacks);
+
+                       /* set the IPSec Shared Secret */
+                       CFDictionarySetValue(newEntity, kSCPropNetIPSecSharedSecret, sharedsecret);
+                       CFRelease(sharedsecret);
+
+                       /* update the IPSec entity */
+                       CFDictionarySetValue(newOptions, kSCEntNetIPSec, newEntity);
+                       CFRelease(newEntity);
+               }
+
+               /* update the userOptions dictionary */
+               CFRelease(*userOptions);
+               *userOptions = CFDictionaryCreateCopy(NULL, newOptions);
+               CFRelease(newOptions);
        }
 
+}
+
+//********************************************************************************
+// copyPasswordFromKeychain
+// --------------------------------------
+// Given a uniqueID, retrieve the password from the keychain
+//********************************************************************************
+static CFStringRef
+copyPasswordFromKeychain(CFStringRef uniqueID)
+{
+       CFArrayRef      enumerator;
+       CFIndex         n;
+       CFStringRef     password = NULL;
+
        enumerator = copyKeychainEnumerator(uniqueID);
-       if(enumerator == NULL) {
-               return;         // if no keychain enumerator
+       if (enumerator == NULL) {
+               return NULL;            // if no keychain enumerator
        }
 
-
        n = CFArrayGetCount(enumerator);
        if (n > 0) {
                void                    *data   = NULL;
@@ -1108,44 +1502,14 @@ addPasswordFromKeychain(CFDictionaryRef *userOptions)
                                                    NULL,               // attrList
                                                    &dataLen,           // length
                                                    (void *)&data);     // outData
-               if(result == noErr && data != NULL && dataLen > 0) {
-                       CFStringRef             pass;
-
-                       pass = CFStringCreateWithBytes(NULL, data, dataLen, kCFStringEncodingUTF8, TRUE);
-                       if (pass) {
-                               CFMutableDictionaryRef  newDict;
-                               CFMutableDictionaryRef  newPPP;
-                               CFDictionaryRef         pppDict;
-
-                               newDict = CFDictionaryCreateMutableCopy(NULL, 0, oldDict);
-                               pppDict = CFDictionaryGetValue(newDict, kSCEntNetPPP);
-                               if (isA_CFDictionary(pppDict)) {
-                                       newPPP = CFDictionaryCreateMutableCopy(NULL, 0, pppDict);
-                               } else {
-                                       newPPP = CFDictionaryCreateMutable(NULL,
-                                                                          0,
-                                                                          &kCFTypeDictionaryKeyCallBacks,
-                                                                          &kCFTypeDictionaryValueCallBacks);
-                               }
-
-                               // set the PPP password
-                               CFDictionarySetValue(newPPP, kSCPropNetPPPAuthPassword, pass);
-                               CFRelease(pass);
-
-                               // update the PPP entity
-                               CFDictionarySetValue(newDict, kSCEntNetPPP, newPPP);
-                               CFRelease(newPPP);
-
-                               // update the userOptions dictionary
-                               CFRelease(oldDict);
-                               *userOptions = CFDictionaryCreateCopy(NULL, newDict);
-                               CFRelease(newDict);
-                       }
+               if ((result == noErr) && (data != NULL) && (dataLen > 0)) {
+                       password = CFStringCreateWithBytes(NULL, data, dataLen, kCFStringEncodingUTF8, TRUE);
                }
        }
 
        CFRelease(enumerator);
-       return;
+
+       return password;
 }
 
 //********************************************************************************
@@ -1156,7 +1520,7 @@ addPasswordFromKeychain(CFDictionaryRef *userOptions)
 static CFArrayRef
 copyKeychainEnumerator(CFStringRef uniqueIdentifier)
 {
-       char                    *buf            = NULL;
+       char                    *buf;
        CFMutableArrayRef       itemArray       = NULL;
        OSStatus                result;
        SecKeychainSearchRef    search          = NULL;
index 74a70d1a498a6a35d8c8346b2b8904899f6570a7..148e3dd186ae269b3aebab81d2b85fa6717a9ae6 100644 (file)
 
 /*!
        @header SCNetworkConnection
-       The SCNetworkConnectionXXX() APIs allow an application to
-       control connection oriented services defined in the system.
+       @discussion The SCNetworkConnection API contains functions that allow
+               an application to control connection-oriented services defined
+               in the system and get connection-status information.
 
-       This is a set of control APIs only. Using these APIs, an
-       application will be able to control existing services.
-       To create, change, or remove services, SCPreferences APIs
-       must be used.
+               The functions in the SCNetworkConnection API allow you to
+               control and get information about existing services only.
+               If you need to create, change, or remove services, you
+               should use the SCNetworkConfiguration API instead.
 
-       Note: Currently only PPP services can be controlled.
+               Note: Currently, only PPP services can be controlled.
  */
 
 
 /*!
        @typedef SCNetworkConnectionRef
-       @discussion This is the handle to manage a connection oriented service.
+       @discussion This is the handle to manage a connection-oriented service.
  */
-typedef const struct __SCNetworkConnection * SCNetworkConnectionRef    AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef const struct __SCNetworkConnection * SCNetworkConnectionRef;
 
 
 /*!
        @typedef SCNetworkConnectionContext
+       @discussion Structure containing user-specified data and callbacks
+               for a SCNetworkConnection.
+       @field version The version number of the structure type being passed
+               in as a parameter to the SCNetworkConnectionCreateWithServiceID
+               function.  This structure is version 0.
+       @field info A C pointer to a user-specified block of data.
+       @field retain The callback used to add a retain for the info field.
+               If this parameter is not a pointer to a function of the correct
+               prototype, the behavior is undefined.  The value may be NULL.
+       @field release The calllback used to remove a retain previously added
+               for the info field.  If this parameter is not a pointer to a
+               function of the correct prototype, the behavior is undefined.
+               The value may be NULL.
+       @field copyDescription The callback used to provide a description of
+               the info field.
  */
 typedef struct {
        CFIndex         version;
@@ -62,7 +78,7 @@ typedef struct {
        const void      *(*retain)(const void *info);
        void            (*release)(const void *info);
        CFStringRef     (*copyDescription)(const void *info);
-} SCNetworkConnectionContext                                           AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+} SCNetworkConnectionContext;
 
 
 
@@ -73,19 +89,14 @@ typedef struct {
                An extended status, specific to the type of network
                connection is also available for applications that
                need additonal information.
-
        @constant kSCNetworkConnectionInvalid
                The network connection refers to an invalid service.
-
        @constant kSCNetworkConnectionDisconnected
                The network connection is disconnected.
-
        @constant kSCNetworkConnectionConnecting
                The network connection is connecting.
-
        @constant kSCNetworkConnectionConnected
                The network connection is connected.
-
        @constant kSCNetworkConnectionDisconnecting
                The network connection is disconnecting.
  */
@@ -96,57 +107,50 @@ enum {
        kSCNetworkConnectionConnected           =  2,
        kSCNetworkConnectionDisconnecting       =  3
 };
-typedef int32_t SCNetworkConnectionStatus                              AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef int32_t SCNetworkConnectionStatus;
 
 
 /*!
        @enum SCNetworkConnectionPPPStatus
-       @discussion PPP specific status of the network connection.
-               This status is PPP specific and returned as part of the extended information
+       @discussion PPP-specific status of the network connection.
+               This status is returned as part of the extended information
                for a PPP service.
-               Note: additional status might be returned in the future, and the application should
-               be prepared to receive an unknown value.
-
+               Note: additional status might be returned in the future.
+               Your application should be prepared to receive an unknown value.
        @constant kSCNetworkConnectionPPPDisconnected
                PPP is disconnected.
-
        @constant kSCNetworkConnectionPPPInitializing
                PPP is initializing.
-
        @constant kSCNetworkConnectionPPPConnectingLink
-               PPP is connecting the lower connection layer (for example, the modem is dialing out).
-
+               PPP is connecting the lower connection layer (for example,
+               the modem is dialing out).
        @constant kSCNetworkConnectionPPPDialOnTraffic
-               PPP is waiting for networking traffic to automatically establish the connection.
-
+               PPP is waiting for networking traffic to automatically
+               establish the connection.
        @constant kSCNetworkConnectionPPPNegotiatingLink
-               PPP lower layer is connected and PPP is negotiating the link layer (LCP protocol).
-
+               The PPP lower layer is connected and PPP is negotiating the
+               link layer (LCP protocol).
        @constant kSCNetworkConnectionPPPAuthenticating
-               PPP is authenticating to the server (PAP, CHAP, MS-CHAP or EAP protocols).
-
+               PPP is authenticating to the server (PAP, CHAP, MS-CHAP or
+               EAP protocols).
        @constant kSCNetworkConnectionPPPWaitingForCallBack
-               PPP is waiting for server to call back.
-
+               PPP is waiting for the server to call back.
        @constant kSCNetworkConnectionPPPNegotiatingNetwork
-               PPP is now authenticated and negotiating the networking layer (IPCP or IPv6CP protocols)
-
+               PPP is now authenticated and negotiating the networking
+               layer (IPCP or IPv6CP protocols)
        @constant kSCNetworkConnectionPPPConnected
-               PPP is now fully connected for at least one of the networking layer.
+               PPP is now fully connected for at least one networking layer.
                Additional networking protocol might still be negotiating.
-
        @constant kSCNetworkConnectionPPPTerminating
                PPP networking and link protocols are terminating.
-
        @constant kSCNetworkConnectionPPPDisconnectingLink
-               PPP is disconnecting the lower level (for example, the modem is hanging up).
-
+               PPP is disconnecting the lower level (for example, the modem
+               is hanging up).
        @constant kSCNetworkConnectionPPPHoldingLinkOff
                PPP is disconnected and maintaining the link temporarily off.
-
        @constant kSCNetworkConnectionPPPSuspended
-               PPP is suspended as a result of the suspend command (for example, when a V92 Modem is On Hold).
-
+               PPP is suspended as a result of the suspend command (for
+               example, when a V.92 Modem is On Hold).
        @constant kSCNetworkConnectionPPPWaitingForRedial
                PPP has found a busy server and is waiting for redial.
  */
@@ -166,7 +170,7 @@ enum {
        kSCNetworkConnectionPPPSuspended                =  12,
        kSCNetworkConnectionPPPWaitingForRedial         =  13
 };
-typedef int32_t SCNetworkConnectionPPPStatus                           AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef int32_t SCNetworkConnectionPPPStatus;
 
 
 /*!
@@ -175,13 +179,13 @@ typedef int32_t SCNetworkConnectionPPPStatus                              AVAILABLE_MAC_OS_X_VERSION_10_3_
                status event is delivered.
        @param status The connection status.
        @param connection The connection reference.
-       @param info ....
+       @param info Application-specific information.
  */
 typedef void (*SCNetworkConnectionCallBack)    (
                                                SCNetworkConnectionRef          connection,
                                                SCNetworkConnectionStatus       status,
                                                void                            *info
-                                               )                       AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+                                               );
 
 
 
@@ -200,24 +204,28 @@ typedef void (*SCNetworkConnectionCallBack)       (
 __BEGIN_DECLS
 
 /*!
-       @function SCDynamicStoreGetTypeID
-       Returns the type identifier of all SCNetworkConnection instances.
+       @function SCNetworkConnectionGetTypeID
+       @discussion Returns the type identifier of all SCNetworkConnection
+               instances.
  */
 CF_EXPORT
 CFTypeID SCNetworkConnectionGetTypeID          (void)                  AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
 
 
 /*!
-    @function SCNetworkConnectionCopyUserPreferences
-       @discussion Provides the default serviceID and a userOptions dictionary for the connection.
-               Applications can use the serviceID and userOptions returned to open a connection on the fly.
-       @param selectionOptions Currently unimplemented. Pass NULL for this version.
-       @param serviceID Reference to the default serviceID for starting connections,
-               this value will be returned by the function.
-       @param userOptions Reference to default userOptions for starting connections,
-               this will be returned by the function.
-       @result TRUE if there is a valid service to dial.
-               FALSE if function was unable to retrieve a service to dial.
+       @function SCNetworkConnectionCopyUserPreferences
+       @discussion Provides the default service ID and a dictionary of user
+               options for the connection.  Applications can use the
+               returned serviceID and userOptions values to open a
+               connection on the fly.
+       @param selectionOptions Currently unimplemented. Pass NULL for this
+               version.
+       @param serviceID Reference to the default serviceID for starting
+               connections, this value will be returned by the function.
+       @param userOptions Reference to default userOptions for starting
+               connections, this will be returned by the function.
+       @result Returns TRUE if there is a valid service to dial;
+               FALSE if the function was unable to retrieve a service to dial.
  */
 Boolean SCNetworkConnectionCopyUserPreferences (
                                                CFDictionaryRef                 selectionOptions,
@@ -228,22 +236,24 @@ Boolean SCNetworkConnectionCopyUserPreferences    (
 
 /*!
        @function SCNetworkConnectionCreateWithServiceID
-       @discussion Creates a new connection reference to use for getting the status,
-               for connecting or for disconnecting the associated service.
-       @param allocator The CFAllocator which should be used to allocate
-               memory for the connection structure.
-               This parameter may be NULL in which case the current
-               default CFAllocator is used. If this reference is not
-               a valid CFAllocator, the behavior is undefined.
+       @discussion Creates a new connection reference to use for getting
+               the status or for connecting or disconnecting the associated
+               service.
+       @param allocator The CFAllocator that should be used to allocate
+               memory for the connection structure.  This parameter may be
+               NULL in which case the current default CFAllocator is used.
+               If this reference is not a valid CFAllocator, the behavior
+               is undefined.
        @param serviceID A string that defines the service identifier
-               of the connection. Service identifiers uniquely identify
+               of the connection.  Service identifiers uniquely identify
                services in the system configuration database.
        @param callout The function to be called when the status
-               of the connection changes.
-               If this parameter is NULL, the application will not receive
-               change of status notifications and will need to poll for updates.
-       @param context The SCNetworkConnectionContext associated with the callout.
-       @result A reference to the new SCNetworkConnection.
+               of the connection changes.  If this parameter is NULL, the
+               application will not receive notifications of status change
+               and will need to poll for updates.
+       @param context The SCNetworkConnectionContext associated with the
+               callout.
+       @result Returns a reference to the new SCNetworkConnection.
  */
 SCNetworkConnectionRef
 SCNetworkConnectionCreateWithServiceID         (
@@ -257,8 +267,8 @@ SCNetworkConnectionCreateWithServiceID              (
 /*!
        @function SCNetworkConnectionCopyService
        @discussion Returns the service ID associated with the SCNetworkConnection.
-       @param connection The SCNetworkConnection to obtained status from.
-       Returns the service ID associated with the SCNetworkConnection.
+       @param connection The SCNetworkConnection to obtain status from.
+       @result Returns the service ID associated with the SCNetworkConnection.
  */
 CFStringRef
 SCNetworkConnectionCopyServiceID               (
@@ -269,15 +279,19 @@ SCNetworkConnectionCopyServiceID          (
 /*!
        @function SCNetworkConnectionGetStatus
        @discussion Returns the status of the SCNetworkConnection.
-               A status is one of the following values :
-                   kSCNetworkConnectionInvalid
-                   kSCNetworkConnectionDisconnected
-                   kSCNetworkConnectionConnecting
-                   kSCNetworkConnectionDisconnecting
-                   kSCNetworkConnectionConnected
-
+               A status is one of the following values:
+<pre>
+@textblock
+&#32
+       kSCNetworkConnectionInvalid
+       kSCNetworkConnectionDisconnected
+       kSCNetworkConnectionConnecting
+       kSCNetworkConnectionDisconnecting
+       kSCNetworkConnectionConnected
+@/textblock
+</pre>
        @param connection The SCNetworkConnection to obtain status from.
-       @result The status value.
+       @result Returns the status value.
 */
 SCNetworkConnectionStatus
 SCNetworkConnectionGetStatus                   (
@@ -291,29 +305,34 @@ SCNetworkConnectionGetStatus                      (
                An extended status dictionary contains specific dictionaries
                describing the status for each subcomponent of the service.
 
-               For example, a status dictionary will contain the following dictionaries:
-
-               IPv4:
-                   IPaddress: IP address used.
-
-               PPP:
-                   Status: PPP specific status of type SCNetworkConnectionPPPStatus.
-                   LastCause: Available when status is Disconnected.
-                               Contains the last error of disconnection.
-                   ConnectTime: time when the connection happened
-                   MaxTime: maximum time for this connection
-
-               Modem:
-                   ConnectionSpeed:   Speed of the modem connection in bits/s
-
-               Other dictionaries could be present for PPPoE, PPTP and L2TP.
-
-               The status dictionary can be extended as needed in the future
-               to contain additional information.
-
+               For example, a status dictionary will contain the following
+               sub-dictionaries, keys, and values:
+<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.
-       @result The status dictionary.
-               If NULL is returned, the error can be retrieved with SCError().
+       @result Returns the status dictionary.
+               If NULL is returned, the error can be retrieved using the SCError function.
  */
 CFDictionaryRef
 SCNetworkConnectionCopyExtendedStatus          (
@@ -325,23 +344,37 @@ SCNetworkConnectionCopyExtendedStatus             (
        @function SCNetworkConnectionCopyStatistics
        @discussion Returns the statistics of the SCNetworkConnection.
                A statistic dictionary contains specific dictionaries
-               with statistics for each subcomponents of the service.
-
-               For example, a statistic dictionary will contain the following dictionaries:
-
-               PPP: {Bytes,Packets,Errors}{In,Out}:
-                   Statistics at the Network level.
-                   Contains the number of bytes, packets, and errors on the PPP interface.
-                   For example, BytesIn contains the number of bytes going up
-                   into the network stack, for any networking protocol,
-                   without the PPP headers and trailers.
-
-               The statistic dictionary can be extended as needed in the future
-               to contain additional information.
-
+               with statistics for each subcomponent of the service.
+
+               For example, a statistics dictionary will contain the following
+               sub-dictionaries, keys, and values:
+<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.
-       @result The statistics dictionary.
-               If NULL is returned, the error can be retrieved with SCError().
+       @result Returns the statistics dictionary.
+               If NULL is returned, the error can be retrieved using the SCError function.
  */
 CFDictionaryRef
 SCNetworkConnectionCopyStatistics              (
@@ -351,42 +384,47 @@ SCNetworkConnectionCopyStatistics         (
 
 /*!
        @function SCNetworkConnectionStart
-       @discussion Start the connection for the SCNetworkConnection.
+       @discussion Starts the connection for the SCNetworkConnection.
                The connection process is asynchronous and the function will
-               return immediately. The connection status can be obtain by polling or
-               by callback.
-               The connection is done with the default settings from the administrator.
-               Some of the settings can be overridden for the duration of
-               the connection. They are given in an option dictionary.
-               The options dictionary is in the format of a Network Service
-               as described in SystemConfiguration.
-
-               Note: Starting and stopping of connections is implicitely arbitrated.
-               Calling Start on a connection already started will indicate
-               that the application has interest in the connection and it shouldn't
-               be stopped by anyone else.
-
+               return immediately.  The connection status can be obtained
+               by polling or by callback.  The connection is made with the
+               default settings from the administrator.  Some of the settings
+               can be overridden for the duration of the connection.  These
+               are specified in an options dictionary.  The options dictionary
+               uses the same format as a network service defined in the system
+               configuration preferences schema.
+
+               Note: Starting and stopping of connections is implicitly
+               arbitrated.  Calling SCNetworkConnectionStart on a connection
+               already started will indicate that the application has
+               interest in the connection and it shouldn't be stopped by
+               anyone else.
        @param connection The SCNetworkConnection to start.
        @param userOptions The options dictionary to start the connection with.
                If userOptions is NULL, the default settings will be used.
-               If userOptions are specified, they must be in the SystemConfiguration format.
-               The options will override the default settings defined for the service.
-
-               For security reasons, not all the options can be overridden, the appropriate merging
-               of all the settings will be done before the connection is established,
-               and inappropriate options will be ignored.
-
-       @param linger This parameter indicates whether or not the connection can stay around
-               when the application no longer has interest in it.
-               Typical application should pass FALSE, and the Stop function will
-               automatically be called when the reference is released or if the application quits.
-               If the application passes TRUE, the application can release the reference
-               or exit and the Stop function will not be called.
-
-       @result TRUE if the connection was correctly started. The actual connection is not established yet,
-               and the connection status needs to be periodically checked.
-               FALSE if the connection request didn't start. Error must be taken
-               from SCError().
+               If userOptions are specified, they must be in the same format
+               as network services stored in the system configuration
+               preferences schema.  The options will override the default
+               settings defined for the service.
+
+               For security reasons, not all options can be overridden; the
+               appropriate merging of all settings will be done before the
+               connection is established, and inappropriate options will be
+               ignored.
+       @param linger This parameter indicates whether or not the connection
+               can stay around when the application no longer has interest
+               in it.  A typical application should pass FALSE, and the
+               connection will be automatically stopped when the reference
+               is released or if the application quits.  If the application
+               passes TRUE, the application can release the reference or
+               exit and the connection will be maintained until a timeout
+               event, until a specific stop request occurs, or until an
+               error is encountered.
+       @result Returns TRUE if the connection was correctly started (the
+               actual connection is not established yet, and the connection
+               status needs to be periodically checked); FALSE if the
+               connection request was not started.  The error must be
+               retrieved from the SCError function.
  */
 Boolean
 SCNetworkConnectionStart                       (
@@ -398,21 +436,22 @@ SCNetworkConnectionStart                  (
 
 /*!
        @function SCNetworkConnectionStop
-       @discussion Stop the connection for the SCNetworkConnection.
-               The disconnection process is asynchronous and the function will
-               return immediately. The connection status can be obtain by polling or
-               by callback.
-               This function performs an arbitrated stop of the connection.
-               If several applications have marked their interest in the connection,
-               by calling SCNetworkConnectionStart, the call will succeed but the the actual
-               connection will be maintained until the last interested application calls stop.
-
-               In certain cases, you might want to stop the connection anyway, and
-               SCNetworkConnectionStop with forceDisconnect argument can be used.
-
+       @discussion Stops the connection for the SCNetworkConnection.
+               The disconnection process is asynchronous and the function
+               will return immediately.  The connection status can be
+               obtained by polling or by callback.  This function performs
+               an arbitrated stop of the connection.  If several applications
+               have marked their interest in the connection, by calling
+               SCNetworkConnectionStart, the call will succeed but the
+               actual connection will be maintained until the last interested
+               application calls SCNetworkConnectionStop.
+
+               In certain cases, you might want to stop the connection anyway.
+               In these cases, you set the forceDisconnect argument to TRUE.
        @param connection The SCNetworkConnection to stop.
-       @result TRUE if the disconnection request succeeded.
-               FALSE if the disconnection request failed. Error must be taken from SCError().
+       @result Returns TRUE if the disconnection request succeeded;
+               FALSE if the disconnection request failed.
+               The error must be retrieved from the SCError function.
  */
 Boolean
 SCNetworkConnectionStop                                (
@@ -423,13 +462,13 @@ SCNetworkConnectionStop                           (
 
 /*!
        @function SCNetworkConnectionCopyCurrentOptions
-       @discussion Copy the user options used to start the connection.
-               This is a mechanism for a client to retrieve the user options
+       @discussion Copies the user options used to start the connection.
+               This is a mechanism a client can use to retrieve the user options
                previously passed to the SCNetworkConnectionStart function.
        @param connection The SCNetworkConnection to obtain options from.
-       @result The service dictionary containing the connection options.
+       @result Returns the service dictionary containing the connection options.
                The dictionary can be empty if no user options were used.
-               If NULL is returned, the error can be retrieved with SCError().
+               If NULL is returned, the error can be retrieved using the SCError function.
  */
 CFDictionaryRef
 SCNetworkConnectionCopyUserOptions             (
@@ -439,12 +478,13 @@ SCNetworkConnectionCopyUserOptions                (
 
 /*!
        @function SCNetworkConnectionScheduleWithRunLoop
-       @discussion Schedule a connection with the Run Loop.
+       @discussion Schedules a connection with the run loop.
        @param connection The SCNetworkConnection to schedule.
-       @param runLoop The runloop to schedule with.
-       @param runLoopMode The runloop mode.
-       @result TRUE if success.
-               FALSE if failed. The error can be retrieved with SCError().
+       @param runLoop The run loop to schedule with.
+       @param runLoopMode The run loop mode.
+       @result Returns TRUE if the connection is scheduled successfully;
+               FALSE if the scheduling failed.
+               The error can be retrieved using the SCError function.
  */
 Boolean
 SCNetworkConnectionScheduleWithRunLoop         (
@@ -456,12 +496,13 @@ SCNetworkConnectionScheduleWithRunLoop            (
 
 /*!
        @function SCNetworkConnectionUnscheduleFromRunLoop
-       @discussion Unschedule a connection from the Run Loop.
+       @discussion Unschedules a connection from the run loop.
        @param connection The SCNetworkConnection to unschedule.
-       @param runLoop The runloop to unschedule from.
-       @param runLoopMode The runloop mode.
-       @result TRUE if success.
-               FALSE if failed. The error can be retrieved with SCError().
+       @param runLoop The run loop to unschedule from.
+       @param runLoopMode The run loop mode.
+       @result Returns TRUE if the connection is unscheduled successfully;
+               FALSE if the unscheduling failed.
+               The error can be retrieved using the SCError function.
  */
 Boolean
 SCNetworkConnectionUnscheduleFromRunLoop       (
diff --git a/SystemConfiguration.fproj/SCNetworkInterface.c b/SystemConfiguration.fproj/SCNetworkInterface.c
new file mode 100644 (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@
- *
+ * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- *
+ * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- *
+ * 
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
  * Modification History
  *
+ * March 31, 2004              Allan Nathanson <ajn@apple.com>
+ * - use [SC] DNS configuration information
+ *
  * January 19, 2003            Allan Nathanson <ajn@apple.com>
  * - add advanced reachability APIs
  */
 #include <CoreFoundation/CFRuntime.h>
 #include <pthread.h>
 
+#include <notify.h>
+#include <dnsinfo.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <arpa/nameser.h>
 #include <netdb.h>
 #include <netdb_async.h>
 #include <resolv.h>
@@ -54,7 +58,7 @@
 #define s6_addr16 __u6_addr.__u6_addr16
 #endif
 
-#include "ppp.h"
+#include <ppp/ppp_msg.h>
 
 
 #define kSCNetworkFlagsFirstResolvePending     (1<<31)
@@ -104,9 +108,11 @@ typedef struct {
        SCNetworkReachabilityContext    rlsContext;
        CFMutableArrayRef               rlList;
 
-       /* async DNS query info */
+       /* [async] DNS query info */
+       Boolean                         haveDNS;
        CFMachPortRef                   dnsPort;
        CFRunLoopSourceRef              dnsRLS;
+       struct timeval                  dnsQueryStart;
 
 } SCNetworkReachabilityPrivate, *SCNetworkReachabilityPrivateRef;
 
@@ -128,10 +134,12 @@ static const CFRuntimeClass __SCNetworkReachabilityClass = {
 
 
 static pthread_once_t          initialized     = PTHREAD_ONCE_INIT;
-static Boolean                 needDNS         = TRUE;
 
 
-/* host "something has changed" notifications */
+/*
+ * host "something has changed" notifications
+ */
+
 static pthread_mutex_t         hn_lock         = PTHREAD_MUTEX_INITIALIZER;
 static SCDynamicStoreRef       hn_store        = NULL;
 static CFRunLoopSourceRef      hn_storeRLS     = NULL;
@@ -139,161 +147,52 @@ static CFMutableArrayRef hn_rlList       = NULL;
 static CFMutableSetRef         hn_targets      = NULL;
 
 
-static __inline__ CFTypeRef
-isA_SCNetworkReachability(CFTypeRef obj)
-{
-       return (isA_CFType(obj, SCNetworkReachabilityGetTypeID()));
-}
+/*
+ * DNS configuration
+ */
 
+typedef struct {
+       dns_config_t    *config;
+       int             refs;
+} dns_configuration_t;
 
-static void
-sockaddr_to_string(const struct sockaddr *address, char *buf, size_t bufLen)
-{
-       bzero(buf, bufLen);
-       switch (address->sa_family) {
-               case AF_INET :
-                       (void)inet_ntop(((struct sockaddr_in *)address)->sin_family,
-                                       &((struct sockaddr_in *)address)->sin_addr,
-                                       buf,
-                                       bufLen);
-                       break;
-               case AF_INET6 : {
-                       (void)inet_ntop(((struct sockaddr_in6 *)address)->sin6_family,
-                                       &((struct sockaddr_in6 *)address)->sin6_addr,
-                                       buf,
-                                       bufLen);
-                       if (((struct sockaddr_in6 *)address)->sin6_scope_id != 0) {
-                               int     n;
-
-                               n = strlen(buf);
-                               if ((n+IF_NAMESIZE+1) <= (int)bufLen) {
-                                       buf[n++] = '%';
-                                       if_indextoname(((struct sockaddr_in6 *)address)->sin6_scope_id, &buf[n]);
-                               }
-                       }
-                       break;
-               }
-               case AF_LINK :
-                       if (((struct sockaddr_dl *)address)->sdl_len < bufLen) {
-                               bufLen = ((struct sockaddr_dl *)address)->sdl_len;
-                       } else {
-                               bufLen = bufLen - 1;
-                       }
 
-                       bcopy(((struct sockaddr_dl *)address)->sdl_data, buf, bufLen);
-                       break;
-               default :
-                       snprintf(buf, bufLen, "unexpected address family %d", address->sa_family);
-                       break;
-       }
+static pthread_mutex_t         dns_lock                = PTHREAD_MUTEX_INITIALIZER;
+static dns_configuration_t     *dns_configuration      = NULL;
+static int                     dns_token;
+static Boolean                 dns_token_valid         = FALSE;
 
-       return;
-}
 
-
-#ifndef        CHECK_IPV6_REACHABILITY
-static char *
-__netdb_error(int error)
+static __inline__ CFTypeRef
+isA_SCNetworkReachability(CFTypeRef obj)
 {
-       char    *msg;
-
-       switch(error) {
-               case NETDB_INTERNAL :
-                       msg = strerror(errno);
-                       break;
-               case HOST_NOT_FOUND :
-                       msg = "Host not found.";
-                       break;
-               case TRY_AGAIN :
-                       msg = "Try again.";
-                       break;
-               case NO_RECOVERY :
-                       msg = "No recovery.";
-                       break;
-               case NO_DATA :
-                       msg = "No data available.";
-                       break;
-               default :
-                       msg = "Unknown";
-                       break;
-       }
-
-       return msg;
+       return (isA_CFType(obj, SCNetworkReachabilityGetTypeID()));
 }
-#endif /* CHECK_IPV6_REACHABILITY */
 
 
 static void
-__signalRunLoop(CFTypeRef obj, CFRunLoopSourceRef rls, CFArrayRef rlList)
+__log_query_time(Boolean found, Boolean async, struct timeval *start)
 {
-       CFRunLoopRef    rl      = NULL;
-       CFRunLoopRef    rl1     = NULL;
-       CFIndex         i;
-       CFIndex         n       = CFArrayGetCount(rlList);
+       struct timeval  dnsQueryComplete;
+       struct timeval  dnsQueryElapsed;
 
-       if (n == 0) {
+       if (!_sc_debug) {
                return;
        }
 
-       /* get first runLoop for this object */
-       for (i = 0; i < n; i += 3) {
-               if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
-                       continue;
-               }
-
-               rl1 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
-               break;
-       }
-
-       if (!rl1) {
-               /* if not scheduled */
+       if (start->tv_sec == 0) {
                return;
        }
 
-       /* check if we have another runLoop for this object */
-       rl = rl1;
-       for (i = i+3; i < n; i += 3) {
-               CFRunLoopRef    rl2;
+       (void) gettimeofday(&dnsQueryComplete, NULL);
+       timersub(&dnsQueryComplete, start, &dnsQueryElapsed);
+       SCLog(TRUE, LOG_DEBUG,
+             CFSTR("%ssync DNS complete%s (query time = %d.%3.3d)"),
+             async ? "a" : "",
+             found ? "" : ", host not found",
+             dnsQueryElapsed.tv_sec,
+             dnsQueryElapsed.tv_usec / 1000);
 
-               if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
-                       continue;
-               }
-
-               rl2 = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
-               if (!CFEqual(rl1, rl2)) {
-                       /* we've got more than one runLoop */
-                       rl = NULL;
-                       break;
-               }
-       }
-
-       if (rl) {
-               /* if we only have one runLoop */
-               CFRunLoopWakeUp(rl);
-               return;
-       }
-
-       /* more than one different runLoop, so we must pick one */
-       for (i = 0; i < n; i+=3) {
-               CFStringRef     rlMode;
-
-               if (!CFEqual(obj, CFArrayGetValueAtIndex(rlList, i))) {
-                       continue;
-               }
-
-               rl     = (CFRunLoopRef)CFArrayGetValueAtIndex(rlList, i+1);
-               rlMode = CFRunLoopCopyCurrentMode(rl);
-               if (rlMode && CFRunLoopIsWaiting(rl) && CFRunLoopContainsSource(rl, rls, rlMode)) {
-                       /* we've found a runLoop that's "ready" */
-                       CFRelease(rlMode);
-                       CFRunLoopWakeUp(rl);
-                       return;
-               }
-               if (rlMode) CFRelease(rlMode);
-       }
-
-       /* didn't choose one above, so choose first */
-       CFRunLoopWakeUp(rl1);
        return;
 }
 
@@ -312,7 +211,7 @@ updatePPPStatus(SCDynamicStoreRef           *storeP,
        CFIndex                 n;
        CFStringRef             ppp_if;
        int                     sc_status       = kSCStatusReachabilityUnknown;
-       SCDynamicStoreRef       store           = (storeP) ? *storeP : NULL;
+       SCDynamicStoreRef       store           = (storeP != NULL) ? *storeP : NULL;
        const void *            values_q[N_QUICK];
        const void **           values  = values_q;
 
@@ -327,10 +226,10 @@ updatePPPStatus(SCDynamicStoreRef         *storeP,
                        goto done;
        }
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
+                       SCLog(_sc_verbose, LOG_INFO, CFSTR("updatePPPStatus SCDynamicStoreCreate() failed"));
                        goto done;
                }
        }
@@ -364,7 +263,7 @@ updatePPPStatus(SCDynamicStoreRef           *storeP,
                dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
                CFRelease(patterns);
        }
-       if (!dict) {
+       if (dict == NULL) {
                /* if we could not access the dynamic store */
                goto done;
        }
@@ -502,16 +401,16 @@ updatePPPStatus(SCDynamicStoreRef         *storeP,
 
     done :
 
-       if (dict)       CFRelease(dict);
-       if (storeP)     *storeP = store;
+       if (dict != NULL)       CFRelease(dict);
+       if (storeP != NULL)     *storeP = store;
        return sc_status;
 }
 
 
 static int
 updatePPPAvailable(SCDynamicStoreRef           *storeP,
-                 const struct sockaddr         *sa,
-                 SCNetworkConnectionFlags      *flags)
+                  const struct sockaddr        *sa,
+                  SCNetworkConnectionFlags     *flags)
 {
        CFDictionaryRef         dict            = NULL;
        CFStringRef             entity;
@@ -520,25 +419,29 @@ updatePPPAvailable(SCDynamicStoreRef              *storeP,
        const void **           keys            = keys_q;
        CFIndex                 n;
        int                     sc_status       = kSCStatusReachabilityUnknown;
-       SCDynamicStoreRef       store           = (storeP) ? *storeP : NULL;
+       SCDynamicStoreRef       store           = (storeP != NULL) ? *storeP : NULL;
        const void *            values_q[N_QUICK];
        const void **           values  = values_q;
 
-       switch (sa->sa_family) {
-               case AF_INET :
-                       entity = kSCEntNetIPv4;
-                       break;
-               case AF_INET6 :
-                       entity = kSCEntNetIPv6;
-                       break;
-               default :
-                       goto done;
+       if (sa == NULL) {
+               entity = kSCEntNetIPv4;
+       } else {
+               switch (sa->sa_family) {
+                       case AF_INET :
+                               entity = kSCEntNetIPv4;
+                               break;
+                       case AF_INET6 :
+                               entity = kSCEntNetIPv6;
+                               break;
+                       default :
+                               goto done;
+               }
        }
 
-       if (!store) {
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL, CFSTR("SCNetworkReachability"), NULL, NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
+                       SCLog(_sc_debug, LOG_INFO, CFSTR("  status    = unknown (could not access SCDynamicStore"));
                        goto done;
                }
        }
@@ -566,7 +469,7 @@ updatePPPAvailable(SCDynamicStoreRef                *storeP,
                dict = SCDynamicStoreCopyMultiple(store, NULL, patterns);
                CFRelease(patterns);
        }
-       if (!dict) {
+       if (dict == NULL) {
                /* if we could not access the dynamic store */
                goto done;
        }
@@ -667,8 +570,8 @@ updatePPPAvailable(SCDynamicStoreRef                *storeP,
 
     done :
 
-       if (dict)       CFRelease(dict);
-       if (storeP)     *storeP = store;
+       if (dict != NULL)       CFRelease(dict);
+       if (storeP != NULL)     *storeP = store;
        return sc_status;
 }
 
@@ -717,7 +620,7 @@ checkAddress(SCDynamicStoreRef              *storeP,
        int                     sc_status       = kSCStatusReachabilityUnknown;
        struct sockaddr_dl      *sdl;
        int                     seq             = (int)pthread_self();
-       SCDynamicStoreRef       store           = (storeP) ? *storeP : NULL;
+       SCDynamicStoreRef       store           = (storeP != NULL) ? *storeP : NULL;
        char                    *statusMessage  = NULL;
 #ifndef        RTM_GET_SILENT
 #warning Note: Using RTM_GET (and not RTM_GET_SILENT)
@@ -725,16 +628,21 @@ checkAddress(SCDynamicStoreRef            *storeP,
        int                     sosize          = 48 * 1024;
 #endif
 
-       if (!address || !flags) {
-               sc_status = kSCStatusInvalidArgument;
-               goto done;
+       *flags = 0;
+       if (if_index != NULL) {
+               *if_index = 0;
+       }
+
+       if (address == NULL) {
+               /* special case: check only for available paths off the system */
+               goto checkAvailable;
        }
 
        switch (address->sa_family) {
                case AF_INET :
                case AF_INET6 :
                        if (_sc_debug) {
-                               sockaddr_to_string(address, buf, sizeof(buf));
+                               _SC_sockaddr_to_string(address, buf, sizeof(buf));
                                SCLog(TRUE, LOG_INFO, CFSTR("checkAddress(%s)"), buf);
                        }
                        break;
@@ -749,16 +657,6 @@ checkAddress(SCDynamicStoreRef             *storeP,
                        goto done;
        }
 
-       *flags = 0;
-       if (if_index) {
-               *if_index = 0;
-       }
-
-       if ((address->sa_family == AF_INET) && (((struct sockaddr_in *)address)->sin_addr.s_addr == 0)) {
-               /* special case: check for available paths off the system */
-               goto checkAvailable;
-       }
-
        bzero(&buf, sizeof(buf));
 
        rtm = (struct rt_msghdr *)&buf;
@@ -877,7 +775,7 @@ checkAddress(SCDynamicStoreRef              *storeP,
 
        for (i = 0; i < RTAX_MAX; i++) {
                if (rti_info[i] != NULL) {
-                       sockaddr_to_string(rti_info[i], buf, sizeof(buf));
+                       _SC_sockaddr_to_string(rti_info[i], buf, sizeof(buf));
                        SCLog(_sc_debug, LOG_DEBUG, CFSTR("%d: %s"), i, buf);
                }
        }
@@ -887,13 +785,13 @@ checkAddress(SCDynamicStoreRef            *storeP,
        if ((rti_info[RTAX_IFP] == NULL) ||
            (rti_info[RTAX_IFP]->sa_family != AF_LINK)) {
                /* no interface info */
-               goto done;      // ???
+               goto done;
        }
 
        sdl = (struct sockaddr_dl *) rti_info[RTAX_IFP];
        if ((sdl->sdl_nlen == 0) || (sdl->sdl_nlen > IFNAMSIZ)) {
                /* no interface name */
-               goto done;      // ???
+               goto checkAvailable;
        }
 
        /* get the interface flags */
@@ -948,6 +846,14 @@ checkAddress(SCDynamicStoreRef             *storeP,
                                addr1 = &((struct sockaddr_in *)address)->sin_addr;
                                addr2 = &((struct sockaddr_in *)rti_info[RTAX_IFA])->sin_addr;
                                len = sizeof(struct in_addr);
+
+                               /*
+                                * check if 0.0.0.0
+                                */
+                               if (((struct sockaddr_in *)address)->sin_addr.s_addr == 0) {
+                                       statusMessage = "isReachable (this host)";
+                                       *flags |= kSCNetworkFlagsIsLocalAddress;
+                               }
                                break;
                        case AF_INET6 :
                                addr1 = &((struct sockaddr_in6 *)address)->sin6_addr;
@@ -964,7 +870,10 @@ checkAddress(SCDynamicStoreRef             *storeP,
                }
        }
 
-       if (rti_info[RTAX_GATEWAY] && (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) {
+       if (!(rtm->rtm_flags & RTF_GATEWAY) &&
+           (rti_info[RTAX_GATEWAY] != NULL) &&
+           (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) &&
+           !(ifr.ifr_flags & IFF_POINTOPOINT)) {
                *flags |= kSCNetworkFlagsIsDirect;
        }
 
@@ -973,7 +882,7 @@ checkAddress(SCDynamicStoreRef              *storeP,
              if_name,
              (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ);
 
-       if (if_index) {
+       if (if_index != NULL) {
                *if_index = sdl->sdl_index;
        }
 
@@ -1012,7 +921,7 @@ checkAddress(SCDynamicStoreRef             *storeP,
                SCLog(_sc_debug, LOG_INFO, CFSTR("  cannot be reached"));
        }
 
-       if (storeP)             *storeP = store;
+       if (storeP != NULL)     *storeP = store;
        if (sc_status != kSCStatusOK) {
                _SCErrorSet(sc_status);
                return FALSE;
@@ -1022,47 +931,6 @@ checkAddress(SCDynamicStoreRef            *storeP,
 }
 
 
-static Boolean
-checkAddressZero(SCDynamicStoreRef             *storeP,
-                SCNetworkConnectionFlags       *flags,
-                uint16_t                       *if_index)
-{
-       Boolean                 ok;
-       struct sockaddr_in      sin;
-
-       bzero(&sin, sizeof(sin));
-       sin.sin_len         = sizeof(sin);
-       sin.sin_family      = AF_INET;
-       sin.sin_addr.s_addr = 0;
-
-       ok = checkAddress(storeP, (struct sockaddr *)&sin, flags, if_index);
-
-       return ok;
-}
-
-
-static Boolean
-isAddressZero(struct sockaddr *sa, SCNetworkConnectionFlags *flags)
-{
-       /*
-        * Check if 0.0.0.0
-        */
-       if (sa->sa_family == AF_INET) {
-               struct sockaddr_in      *sin = (struct sockaddr_in *)sa;
-
-               if (sin->sin_addr.s_addr == 0) {
-                       SCLog(_sc_debug, LOG_INFO, CFSTR("isAddressZero(0.0.0.0)"));
-                       SCLog(_sc_debug, LOG_INFO, CFSTR("  status     = isReachable (this host)"));
-                       *flags |= kSCNetworkFlagsReachable;
-                       *flags |= kSCNetworkFlagsIsLocalAddress;
-                       return TRUE;
-               }
-       }
-
-       return FALSE;
-}
-
-
 static CFStringRef
 __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
 {
@@ -1077,14 +945,14 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                case reachabilityTypeAddressPair : {
                        char            buf[64];
 
-                       if (targetPrivate->localAddress) {
-                               sockaddr_to_string(targetPrivate->localAddress, buf, sizeof(buf));
+                       if (targetPrivate->localAddress != NULL) {
+                               _SC_sockaddr_to_string(targetPrivate->localAddress, buf, sizeof(buf));
                                CFStringAppendFormat(result, NULL, CFSTR("local address=%s"),
                                                     buf);
                        }
 
-                       if (targetPrivate->remoteAddress) {
-                               sockaddr_to_string(targetPrivate->remoteAddress, buf, sizeof(buf));
+                       if (targetPrivate->remoteAddress != NULL) {
+                               _SC_sockaddr_to_string(targetPrivate->remoteAddress, buf, sizeof(buf));
                                CFStringAppendFormat(result, NULL, CFSTR("%s%saddress=%s"),
                                                     targetPrivate->localAddress ? ", " : "",
                                                     (targetPrivate->type == reachabilityTypeAddressPair) ? "remote " : "",
@@ -1095,7 +963,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                case reachabilityTypeName : {
                        CFStringAppendFormat(result, NULL, CFSTR("name=%s"), targetPrivate->name);
                        if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
-                               if (targetPrivate->resolvedAddress) {
+                               if (targetPrivate->resolvedAddress != NULL) {
                                        if (isA_CFArray(targetPrivate->resolvedAddress)) {
                                                CFIndex i;
                                                CFIndex n       = CFArrayGetCount(targetPrivate->resolvedAddress);
@@ -1108,7 +976,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
 
                                                        address = CFArrayGetValueAtIndex(targetPrivate->resolvedAddress, i);
                                                        sa      = (struct sockaddr *)CFDataGetBytePtr(address);
-                                                       sockaddr_to_string(sa, buf, sizeof(buf));
+                                                       _SC_sockaddr_to_string(sa, buf, sizeof(buf));
                                                        CFStringAppendFormat(result, NULL, CFSTR("%s%s"),
                                                                             i > 0 ? ", " : "",
                                                                             buf);
@@ -1118,13 +986,8 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                                                CFStringAppendFormat(result, NULL, CFSTR(" (no addresses)"));
                                        }
                                } else {
-#ifdef CHECK_IPV6_REACHABILITY
                                        CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
                                                             gai_strerror(targetPrivate->resolvedAddressError));
-#else  /* CHECK_IPV6_REACHABILITY */
-                                       CFStringAppendFormat(result, NULL, CFSTR(" (%s)"),
-                                                            __netdb_error(targetPrivate->resolvedAddressError));
-#endif /* CHECK_IPV6_REACHABILITY */
                                }
                        } else if (targetPrivate->dnsPort) {
                                CFStringAppendFormat(result, NULL, CFSTR(" (DNS query active)"));
@@ -1132,7 +995,7 @@ __SCNetworkReachabilityCopyDescription(CFTypeRef cf)
                        break;
                }
        }
-       if (targetPrivate->rls) {
+       if (targetPrivate->rls != NULL) {
                CFStringAppendFormat(result,
                                     NULL,
                                     CFSTR(", flags=%8.8x, if_index=%hu"),
@@ -1150,26 +1013,24 @@ __SCNetworkReachabilityDeallocate(CFTypeRef cf)
 {
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityDeallocate:"));
-
        /* release resources */
 
        pthread_mutex_destroy(&targetPrivate->lock);
 
-       if (targetPrivate->name)
+       if (targetPrivate->name != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->name);
 
-       if (targetPrivate->resolvedAddress)
+       if (targetPrivate->resolvedAddress != NULL)
                CFRelease(targetPrivate->resolvedAddress);
 
-       if (targetPrivate->localAddress)
+       if (targetPrivate->localAddress != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->localAddress);
 
-       if (targetPrivate->remoteAddress)
+       if (targetPrivate->remoteAddress != NULL)
                CFAllocatorDeallocate(NULL, (void *)targetPrivate->remoteAddress);
 
-       if (targetPrivate->rlsContext.release) {
-               targetPrivate->rlsContext.release(targetPrivate->rlsContext.info);
+       if (targetPrivate->rlsContext.release != NULL) {
+               (*targetPrivate->rlsContext.release)(targetPrivate->rlsContext.info);
        }
 
        return;
@@ -1193,15 +1054,13 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef     allocator)
        /* initialize runtime */
        pthread_once(&initialized, __SCNetworkReachabilityInitialize);
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCNetworkReachabilityCreatePrivate:"));
-
        /* allocate target */
        size          = sizeof(SCNetworkReachabilityPrivate) - sizeof(CFRuntimeBase);
        targetPrivate = (SCNetworkReachabilityPrivateRef)_CFRuntimeCreateInstance(allocator,
                                                                                  __kSCNetworkReachabilityTypeID,
                                                                                  size,
                                                                                  NULL);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
@@ -1226,6 +1085,7 @@ __SCNetworkReachabilityCreatePrivate(CFAllocatorRef       allocator)
        targetPrivate->rlsContext.copyDescription       = NULL;
        targetPrivate->rlList                           = NULL;
 
+       targetPrivate->haveDNS                          = FALSE;
        targetPrivate->dnsPort                          = NULL;
        targetPrivate->dnsRLS                           = NULL;
 
@@ -1239,7 +1099,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef             allocator,
 {
        SCNetworkReachabilityPrivateRef targetPrivate;
 
-       if (!address ||
+       if ((address == NULL) ||
            (address->sa_len == 0) ||
            (address->sa_len > sizeof(struct sockaddr_storage))) {
                _SCErrorSet(kSCStatusInvalidArgument);
@@ -1247,7 +1107,7 @@ SCNetworkReachabilityCreateWithAddress(CFAllocatorRef             allocator,
        }
 
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
@@ -1271,7 +1131,7 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef         allocator,
                return NULL;
        }
 
-       if (localAddress) {
+       if (localAddress != NULL) {
                if ((localAddress->sa_len == 0) ||
                    (localAddress->sa_len > sizeof(struct sockaddr_storage))) {
                            _SCErrorSet(kSCStatusInvalidArgument);
@@ -1279,7 +1139,7 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef         allocator,
                }
        }
 
-       if (remoteAddress) {
+       if (remoteAddress != NULL) {
                if ((remoteAddress->sa_len == 0) ||
                    (remoteAddress->sa_len > sizeof(struct sockaddr_storage))) {
                            _SCErrorSet(kSCStatusInvalidArgument);
@@ -1288,18 +1148,18 @@ SCNetworkReachabilityCreateWithAddressPair(CFAllocatorRef               allocator,
        }
 
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
        targetPrivate->type = reachabilityTypeAddressPair;
 
-       if (localAddress) {
+       if (localAddress != NULL) {
                targetPrivate->localAddress = CFAllocatorAllocate(NULL, localAddress->sa_len, 0);
                bcopy(localAddress, targetPrivate->localAddress, localAddress->sa_len);
        }
 
-       if (remoteAddress) {
+       if (remoteAddress != NULL) {
                targetPrivate->remoteAddress = CFAllocatorAllocate(NULL, remoteAddress->sa_len, 0);
                bcopy(remoteAddress, targetPrivate->remoteAddress, remoteAddress->sa_len);
        }
@@ -1312,15 +1172,42 @@ SCNetworkReachabilityRef
 SCNetworkReachabilityCreateWithName(CFAllocatorRef     allocator,
                                    const char          *nodename)
 {
+       struct sockaddr_in              sin;
+       struct sockaddr_in6             sin6;
        SCNetworkReachabilityPrivateRef targetPrivate;
 
-       if (!nodename) {
+       if (nodename == NULL) {
                _SCErrorSet(kSCStatusInvalidArgument);
                return NULL;
        }
 
+       /* check if this "nodename" is really an IP[v6] address in disguise */
+
+       bzero(&sin, sizeof(sin));
+       sin.sin_len    = sizeof(sin);
+       sin.sin_family = AF_INET;
+       if (inet_aton(nodename, &sin.sin_addr) == 1) {
+               /* if IPv4 address */
+               return SCNetworkReachabilityCreateWithAddress(allocator, (struct sockaddr *)&sin);
+       }
+
+       bzero(&sin6, sizeof(sin6));
+       sin6.sin6_len    = sizeof(sin6);
+       sin6.sin6_family = AF_INET6;
+       if (inet_pton(AF_INET6, nodename, &sin6.sin6_addr) == 1) {
+               /* if IPv6 address */
+               char    *p;
+
+               p = strchr(nodename, '%');
+               if (p != NULL) {
+                       sin6.sin6_scope_id = if_nametoindex(p+1);
+               }
+
+               return SCNetworkReachabilityCreateWithAddress(allocator, (struct sockaddr *)&sin6);
+       }
+
        targetPrivate = __SCNetworkReachabilityCreatePrivate(allocator);
-       if (!targetPrivate) {
+       if (targetPrivate == NULL) {
                return NULL;
        }
 
@@ -1364,7 +1251,7 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef target,
        }
 
        if (targetPrivate->resolvedAddress || (targetPrivate->resolvedAddressError != NETDB_SUCCESS)) {
-               if (targetPrivate->resolvedAddress) {
+               if (targetPrivate->resolvedAddress != NULL) {
                        return CFRetain(targetPrivate->resolvedAddress);
                } else {
                        /* if status is known but no resolved addresses to return */
@@ -1379,37 +1266,20 @@ SCNetworkReachabilityCopyResolvedAddress(SCNetworkReachabilityRef       target,
 
 
 static void
-__SCNetworkReachabilitySetResolvedAddress(SCNetworkReachabilityRef     target,
-                                         CFArrayRef                    addresses,
-                                         int                           error_num)
-{
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       if (targetPrivate->resolvedAddress) {
-               CFRelease(targetPrivate->resolvedAddress);
-       }
-       targetPrivate->resolvedAddress      = addresses ? CFRetain(addresses) : NULL;
-       targetPrivate->resolvedAddressError = error_num;
-       return;
-}
-
-
-#ifdef CHECK_IPV6_REACHABILITY
-static void
-__SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinfo *res, void *context)
+__SCNetworkReachabilitySetResolvedAddress(int32_t                      status,
+                                         struct addrinfo               *res,
+                                         SCNetworkReachabilityRef      target)
 {
-       Boolean                                 ok;
        struct addrinfo                         *resP;
-       SCNetworkReachabilityRef                target          = (SCNetworkReachabilityRef)context;
        SCNetworkReachabilityPrivateRef         targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
-       ok = (status == 0) && (res != NULL);
+       if (targetPrivate->resolvedAddress != NULL) {
+               CFRelease(targetPrivate->resolvedAddress);
+               targetPrivate->resolvedAddress = NULL;
+       }
 
-       SCLog(_sc_debug, LOG_DEBUG,
-             CFSTR("process async DNS complete%s"),
-             ok ? "" : ", host not found");
+       if ((status == 0) && (res != NULL)) {
 
-       if (ok) {
                CFMutableArrayRef       addresses;
 
                addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
@@ -1423,94 +1293,41 @@ __SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinf
                }
 
                /* save the resolved address[es] */
-               __SCNetworkReachabilitySetResolvedAddress(target, addresses, NETDB_SUCCESS);
-               CFRelease(addresses);
+               targetPrivate->resolvedAddress      = addresses;
+               targetPrivate->resolvedAddressError = NETDB_SUCCESS;
        } else {
                SCLog(_sc_debug, LOG_INFO, CFSTR("getaddrinfo() failed: %s"), gai_strerror(status));
 
                /* save the error associated with the attempt to resolve the name */
-               __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, status);
+               targetPrivate->resolvedAddress      = CFRetain(kCFNull);
+               targetPrivate->resolvedAddressError = status;
        }
 
        if (res)        freeaddrinfo(res);
 
-       if (targetPrivate->rls) {
+       if (targetPrivate->rls != NULL) {
                SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed"));
                CFRunLoopSourceSignal(targetPrivate->rls);
-               __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+               _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
        }
 
        return;
 }
-#else  /* CHECK_IPV6_REACHABILITY */
-static void
-__SCNetworkReachabilityCallbackSetResolvedAddress(struct hostent *h, int error, void *context)
-{
-       SCNetworkReachabilityRef                target          = (SCNetworkReachabilityRef)context;
-       SCNetworkReachabilityPrivateRef         targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
-
-       SCLog(_sc_debug, LOG_DEBUG,
-             CFSTR("process async DNS complete%s"),
-             (h == NULL) ? ", host not found" : "");
-
-       if (h && h->h_length) {
-               CFMutableArrayRef       addresses;
-               union {
-                       struct sockaddr         sa;
-                       struct sockaddr_in      sin;
-                       struct sockaddr_in6     sin6;
-                       struct sockaddr_storage ss;
-               }       addr;
-               char    **ha            = h->h_addr_list;
-
-               addresses = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-
-               bzero(&addr, sizeof(addr));
-
-               while (*ha) {
-                       CFDataRef       newAddress;
-
-                       switch (h->h_length) {
-                               case sizeof(struct in_addr) :
-                                       addr.sin.sin_family = AF_INET;
-                                       addr.sin.sin_len    = sizeof(struct sockaddr_in);
-                                       bcopy(*ha, &addr.sin.sin_addr, h->h_length);
-                                       break;
-                               case sizeof(struct in6_addr) :
-                                       addr.sin6.sin6_family = AF_INET6;
-                                       addr.sin6.sin6_len    = sizeof(struct sockaddr_in6);
-                                       bcopy(*ha, &addr.sin6.sin6_addr, h->h_length);
-                                       break;
-                       }
-
-                       newAddress = CFDataCreate(NULL, (void *)&addr, addr.sa.sa_len);
-                       CFArrayAppendValue(addresses, newAddress);
-                       CFRelease(newAddress);
-
-                       ha++;
-               }
-
-               /* save the resolved address[es] */
-               __SCNetworkReachabilitySetResolvedAddress(target, addresses, NETDB_SUCCESS);
-               CFRelease(addresses);
-       } else {
-               SCLog(_sc_debug, LOG_INFO, CFSTR("getipnodebyname() failed: %s"), __netdb_error(error));
 
-               /* save the error associated with the attempt to resolve the name */
-               __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error);
-       }
 
-       if (h)  freehostent(h);
+static void
+__SCNetworkReachabilityCallbackSetResolvedAddress(int32_t status, struct addrinfo *res, void *context)
+{
+       SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)context;
+       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
-       if (targetPrivate->rls) {
-               SCLog(_sc_debug, LOG_INFO, CFSTR("DNS request completed"));
-               CFRunLoopSourceSignal(targetPrivate->rls);
-               __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
-       }
+       __log_query_time(((status == 0) && (res != NULL)),      // if successful query
+                        TRUE,                                  // async
+                        &targetPrivate->dnsQueryStart);        // start time
 
+       __SCNetworkReachabilitySetResolvedAddress(status, res, target);
        return;
 }
-#endif /* CHECK_IPV6_REACHABILITY */
 
 
 /*
@@ -1530,7 +1347,6 @@ rankReachability(SCNetworkConnectionFlags flags)
 }
 
 
-#ifdef CHECK_IPV6_REACHABILITY
 static void
 getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
 {
@@ -1542,6 +1358,7 @@ getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi
        getaddrinfo_async_handle_reply(msg);
 
        if (port == targetPrivate->dnsPort) {
+               CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
                CFRelease(targetPrivate->dnsRLS);
                targetPrivate->dnsRLS = NULL;
                CFRelease(targetPrivate->dnsPort);
@@ -1552,38 +1369,255 @@ getaddrinfo_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, voi
 
        return;
 }
-#else  /* CHECK_IPV6_REACHABILITY */
-static void
-getipnodebyname_async_handleCFReply(CFMachPortRef port, void *msg, CFIndex size, void *info)
+
+
+static Boolean
+check_resolver_reachability(SCDynamicStoreRef          *storeP,
+                           dns_resolver_t              *resolver,
+                           SCNetworkConnectionFlags    *flags,
+                           Boolean                     *haveDNS)
 {
-       SCNetworkReachabilityRef        target          = (SCNetworkReachabilityRef)info;
-       SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
+       int             i;
+       Boolean         ok      = TRUE;
 
-       pthread_mutex_lock(&targetPrivate->lock);
+       *flags   = kSCNetworkFlagsReachable;
+       *haveDNS = FALSE;
 
-       getipnodebyname_async_handleReply(msg);
+       for (i = 0; i < resolver->n_nameserver; i++) {
+               struct sockaddr                 *address        = resolver->nameserver[i];
+               SCNetworkConnectionFlags        ns_flags        = 0;
 
-       if (port == targetPrivate->dnsPort) {
-               CFRelease(targetPrivate->dnsRLS);
-               targetPrivate->dnsRLS = NULL;
-               CFRelease(targetPrivate->dnsPort);
-               targetPrivate->dnsPort = NULL;
+               *haveDNS = TRUE;
+
+               if (address->sa_family != AF_INET) {
+                       /*
+                        * we need to skip non-IPv4 DNS server
+                        * addresses (at least until [3510431] has
+                        * been resolved).
+                        */
+                       continue;
+               }
+
+               ok = checkAddress(storeP, address, &ns_flags, NULL);
+               if (!ok) {
+                       /* not today */
+                       goto done;
+               }
+
+               if (rankReachability(ns_flags) < rankReachability(*flags)) {
+                       /* return the worst case result */
+                       *flags = ns_flags;
+               }
        }
 
-       pthread_mutex_unlock(&targetPrivate->lock);
+    done :
+
+       return ok;
+}
+
+
+static Boolean
+check_matching_resolvers(SCDynamicStoreRef             *storeP,
+                        dns_config_t                   *dns_config,
+                        const char                     *fqdn,
+                        SCNetworkConnectionFlags       *flags,
+                        Boolean                        *haveDNS)
+{
+       int             i;
+       Boolean         matched = FALSE;
+       const char      *name   = fqdn;
+
+       while (!matched && (name != NULL)) {
+               int     len;
+
+               /*
+                * check if the provided name (or sub-component)
+                * matches one of our resolver configurations.
+                */
+               len = strlen(name);
+               for (i = 0; i < dns_config->n_resolver; i++) {
+                       char            *domain;
+                       dns_resolver_t  *resolver;
+
+                       resolver = dns_config->resolver[i];
+                       domain   = resolver->domain;
+                       if (domain != NULL && (len == strlen(domain))) {
+                               if (strcasecmp(name, domain) == 0) {
+                                       Boolean ok;
+
+                                       /*
+                                        * if name matches domain
+                                        */
+                                       matched = TRUE;
+                                       ok = check_resolver_reachability(storeP, resolver, flags, haveDNS);
+                                       if (!ok) {
+                                               /* not today */
+                                               return FALSE;
+                                       }
+                               }
+                       }
+               }
+
+               if (!matched) {
+                       /*
+                        * we have not found a matching resolver, try
+                        * a less qualified domain
+                        */
+                       name = strchr(name, '.');
+                       if ((name != NULL) && (*name != '\0')) {
+                               name++;
+                       } else {
+                               name = NULL;
+                       }
+               }
+       }
+
+       return matched;
+}
+
+
+static dns_configuration_t *
+dns_configuration_retain()
+{
+       pthread_mutex_lock(&dns_lock);
+
+       if ((dns_configuration != NULL) && dns_token_valid) {
+               int             check   = 0;
+               uint32_t        status;
+
+               /*
+                * check if the global [DNS] configuration snapshot needs
+                * to be updated
+                */
+               status = notify_check(dns_token, &check);
+               if (status != NOTIFY_STATUS_OK) {
+                       SCLog(TRUE, LOG_INFO, CFSTR("notify_check() failed, status=%lu"), status);
+               }
+
+               if ((status != NOTIFY_STATUS_OK) || (check != 0)) {
+                       /*
+                        * if the snapshot needs to be refreshed
+                        */
+                       if (dns_configuration->refs == 0) {
+                               dns_configuration_free(dns_configuration->config);
+                               CFAllocatorDeallocate(NULL, dns_configuration);
+                       }
+                       dns_configuration = NULL;
+               }
+       }
+
+       if (dns_configuration == NULL) {
+               dns_config_t    *new_config;
 
+               new_config = dns_configuration_copy();
+               if (new_config != NULL) {
+                       dns_configuration = CFAllocatorAllocate(NULL, sizeof(dns_configuration_t), 0);
+                       dns_configuration->config = new_config;
+                       dns_configuration->refs   = 0;
+               }
+       }
+
+       if (dns_configuration != NULL) {
+               dns_configuration->refs++;
+       }
+
+       pthread_mutex_unlock(&dns_lock);
+       return dns_configuration;
+}
+
+
+static void
+dns_configuration_release(dns_configuration_t *config)
+{
+       pthread_mutex_lock(&dns_lock);
+
+       config->refs--;
+       if (config->refs == 0) {
+               if ((dns_configuration != config)) {
+                       dns_configuration_free(config->config);
+                       CFAllocatorDeallocate(NULL, config);
+               }
+       }
+
+       pthread_mutex_unlock(&dns_lock);
        return;
 }
-#endif /* CHECK_IPV6_REACHABILITY */
 
 
 static Boolean
-checkResolverReachability(SCDynamicStoreRef            *storeP,
-                         SCNetworkConnectionFlags      *flags,
-                         Boolean                       *haveDNS)
+dns_configuration_watch()
 {
-       int     i;
-       Boolean ok      = TRUE;
+       int             dns_check       = 0;
+       const char      *dns_key;
+       Boolean         ok              = FALSE;
+       uint32_t        status;
+
+       pthread_mutex_lock(&dns_lock);
+
+       dns_key = dns_configuration_notify_key();
+       if (dns_key == NULL) {
+               SCLog(TRUE, LOG_INFO, CFSTR("dns_configuration_notify_key() failed"));
+               goto done;
+       }
+
+       status = notify_register_check(dns_key, &dns_token);
+       if (status == NOTIFY_STATUS_OK) {
+               dns_token_valid = TRUE;
+       } else {
+               SCLog(TRUE, LOG_INFO, CFSTR("notify_register_check() failed, status=%lu"), status);
+               goto done;
+       }
+
+       status = notify_check(dns_token, &dns_check);
+       if (status != NOTIFY_STATUS_OK) {
+               SCLog(TRUE, LOG_INFO, CFSTR("notify_check() failed, status=%lu"), status);
+               (void)notify_cancel(dns_token);
+               dns_token_valid = FALSE;
+               goto done;
+       }
+
+       ok = TRUE;
+
+    done :
+
+       pthread_mutex_unlock(&dns_lock);
+       return ok;
+}
+
+
+static void
+dns_configuration_unwatch()
+{
+       pthread_mutex_lock(&dns_lock);
+
+       (void)notify_cancel(dns_token);
+       dns_token_valid = FALSE;
+
+       if ((dns_configuration != NULL) && (dns_configuration->refs == 0)) {
+               dns_configuration_free(dns_configuration->config);
+               CFAllocatorDeallocate(NULL, dns_configuration);
+               dns_configuration = NULL;
+       }
+
+       pthread_mutex_unlock(&dns_lock);
+       return;
+}
+
+
+Boolean
+_SC_checkResolverReachability(SCDynamicStoreRef                *storeP,
+                             SCNetworkConnectionFlags  *flags,
+                             Boolean                   *haveDNS,
+                             const char *              nodename)
+{
+       dns_resolver_t          *default_resolver;
+       dns_configuration_t     *dns;
+       Boolean                 found                   = FALSE;
+       char                    *fqdn                   = (char *)nodename;
+       int                     i;
+       Boolean                 isFQDN                  = FALSE;
+       uint32_t                len;
+       Boolean                 ok                      = TRUE;
 
        /*
         * We first assume that all of the configured DNS servers
@@ -1596,41 +1630,105 @@ checkResolverReachability(SCDynamicStoreRef            *storeP,
        *flags   = kSCNetworkFlagsReachable;
        *haveDNS = FALSE;
 
-       if (needDNS) {
-               if (hn_store) {
-                       /* if we are actively watching at least one host */
-                       needDNS = FALSE;
-               }
-               res_init();
+       len = strlen(fqdn);
+       if (len == 0) {
+               // if no nodename, return not reachable
+               *flags = 0;
+               return ok;
        }
 
-       for (i = 0; i < _res.nscount; i++) {
-               SCNetworkConnectionFlags        ns_flags        = 0;
+       dns = dns_configuration_retain();
+       if (dns == NULL) {
+               // if error
+               goto done;
+       }
 
-               if (_res.nsaddr_list[i].sin_addr.s_addr == 0) {
-                       continue;
-               }
+       if (dns->config->n_resolver == 0) {
+               // if no resolver configuration
+               goto done;
+       }
 
-               *haveDNS = TRUE;
+       *flags = kSCNetworkFlagsReachable;
 
-               if (_res.nsaddr_list[i].sin_len == 0) {
-                       _res.nsaddr_list[i].sin_len = sizeof(_res.nsaddr_list[i]);
-               }
+       if (fqdn[len - 1] == '.') {
+               isFQDN = TRUE;
 
-               ok = checkAddress(storeP, (struct sockaddr *)&_res.nsaddr_list[i], &ns_flags, NULL);
-               if (!ok) {
-                       /* not today */
-                       break;
+               // trim trailing '.''s
+               while ((len > 0) && (fqdn[len-1] == '.')) {
+                       if (fqdn == nodename) {
+                               fqdn = strdup(nodename);
+                       }
+                       fqdn[--len] = '\0';
                }
-               if (rankReachability(ns_flags) < rankReachability(*flags)) {
-                       /* return the worst case result */
-                       *flags = ns_flags;
+       }
+
+       default_resolver = dns->config->resolver[0];
+
+       /*
+        * try the provided name
+        */
+       found = check_matching_resolvers(storeP, dns->config, fqdn, flags, haveDNS);
+       if (!found && !isFQDN && (dns->config->n_resolver > 1)) {
+               /*
+                * FQDN not specified, try w/search or default domain(s) too
+                */
+               if (default_resolver->n_search > 0) {
+                       for (i = 0; !found && (i < default_resolver->n_search); i++) {
+                               int     ret;
+                               char    *search_fqdn    = NULL;
+
+                               ret = asprintf(&search_fqdn, "%s.%s", fqdn, default_resolver->search[i]);
+                               if (ret == -1) {
+                                       continue;
+                               }
+
+                               // try the provided name with the search domain appended
+                               found = check_matching_resolvers(storeP, dns->config, search_fqdn, flags, haveDNS);
+                               free(search_fqdn);
+                       }
+               } else if (default_resolver->domain != NULL) {
+                       char    *dp;
+                       int     domain_parts    = 1;
+
+                       for (dp = default_resolver->domain; *dp != '\0'; dp++) {
+                               if (*dp == '.') {
+                                       domain_parts++;
+                               }
+                       }
+
+                       dp = default_resolver->domain;
+                       for (i = LOCALDOMAINPARTS; !found && (i <= domain_parts); i++) {
+                               int     ret;
+                               char    *search_fqdn    = NULL;
+
+                               ret = asprintf(&search_fqdn, "%s.%s", fqdn, dp);
+                               if (ret == -1) {
+                                       continue;
+                               }
+
+                               // try the provided name with the [default] domain appended
+                               found = check_matching_resolvers(storeP, dns->config, search_fqdn, flags, haveDNS);
+                               free(search_fqdn);
+
+                               // move to the next component of the [default] domain
+                               dp = strchr(dp, '.') + 1;
+                       }
                }
        }
 
-       if (!*haveDNS) {
-               /* if no DNS server addresses */
-               *flags = 0;
+       if (!found) {
+               /*
+                * check the reachability of the default resolver
+                */
+               ok = check_resolver_reachability(storeP, default_resolver, flags, haveDNS);
+       }
+
+       if (fqdn != nodename)   free(fqdn);
+
+    done :
+
+       if (dns != NULL) {
+               dns_configuration_release(dns);
        }
 
        return ok;
@@ -1641,17 +1739,19 @@ static Boolean
 startAsyncDNSQuery(SCNetworkReachabilityRef target) {
        CFMachPortContext               context         = { 0, (void *)target, CFRetain, CFRelease, CFCopyDescription };
        int                             error;
-#ifdef CHECK_IPV6_REACHABILITY
        struct addrinfo                 hints;
-#endif /* CHECK_IPV6_REACHABILITY */
        CFIndex                         i;
        CFIndex                         n;
        mach_port_t                     port;
        SCNetworkReachabilityPrivateRef targetPrivate   = (SCNetworkReachabilityPrivateRef)target;
 
-#ifdef CHECK_IPV6_REACHABILITY
+       (void) gettimeofday(&targetPrivate->dnsQueryStart, NULL);
+
        bzero(&hints, sizeof(hints));
        hints.ai_flags = AI_ADDRCONFIG;
+#ifdef AI_PARALLEL
+       hints.ai_flags |= AI_PARALLEL;
+#endif /* AI_PARALLEL */
 
        error = getaddrinfo_async_start(&port,
                                        targetPrivate->name,
@@ -1661,7 +1761,7 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) {
                                        (void *)target);
        if (error != 0) {
                /* save the error associated with the attempt to resolve the name */
-               __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error);
+               __SCNetworkReachabilityCallbackSetResolvedAddress(error, NULL, (void *)target);
                return FALSE;
        }
 
@@ -1670,26 +1770,6 @@ startAsyncDNSQuery(SCNetworkReachabilityRef target) {
                                                          getaddrinfo_async_handleCFReply,
                                                          &context,
                                                          NULL);
-#else  /* CHECK_IPV6_REACHABILITY */
-       port = getipnodebyname_async_start(targetPrivate->name,
-                                          AF_INET,
-                                          0,
-                                          &error,
-                                          __SCNetworkReachabilityCallbackSetResolvedAddress,
-                                          (void *)target);
-       if (port == MACH_PORT_NULL) {
-               /* save the error associated with the attempt to resolve the name */
-               __SCNetworkReachabilitySetResolvedAddress(target, (CFArrayRef)kCFNull, error);
-               return FALSE;
-       }
-
-       targetPrivate->dnsPort = CFMachPortCreateWithPort(NULL,
-                                                         port,
-                                                         getipnodebyname_async_handleCFReply,
-                                                         &context,
-                                                         NULL);
-#endif /* CHECK_IPV6_REACHABILITY */
-
        targetPrivate->dnsRLS = CFMachPortCreateRunLoopSource(NULL, targetPrivate->dnsPort, 0);
 
        n = CFArrayGetCount(targetPrivate->rlList);
@@ -1718,7 +1798,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef         *storeP,
        Boolean                         ok              = TRUE;
 
        *flags = 0;
-       if (if_index) {
+       if (if_index != NULL) {
                *if_index = 0;
        }
 
@@ -1733,14 +1813,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef                *storeP,
                        /*
                         * Check "local" address
                         */
-                       if (targetPrivate->localAddress) {
-                               /*
-                                * Check if 0.0.0.0
-                                */
-                               if (isAddressZero(targetPrivate->localAddress, &my_flags)) {
-                                       goto checkRemote;
-                               }
-
+                       if (targetPrivate->localAddress != NULL) {
                                /*
                                 * Check "local" address
                                 */
@@ -1754,12 +1827,10 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                                }
                        }
 
-                   checkRemote :
-
                        /*
                         * Check "remote" address
                         */
-                       if (targetPrivate->remoteAddress) {
+                       if (targetPrivate->remoteAddress != NULL) {
                                /*
                                 * in cases where we have "local" and "remote" addresses
                                 * we need to re-initialize the to-be-returned flags.
@@ -1767,13 +1838,6 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef                *storeP,
                                my_flags = 0;
                                my_index = 0;
 
-                               /*
-                                * Check if 0.0.0.0
-                                */
-                               if (isAddressZero(targetPrivate->remoteAddress, &my_flags)) {
-                                       break;
-                               }
-
                                /*
                                 * Check "remote" address
                                 */
@@ -1788,27 +1852,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                }
 
                case reachabilityTypeName : {
+                       struct timeval                  dnsQueryStart;
                        int                             error;
-#ifndef        CHECK_IPV6_REACHABILITY
-                       struct hostent                  *h;
-#endif /* CHECK_IPV6_REACHABILITY */
-                       Boolean                         haveDNS         = FALSE;
-#ifdef CHECK_IPV6_REACHABILITY
                        struct addrinfo                 hints;
-#endif /* CHECK_IPV6_REACHABILITY */
                        SCNetworkConnectionFlags        ns_flags;
-#ifdef CHECK_IPV6_REACHABILITY
                        struct addrinfo                 *res;
-#endif /* CHECK_IPV6_REACHABILITY */
 
                        addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
-                       if (addresses || (error != NETDB_SUCCESS)) {
+                       if ((addresses != NULL) || (error != NETDB_SUCCESS)) {
                                /* if resolved or an error had been detected */
                                goto checkResolvedAddress;
                        }
 
                        /* check the reachability of the DNS servers */
-                       ok = checkResolverReachability(storeP, &ns_flags, &haveDNS);\
+                       ok = _SC_checkResolverReachability(storeP,
+                                                          &ns_flags,
+                                                          &targetPrivate->haveDNS,
+                                                          targetPrivate->name);
                        if (!ok) {
                                /* if we could not get DNS server info */
                                goto error;
@@ -1820,30 +1880,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                                 * flags based on the availability of configured (but not
                                 * active) services.
                                 */
-                               if (!checkAddressZero(storeP, &my_flags, &my_index)) {
+                               if (!checkAddress(storeP, NULL, &my_flags, &my_index)) {
                                        goto error;
                                }
 
-                               if (async && targetPrivate->rls) {
+                               if (async && (targetPrivate->rls != NULL)) {
                                        /*
-                                        * return HOST_NOT_FOUND, set flags appropriately,
+                                        * return "host not found", set flags appropriately,
                                         * and schedule notification.
                                         */
-#ifdef CHECK_IPV6_REACHABILITY
                                        __SCNetworkReachabilityCallbackSetResolvedAddress(EAI_NODATA,
                                                                                          NULL,
                                                                                          (void *)target);
-#else  /* CHECK_IPV6_REACHABILITY */
-                                       __SCNetworkReachabilityCallbackSetResolvedAddress(NULL,
-                                                                                         HOST_NOT_FOUND,
-                                                                                         (void *)target);
-#endif /* CHECK_IPV6_REACHABILITY */
-
                                        my_flags |= (targetPrivate->flags & kSCNetworkFlagsFirstResolvePending);
 
                                        SCLog(_sc_debug, LOG_INFO, CFSTR("no DNS servers are reachable"));
                                        CFRunLoopSourceSignal(targetPrivate->rls);
-                                       __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+                                       _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
                                }
                                break;
                        }
@@ -1878,16 +1931,23 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                         * OK, all of the DNS name servers are available.  Let's
                         * resolve the nodename into an address.
                         */
-#ifdef CHECK_IPV6_REACHABILITY
+                       if (_sc_debug) {
+                               (void) gettimeofday(&dnsQueryStart, NULL);
+                       }
+
                        bzero(&hints, sizeof(hints));
                        hints.ai_flags = AI_ADDRCONFIG;
+#ifdef AI_PARALLEL
+                       hints.ai_flags |= AI_PARALLEL;
+#endif /* AI_PARALLEL */
 
                        error = getaddrinfo(targetPrivate->name, NULL, &hints, &res);
-                       __SCNetworkReachabilityCallbackSetResolvedAddress(error, res, (void *)target);
-#else  /* CHECK_IPV6_REACHABILITY */
-                       h = getipnodebyname(targetPrivate->name, AF_INET, 0, &error);
-                       __SCNetworkReachabilityCallbackSetResolvedAddress(h, error, (void *)target);
-#endif /* CHECK_IPV6_REACHABILITY */
+
+                       __log_query_time(((error == 0) && (res != NULL)),// if successful query
+                                        FALSE,                         // sync
+                                        &dnsQueryStart);               // start time
+
+                       __SCNetworkReachabilitySetResolvedAddress(error, res, target);
 
                        addresses = (CFMutableArrayRef)SCNetworkReachabilityCopyResolvedAddress(target, &error);
 
@@ -1911,6 +1971,7 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef         *storeP,
                                        struct sockaddr                 *sa;
 
                                        sa = (struct sockaddr *)CFDataGetBytePtr(CFArrayGetValueAtIndex(addresses, i));
+
                                        ok = checkAddress(storeP, sa, &ns_flags, &ns_if_index);
                                        if (!ok) {
                                                goto error;     /* not today */
@@ -1927,13 +1988,13 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
                                        }
                                }
                        } else {
-                               if ((error == HOST_NOT_FOUND) && !haveDNS) {
+                               if ((error == EAI_NODATA) && !targetPrivate->haveDNS) {
                                        /*
                                         * No DNS servers are defined. Set flags based on
                                         * the availability of configured (but not active)
                                         * services.
                                         */
-                                       ok = checkAddressZero(storeP, &my_flags, &my_index);
+                                       ok = checkAddress(storeP, NULL, &my_flags, &my_index);
                                        if (!ok) {
                                                goto error;     /* not today */
                                        }
@@ -1958,13 +2019,13 @@ __SCNetworkReachabilityGetFlags(SCDynamicStoreRef               *storeP,
        }
 
        *flags = my_flags;
-       if (if_index) {
+       if (if_index != NULL) {
                *if_index = my_index;
        }
 
     error :
 
-       if (addresses)  CFRelease(addresses);
+       if (addresses != NULL)  CFRelease(addresses);
        return ok;
 }
 
@@ -1982,15 +2043,15 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef  target,
                return FALSE;
        }
 
-       if (targetPrivate->rlList) {
-               /* if being watched, return current (OK, last known) status */
+       if (targetPrivate->rlList != NULL) {
+               // if being watched, return the last known (and what should be current) status
                *flags = targetPrivate->flags & ~kSCNetworkFlagsFirstResolvePending;
                return TRUE;
        }
 
        ok = __SCNetworkReachabilityGetFlags(&store, target, flags, NULL, FALSE);
        *flags &= ~kSCNetworkFlagsFirstResolvePending;
-       if (store)      CFRelease(store);
+       if (store != NULL)      CFRelease(store);
        return ok;
 }
 
@@ -1998,6 +2059,7 @@ SCNetworkReachabilityGetFlags(SCNetworkReachabilityRef    target,
 static void
 __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef  store)
 {
+       CFStringRef                     dns_key;
        CFStringRef                     key;
        CFMutableArrayRef               keys;
        CFStringRef                     pattern;
@@ -2006,34 +2068,30 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef   store)
        keys     = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 
-       /*
-        * Setup:/Network/Global/IPv4 (for the ServiceOrder)
-        */
+       // Setup:/Network/Global/IPv4 (for the ServiceOrder)
        key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
                                                         kSCDynamicStoreDomainSetup,
                                                         kSCEntNetIPv4);
        CFArrayAppendValue(keys, key);
        CFRelease(key);
 
-       /*
-        * State:/Network/Global/DNS
-        */
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
-                                                        kSCDynamicStoreDomainState,
-                                                        kSCEntNetDNS);
+       // Notify:com.apple.SystemConfiguration.dns_configuration
+       dns_key = CFStringCreateWithCString(NULL,
+                                           dns_configuration_notify_key(),
+                                           kCFStringEncodingASCII);
+       key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), dns_key);
+       CFRelease(dns_key);
        CFArrayAppendValue(keys, key);
        CFRelease(key);
 
-       /*
-        * State:/Network/Global/IPv4
-        */
+       // State:/Network/Global/IPv4 (default route)
        key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
                                                         kSCDynamicStoreDomainState,
                                                         kSCEntNetIPv4);
        CFArrayAppendValue(keys, key);
        CFRelease(key);
 
-       /* Setup: per-service IPv4 info */
+       // Setup: per-service IPv4 info
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -2041,7 +2099,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* Setup: per-service Interface info */
+       // Setup: per-service Interface info
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -2049,7 +2107,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* Setup: per-service PPP info */
+       // Setup: per-service PPP info (for kSCPropNetPPPDialOnDemand)
        pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
                                                              kSCDynamicStoreDomainSetup,
                                                              kSCCompAnyRegex,
@@ -2057,15 +2115,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef    store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* State: per-service IPv4 info */
-       pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
-                                                             kSCDynamicStoreDomainState,
-                                                             kSCCompAnyRegex,
-                                                             kSCEntNetIPv4);
-       CFArrayAppendValue(patterns, pattern);
-       CFRelease(pattern);
-
-       /* State: per-interface IPv4 info */
+       // State: per-interface IPv4 info
        pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                                kSCDynamicStoreDomainState,
                                                                kSCCompAnyRegex,
@@ -2073,7 +2123,7 @@ __SCNetworkReachabilityReachabilitySetNotifications(SCDynamicStoreRef     store)
        CFArrayAppendValue(patterns, pattern);
        CFRelease(pattern);
 
-       /* State: per-interface IPv6 info */
+       // State: per-interface IPv6 info
        pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
                                                                kSCDynamicStoreDomainState,
                                                                kSCCompAnyRegex,
@@ -2094,12 +2144,13 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef      store,
                                                 CFArrayRef             changedKeys,
                                                 void                   *info)
 {
-       Boolean         dnsChanged      = FALSE;
+       Boolean         dnsConfigChanged        = FALSE;
+       CFStringRef     dnsKey;
        CFIndex         i;
        CFStringRef     key;
        CFIndex         nTargets;
        const void *    targets_q[N_QUICK];
-       const void **   targets         = targets_q;
+       const void **   targets                 = targets_q;
 
        pthread_mutex_lock(&hn_lock);
 
@@ -2116,35 +2167,20 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef      store,
 
        SCLog(_sc_debug, LOG_INFO, CFSTR("process configuration change"));
 
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
-                                                        kSCDynamicStoreDomainState,
-                                                        kSCEntNetDNS);
+       dnsKey = CFStringCreateWithCString(NULL,
+                                          dns_configuration_notify_key(),
+                                          kCFStringEncodingASCII);
+       key = CFStringCreateWithFormat(NULL, NULL, CFSTR("Notify:%@"), dnsKey);
+       CFRelease(dnsKey);
        if (CFArrayContainsValue(changedKeys,
                                 CFRangeMake(0, CFArrayGetCount(changedKeys)),
                                 key)) {
-               dnsChanged = TRUE;      /* the DNS server(s) have changed */
-               needDNS    = TRUE;      /* ... and we need to res_init() on the next query */
-       }
-       CFRelease(key);
+               dnsConfigChanged = TRUE;        /* the DNS server(s) have changed */
 
-       if (!dnsChanged) {
-               /*
-                * if the DNS configuration didn't change we still need to
-                * check that the DNS servers are accessible.
-                */
-               Boolean                         haveDNS         = FALSE;
-               SCNetworkConnectionFlags        ns_flags;
-               Boolean                         ok;
-
-               /* check the reachability of the DNS servers */
-               ok = checkResolverReachability(&store, &ns_flags, &haveDNS);\
-               if (!ok || (rankReachability(ns_flags) < 2)) {
-                       /* if DNS servers are not reachable */
-                       dnsChanged = TRUE;
-               }
        }
+       CFRelease(key);
 
-       SCLog(_sc_debug && dnsChanged, LOG_INFO, CFSTR("  DNS changed"));
+       SCLog(_sc_debug && dnsConfigChanged, LOG_INFO, CFSTR("  DNS configuration changed"));
 
        if (nTargets > (CFIndex)(sizeof(targets_q) / sizeof(CFTypeRef)))
                targets = CFAllocatorAllocate(NULL, nTargets * sizeof(CFTypeRef), 0);
@@ -2155,26 +2191,51 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef      store,
 
                pthread_mutex_lock(&targetPrivate->lock);
 
-               if (dnsChanged) {
-                       if (targetPrivate->dnsPort) {
-                               /* cancel the outstanding DNS query */
-#ifdef CHECK_IPV6_REACHABILITY
-                               lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#else  /* CHECK_IPV6_REACHABILITY */
-                               getipnodebyname_async_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#endif /* CHECK_IPV6_REACHABILITY */
-                               CFRelease(targetPrivate->dnsRLS);
-                               targetPrivate->dnsRLS = NULL;
-                               CFRelease(targetPrivate->dnsPort);
-                               targetPrivate->dnsPort = NULL;
+               if (targetPrivate->type == reachabilityTypeName) {
+                       Boolean         dnsChanged      = dnsConfigChanged;
+
+                       if (!dnsChanged) {
+                               /*
+                                * if the DNS configuration didn't change we still need to
+                                * check that the DNS servers are accessible.
+                                */
+                               SCNetworkConnectionFlags        ns_flags;
+                               Boolean                         ok;
+
+                               /* check the reachability of the DNS servers */
+                               ok = _SC_checkResolverReachability(&store,
+                                                                  &ns_flags,
+                                                                  &targetPrivate->haveDNS,
+                                                                  targetPrivate->name);
+                               if (!ok || (rankReachability(ns_flags) < 2)) {
+                                       /* if DNS servers are not reachable */
+                                       dnsChanged = TRUE;
+                               }
                        }
 
-                       /* schedule request to resolve the name again */
-                       __SCNetworkReachabilitySetResolvedAddress(target, NULL, NETDB_SUCCESS);
+                       if (dnsChanged) {
+                               if (targetPrivate->dnsPort) {
+                                       /* cancel the outstanding DNS query */
+                                       lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
+                                       CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
+                                       CFRelease(targetPrivate->dnsRLS);
+                                       targetPrivate->dnsRLS = NULL;
+                                       CFRelease(targetPrivate->dnsPort);
+                                       targetPrivate->dnsPort = NULL;
+                               }
+
+                               /* schedule request to resolve the name again */
+                               if (targetPrivate->resolvedAddress != NULL) {
+                                       CFRelease(targetPrivate->resolvedAddress);
+                                       targetPrivate->resolvedAddress = NULL;
+                               }
+                               targetPrivate->resolvedAddress      = NULL;
+                               targetPrivate->resolvedAddressError = NETDB_SUCCESS;
+                       }
                }
 
                CFRunLoopSourceSignal(targetPrivate->rls);
-               __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+               _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
 
                pthread_mutex_unlock(&targetPrivate->lock);
        }
@@ -2187,78 +2248,6 @@ __SCNetworkReachabilityReachabilityHandleChanges(SCDynamicStoreRef       store,
 }
 
 
-static Boolean
-__isScheduled(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
-       CFIndex i;
-       CFIndex n       = CFArrayGetCount(rlList);
-
-       for (i = 0; i < n; i += 3) {
-               if (obj         && !CFEqual(obj,         CFArrayGetValueAtIndex(rlList, i))) {
-                       continue;
-               }
-               if (runLoop     && !CFEqual(runLoop,     CFArrayGetValueAtIndex(rlList, i+1))) {
-                       continue;
-               }
-               if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
-                       continue;
-               }
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-
-static void
-__schedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList)
-{
-       CFArrayAppendValue(rlList, obj);
-       CFArrayAppendValue(rlList, runLoop);
-       CFArrayAppendValue(rlList, runLoopMode);
-
-       return;
-}
-
-
-static Boolean
-__unschedule(CFTypeRef obj, CFRunLoopRef runLoop, CFStringRef runLoopMode, CFMutableArrayRef rlList, Boolean all)
-{
-       CFIndex i       = 0;
-       Boolean found   = FALSE;
-       CFIndex n       = CFArrayGetCount(rlList);
-
-       while (i < n) {
-               if (obj         && !CFEqual(obj,         CFArrayGetValueAtIndex(rlList, i))) {
-                       i += 3;
-                       continue;
-               }
-               if (runLoop     && !CFEqual(runLoop,     CFArrayGetValueAtIndex(rlList, i+1))) {
-                       i += 3;
-                       continue;
-               }
-               if (runLoopMode && !CFEqual(runLoopMode, CFArrayGetValueAtIndex(rlList, i+2))) {
-                       i += 3;
-                       continue;
-               }
-
-               found = TRUE;
-
-               CFArrayRemoveValueAtIndex(rlList, i + 2);
-               CFArrayRemoveValueAtIndex(rlList, i + 1);
-               CFArrayRemoveValueAtIndex(rlList, i);
-
-               if (!all) {
-                       return found;
-               }
-
-               n -= 3;
-       }
-
-       return found;
-}
-
-
 static void
 rlsPerform(void *info)
 {
@@ -2278,7 +2267,7 @@ rlsPerform(void *info)
 
        /* update reachability, notify if status changed */
        ok = __SCNetworkReachabilityGetFlags(&store, target, &flags, &if_index, TRUE);
-       if (store) CFRelease(store);
+       if (store != NULL) CFRelease(store);
        if (!ok) {
                /* if reachability status not available */
                flags    = 0;
@@ -2288,8 +2277,15 @@ rlsPerform(void *info)
        if ((targetPrivate->flags == flags) && (targetPrivate->if_index == if_index)) {
                /* if reachability flags and interface have not changed */
                pthread_mutex_unlock(&targetPrivate->lock);
-               SCLog(_sc_debug, LOG_DEBUG, CFSTR("flags/interface match"));
+               SCLog(_sc_debug, LOG_DEBUG,
+                     CFSTR("flags/interface match (now %8.8x/%hu)"),
+                     flags, if_index);
                return;
+       } else {
+               SCLog(_sc_debug, LOG_DEBUG,
+                     CFSTR("flags/interface have changed (was %8.8x/%hu, now %8.8x/%hu)"),
+                     targetPrivate->flags, targetPrivate->if_index,
+                     flags, if_index);
        }
 
        /* update flags / interface */
@@ -2298,8 +2294,8 @@ rlsPerform(void *info)
 
        /* callout */
        rlsFunction = targetPrivate->rlsFunction;
-       if (NULL != targetPrivate->rlsContext.retain) {
-               context_info    = (void *)targetPrivate->rlsContext.retain(targetPrivate->rlsContext.info);
+       if (targetPrivate->rlsContext.retain != NULL) {
+               context_info    = (void *)(*targetPrivate->rlsContext.retain)(targetPrivate->rlsContext.info);
                context_release = targetPrivate->rlsContext.release;
        } else {
                context_info    = targetPrivate->rlsContext.info;
@@ -2308,13 +2304,12 @@ rlsPerform(void *info)
 
        pthread_mutex_unlock(&targetPrivate->lock);
 
-       if (rlsFunction) {
-               SCLog(_sc_debug, LOG_DEBUG, CFSTR("flags/interface have changed"));
+       if (rlsFunction != NULL) {
                (*rlsFunction)(target, flags, context_info);
        }
 
-       if (context_release) {
-               context_release(context_info);
+       if (context_release != NULL) {
+               (*context_release)(context_info);
        }
 
        return;
@@ -2330,9 +2325,9 @@ SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target,
 
        pthread_mutex_lock(&targetPrivate->lock);
 
-       if (targetPrivate->rlsContext.release) {
+       if (targetPrivate->rlsContext.release != NULL) {
                /* let go of the current context */
-               targetPrivate->rlsContext.release(targetPrivate->rlsContext.info);
+               (*targetPrivate->rlsContext.release)(targetPrivate->rlsContext.info);
        }
 
        targetPrivate->rlsFunction                      = callout;
@@ -2342,8 +2337,8 @@ SCNetworkReachabilitySetCallback(SCNetworkReachabilityRef target,
        targetPrivate->rlsContext.copyDescription       = NULL;
        if (context) {
                bcopy(context, &targetPrivate->rlsContext, sizeof(SCNetworkReachabilityContext));
-               if (context->retain) {
-                       targetPrivate->rlsContext.info = (void *)context->retain(context->info);
+               if (context->retain != NULL) {
+                       targetPrivate->rlsContext.info = (void *)(*context->retain)(context->info);
                }
        }
 
@@ -2372,15 +2367,21 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
        pthread_mutex_lock(&hn_lock);
        pthread_mutex_lock(&targetPrivate->lock);
 
-       if (!hn_store) {
+       if (hn_store == NULL) {
                /*
-                * if we are not monitoring any hosts
+                * if we are not monitoring any hosts, start watching
                 */
+               if (!dns_configuration_watch()) {
+                       // if error
+                       _SCErrorSet(kSCStatusFailed);
+                       goto done;
+               }
+
                hn_store = SCDynamicStoreCreate(NULL,
                                                CFSTR("SCNetworkReachability"),
                                                __SCNetworkReachabilityReachabilityHandleChanges,
                                                NULL);
-               if (!hn_store) {
+               if (hn_store == NULL) {
                        SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
                        goto done;
                }
@@ -2392,7 +2393,7 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target,
                hn_targets  = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
        }
 
-       if (!targetPrivate->rls) {
+       if (targetPrivate->rls == NULL) {
                CFRunLoopSourceContext  context = { 0                   // version
                                                  , (void *)target      // info
                                                  , CFRetain            // retain
@@ -2410,24 +2411,24 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
                init = TRUE;
        }
 
-       if (!__isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
+       if (!_SC_isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
                /*
                 * if we do not already have host notifications scheduled with
                 * this runLoop / runLoopMode
                 */
                CFRunLoopAddSource(runLoop, targetPrivate->rls, runLoopMode);
 
-               if (targetPrivate->dnsRLS) {
+               if (targetPrivate->dnsRLS != NULL) {
                        /* if we have an active async DNS query too */
                        CFRunLoopAddSource(runLoop, targetPrivate->dnsRLS, runLoopMode);
                }
        }
 
-       __schedule(target, runLoop, runLoopMode, targetPrivate->rlList);
+       _SC_schedule(target, runLoop, runLoopMode, targetPrivate->rlList);
 
        /* schedule the SCNetworkReachability run loop source */
 
-       if (!__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
+       if (!_SC_isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
                /*
                 * if we do not already have SC notifications scheduled with
                 * this runLoop / runLoopMode
@@ -2435,7 +2436,7 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef target,
                CFRunLoopAddSource(runLoop, hn_storeRLS, runLoopMode);
        }
 
-       __schedule(target, runLoop, runLoopMode, hn_rlList);
+       _SC_schedule(target, runLoop, runLoopMode, hn_rlList);
        CFSetAddValue(hn_targets, target);
 
        if (init) {
@@ -2456,13 +2457,13 @@ SCNetworkReachabilityScheduleWithRunLoop(SCNetworkReachabilityRef       target,
                        targetPrivate->flags    = flags;
                        targetPrivate->if_index = if_index;
                        CFRunLoopSourceSignal(targetPrivate->rls);
-                       __signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
+                       _SC_signalRunLoop(target, targetPrivate->rls, targetPrivate->rlList);
                } else {
                        /* if reachability status not available, async lookup started */
                        targetPrivate->flags    = 0;
                        targetPrivate->if_index = 0;
                }
-               if (store) CFRelease(store);
+               if (store != NULL) CFRelease(store);
        }
 
        ok = TRUE;
@@ -2492,24 +2493,24 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
        pthread_mutex_lock(&hn_lock);
        pthread_mutex_lock(&targetPrivate->lock);
 
-       if (!targetPrivate->rls) {
+       if (targetPrivate->rls == NULL) {
                /* if not currently scheduled */
                goto done;
        }
 
-       if (!__unschedule(NULL, runLoop, runLoopMode, targetPrivate->rlList, FALSE)) {
+       if (!_SC_unschedule(NULL, runLoop, runLoopMode, targetPrivate->rlList, FALSE)) {
                /* if not currently scheduled */
                goto done;
        }
 
        n = CFArrayGetCount(targetPrivate->rlList);
-       if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
+       if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, targetPrivate->rlList)) {
                /*
                 * if this host is no longer scheduled for this runLoop / runLoopMode
                 */
                CFRunLoopRemoveSource(runLoop, targetPrivate->rls, runLoopMode);
 
-               if (targetPrivate->dnsRLS) {
+               if (targetPrivate->dnsRLS != NULL) {
                        /* if we have an active async DNS query too */
                        CFRunLoopRemoveSource(runLoop, targetPrivate->dnsRLS, runLoopMode);
                }
@@ -2518,19 +2519,17 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
                        /*
                         * if this host is no longer scheduled
                         */
-                       CFRelease(targetPrivate->rls);          /* cleanup SCNetworkReachability resources */
+                       CFRunLoopSourceInvalidate(targetPrivate->rls);  /* cleanup SCNetworkReachability resources */
+                       CFRelease(targetPrivate->rls);
                        targetPrivate->rls = NULL;
                        CFRelease(targetPrivate->rlList);
                        targetPrivate->rlList = NULL;
-                       CFSetRemoveValue(hn_targets, target);   /* cleanup notification resources */
+                       CFSetRemoveValue(hn_targets, target);           /* cleanup notification resources */
 
                        if (targetPrivate->dnsPort) {
                                /* if we have an active async DNS query too */
-#ifdef CHECK_IPV6_REACHABILITY
                                lu_async_call_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#else  /* CHECK_IPV6_REACHABILITY */
-                               getipnodebyname_async_cancel(CFMachPortGetPort(targetPrivate->dnsPort));
-#endif /* CHECK_IPV6_REACHABILITY */
+                               CFRunLoopSourceInvalidate(targetPrivate->dnsRLS);
                                CFRelease(targetPrivate->dnsRLS);
                                targetPrivate->dnsRLS = NULL;
                                CFRelease(targetPrivate->dnsPort);
@@ -2539,10 +2538,10 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
                }
        }
 
-       (void)__unschedule(target, runLoop, runLoopMode, hn_rlList, FALSE);
+       (void)_SC_unschedule(target, runLoop, runLoopMode, hn_rlList, FALSE);
 
        n = CFArrayGetCount(hn_rlList);
-       if (n == 0 || !__isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
+       if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, hn_rlList)) {
                /*
                 * if we no longer have any addresses scheduled for
                 * this runLoop / runLoopMode
@@ -2554,17 +2553,21 @@ SCNetworkReachabilityUnscheduleFromRunLoop(SCNetworkReachabilityRef     target,
                         * if we are no longer monitoring any addresses
                         */
                        CFRelease(hn_targets);
+                       hn_targets = NULL;
                        CFRelease(hn_rlList);
+                       hn_rlList = NULL;
+                       CFRunLoopSourceInvalidate(hn_storeRLS);
                        CFRelease(hn_storeRLS);
+                       hn_storeRLS = NULL;
                        CFRelease(hn_store);
                        hn_store = NULL;
 
                        /*
                         * until we start monitoring again, ensure that
-                        * all subsequent reachability-by-name checks
-                        * call res_init()
+                        * any resources associated with tracking the
+                        * DNS configuration have been released.
                         */
-                       needDNS = TRUE;
+                       dns_configuration_unwatch();
                }
        }
 
index 8efa2d3f6a2ac9fa7c4a6aaa3aa8ecbddc3e07fb..33ffd57788b4f245593cc1985996910d07c6e794 100644 (file)
 
 /*!
        @header SCNetworkReachability
-       The SCNetworkReachabilityXXX() APIs allow an application to determine the status
-       of a system's current network configuration and the reachability
-       of a target host.  In addition, the reachability can be monitored
-       with a notification being provided when/if the status has changed.
-
-       The term "reachable" reflects whether a data packet, sent by
-       an application into the network stack, can be sent to the
-       the target host/address.  Please note that there is no
-       guarantee that the data packet will actually be received by
-       the host.
+       @discussion The SCNetworkReachability API allows an application to
+               determine the status of a system's current network
+               configuration and the reachability of a target host.
+               In addition, reachability can be monitored with notifications
+               that are sent when the status has changed.
+
+               "Reachability" reflects whether a data packet, sent by
+               an application into the network stack, can leave the local
+               computer.
+               Note that reachability does <i>not</i> guarantee that the data
+               packet will actually be received by the host.
  */
 
 /*!
        @typedef SCNetworkReachabilityRef
-       @discussion This is the handle to a network address/name.
+       @discussion This is the handle to a network address or name.
  */
-typedef const struct __SCNetworkReachability * SCNetworkReachabilityRef                AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+typedef const struct __SCNetworkReachability * SCNetworkReachabilityRef;
 
 
 /*!
        @typedef SCNetworkReachabilityContext
+       Structure containing user-specified data and callbacks for SCNetworkReachability.
+       @field version The version number of the structure type being passed
+               in as a parameter to the SCDynamicStore creation function.
+               This structure is version 0.
+       @field info A C pointer to a user-specified block of data.
+       @field retain The callback used to add a retain for the info field.
+               If this parameter is not a pointer to a function of the correct
+               prototype, the behavior is undefined.  The value may be NULL.
+       @field release The calllback used to remove a retain previously added
+               for the info field.  If this parameter is not a pointer to a
+               function of the correct prototype, the behavior is undefined.
+               The value may be NULL.
+       @field copyDescription The callback used to provide a description of
+               the info field.
  */
 typedef struct {
        CFIndex         version;
@@ -61,32 +76,33 @@ typedef struct {
        const void      *(*retain)(const void *info);
        void            (*release)(const void *info);
        CFStringRef     (*copyDescription)(const void *info);
-} SCNetworkReachabilityContext                                                 AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+} SCNetworkReachabilityContext;
 
 /*!
        @typedef SCNetworkReachabilityCallBack
        @discussion Type of the callback function used when the
-               reachability of a network address/name changes.
-       @param target The SCNetworkReachability reference being monitored for changes.
+               reachability of a network address or name changes.
+       @param target The SCNetworkReachability reference being monitored
+               for changes.
        @param flags The new SCNetworkConnectionFlags representing the
                reachability status of the network address/name.
-       @param info ....
+       @param info A C pointer to a user-specified block of data.
  */
 typedef void (*SCNetworkReachabilityCallBack)  (
                                                SCNetworkReachabilityRef        target,
                                                SCNetworkConnectionFlags        flags,
                                                void                            *info
-                                               )                               AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+                                               );
 
 __BEGIN_DECLS
 
 /*!
        @function SCNetworkReachabilityCreateWithAddress
        @discussion Creates a reference to the specified network
-               address.  This reference can later be used to monitor
-               the reachability of the target host.
+               address.  This reference can be used later to monitor the
+               reachability of the target host.
        @param address The address of the desired host.
-       @result A reference to the new immutable SCNetworkReachabilityRef.
+       @result Returns a reference to the new immutable SCNetworkReachabilityRef.
 
                 You must release the returned value.
  */
@@ -99,13 +115,13 @@ SCNetworkReachabilityCreateWithAddress             (
 /*!
        @function SCNetworkReachabilityCreateWithAddressPair
        @discussion Creates a reference to the specified network
-               address.  This reference can later be used to monitor
-               the reachability of the target host.
+               address.  This reference can be used later to monitor the
+               reachability of the target host.
        @param localAddress The local address associated with a network
                connection.  If NULL, only the remote address is of interest.
        @param remoteAddress The remote address associated with a network
                connection.  If NULL, only the local address is of interest.
-       @result A reference to the new immutable SCNetworkReachabilityRef.
+       @result Returns a reference to the new immutable SCNetworkReachabilityRef.
 
                 You must release the returned value.
  */
@@ -118,12 +134,13 @@ SCNetworkReachabilityCreateWithAddressPair        (
 
 /*!
        @function SCNetworkReachabilityCreateWithName
-       @discussion Creates a reference to the specified network host/node
-               name.  This reference can later be used to monitor the
+       @discussion Creates a reference to the specified network host or node
+               name.  This reference can be used later to monitor the
                reachability of the target host.
-       @param nodename The node name of the desired host. This name would
-               be the same as that passed to gethostbyname() or getaddrinfo().
-       @result A reference to the new immutable SCNetworkReachabilityRef.
+       @param nodename The node name of the desired host.
+               This name would be the same as that passed to the
+               gethostbyname(3) or getaddrinfo(3) functions.
+       @result Returns a reference to the new immutable SCNetworkReachabilityRef.
 
                You must release the returned value.
  */
@@ -135,7 +152,8 @@ SCNetworkReachabilityCreateWithName         (
 
 /*!
        @function SCNetworkReachabilityGetTypeID
-       Returns the type identifier of all SCNetworkReachability instances.
+       @discussion Returns the type identifier of all SCNetworkReachability
+               instances.
  */
 CFTypeID
 SCNetworkReachabilityGetTypeID                 (void)                          AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
@@ -145,13 +163,13 @@ SCNetworkReachabilityGetTypeID                    (void)                          AVAILABLE_MAC_OS_X_VERSION_10_3_AND_L
        @function SCNetworkReachabilityGetFlags
        @discussion Determines if the given target is reachable using the
                current network configuration.
-       @param target The network reference associated with the address/name
+       @param target The network reference associated with the address or name
                to be checked for reachability.
        @param flags A pointer to memory that will be filled with the
                SCNetworkConnectionFlags detailing the reachability
                of the specified target.
-       @result TRUE if the network connection flags are valid; FALSE if the
-               status could not be determined.
+       @result Returns TRUE if the network connection flags are valid;
+               FALSE if the status could not be determined.
  */
 Boolean
 SCNetworkReachabilityGetFlags                  (
@@ -163,14 +181,14 @@ SCNetworkReachabilityGetFlags                     (
        @function SCNetworkReachabilitySetCallback
        @discussion Assigns a client to a target, which receives callbacks
                when the reachability of the target changes.
-       @param target The network reference associated with the address/name
-               to be checked for reachability.
-       @param callout The function to be called when the reachability of
+       @param target The network reference associated with the address or
+               name to be checked for reachability.
+       @param callout The function to be called when the reachability of the
                target changes.  If NULL, the current client for the target
                is removed.
        @param context The SCNetworkReachabilityContext associated with
-               the callout.
-       @result TRUE if the notification client was successfully set.
+               the callout.  The value may be NULL.
+       @result Returns TRUE if the notification client was successfully set.
  */
 Boolean
 SCNetworkReachabilitySetCallback               (
@@ -181,10 +199,15 @@ SCNetworkReachabilitySetCallback          (
 
 /*!
        @function SCNetworkReachabilityScheduleWithRunLoop
-       @discussion Schedule the given target from the given run loop and mode.
-       @param target The address/name which is set up for asynchronous mode.  Must be non-NULL.
-       @param runLoop A reference to a runloop on which the target should be scheduled.  Must be non-NULL.
-       @param runLoopMode The mode on which to schedule the target.  Must be non-NULL.
+       @discussion Schedules the given target with the given run loop and mode.
+       @param target The address or name that is set up for asynchronous
+               notifications.  Must be non-NULL.
+       @param runLoop A reference to a run loop on which the target should
+               be scheduled.  Must be non-NULL.
+       @param runLoopMode The mode on which to schedule the target.
+               Must be non-NULL.
+       @result Returns TRUE if the target is scheduled successfully;
+               FALSE otherwise.
  */
 Boolean
 SCNetworkReachabilityScheduleWithRunLoop       (
@@ -195,10 +218,16 @@ SCNetworkReachabilityScheduleWithRunLoop  (
 
 /*!
        @function SCNetworkReachabilityUnscheduleFromRunLoop
-       @discussion Unschedule the given target from the given run loop and mode.
-       @param target The address/name which is set up for asynchronous mode.  Must be non-NULL.
-       @param runLoop A reference to a runloop on which the target should be scheduled.  Must be non-NULL.
-       @param runLoopMode The mode on which to schedule the target.  Must be non-NULL.
+       @discussion Unschedules the given target from the given run loop
+               and mode.
+       @param target The address or name that is set up for asynchronous
+               notifications.  Must be non-NULL.
+       @param runLoop A reference to a run loop from which the target
+               should be unscheduled.  Must be non-NULL.
+       @param runLoopMode The mode on which to unschedule the target.
+               Must be non-NULL.
+       @result Returns TRUE if the target is unscheduled successfully;
+               FALSE otherwise.
  */
 Boolean
 SCNetworkReachabilityUnscheduleFromRunLoop     (
diff --git a/SystemConfiguration.fproj/SCNetworkService.c b/SystemConfiguration.fproj/SCNetworkService.c
new file mode 100644 (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@
  * 
@@ -160,14 +160,19 @@ __SCPreferencesPath(CFAllocatorRef        allocator,
 
 
 CFDataRef
-SCPreferencesGetSignature(SCPreferencesRef session)
+SCPreferencesGetSignature(SCPreferencesRef prefs)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesGetSignature:"));
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return NULL;
+       }
+
+       __SCPreferencesAccess(prefs);
 
-       sessionPrivate->accessed = TRUE;
-       return sessionPrivate->signature;
+       return prefsPrivate->signature;
 }
 
 
@@ -178,39 +183,45 @@ _SCPNotificationKey(CFAllocatorRef        allocator,
                    CFStringRef         user,
                    int                 keyType)
 {
-       CFStringRef     key             = NULL;
-       char            *pathStr;
-       char            *typeStr;
+       CFStringRef     keyStr;
+       char            *path;
+       CFStringRef     pathStr;
+       CFStringRef     storeKey;
 
-       pathStr = __SCPreferencesPath(allocator, prefsID, perUser, user, TRUE);
-       if (pathStr == NULL) {
-               return NULL;
-       }
-
-       /* create notification key */
        switch (keyType) {
                case kSCPreferencesKeyLock :
-                       typeStr = "lock";
+                       keyStr = CFSTR("lock");
                        break;
                case kSCPreferencesKeyCommit :
-                       typeStr = "commit";
+                       keyStr = CFSTR("commit");
                        break;
                case kSCPreferencesKeyApply :
-                       typeStr = "apply";
+                       keyStr = CFSTR("apply");
                        break;
                default :
-                       typeStr = "?";
+                       return NULL;
        }
 
-       key = CFStringCreateWithFormat(allocator,
-                                      NULL,
-                                      CFSTR("%@%s:%s"),
-                                      kSCDynamicStoreDomainPrefs,
-                                      typeStr,
-                                      pathStr);
+       path = __SCPreferencesPath(allocator, prefsID, perUser, user, TRUE);
+       if (path == NULL) {
+               return NULL;
+       }
 
-       CFAllocatorDeallocate(NULL, pathStr);
-       return key;
+       pathStr = CFStringCreateWithCStringNoCopy(allocator,
+                                                 path,
+                                                 kCFStringEncodingASCII,
+                                                 kCFAllocatorNull);
+
+       storeKey = CFStringCreateWithFormat(allocator,
+                                           NULL,
+                                           CFSTR("%@%@:%@"),
+                                           kSCDynamicStoreDomainPrefs,
+                                           keyStr,
+                                           pathStr);
+
+       CFRelease(pathStr);
+       CFAllocatorDeallocate(NULL, path);
+       return storeKey;
 }
 
 
index 963c2f068c6d212f9b1d9214f382066f6f44532f..420fe3223f29a27f5b12e213439f487f067ecbb5 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
-SCPreferencesAddValue(SCPreferencesRef session, CFStringRef key, CFPropertyListRef value)
+SCPreferencesAddValue(SCPreferencesRef prefs, CFStringRef key, CFPropertyListRef value)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesAddValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key   = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value = %@"), value);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
        }
 
-       sessionPrivate->accessed = TRUE;
+       __SCPreferencesAccess(prefs);
 
-       if (CFDictionaryContainsKey(sessionPrivate->prefs, key)) {
+       if (CFDictionaryContainsKey(prefsPrivate->prefs, key)) {
                _SCErrorSet(kSCStatusKeyExists);
                return FALSE;
        }
 
-       CFDictionaryAddValue(sessionPrivate->prefs, key, value);
-       sessionPrivate->changed  = TRUE;
+       CFDictionaryAddValue(prefsPrivate->prefs, key, value);
+       prefsPrivate->changed  = TRUE;
        return TRUE;
 }
index 951eb4fdc287d5af3c9293239c05cd93b436b46d..775036f3a1cbb984d9694819d2cb5f02821de4de 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
-SCPreferencesApplyChanges(SCPreferencesRef session)
+SCPreferencesApplyChanges(SCPreferencesRef prefs)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        Boolean                 wasLocked;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges:"));
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
 
        /*
         * Determine if the we have exclusive access to the preferences
         * and acquire the lock if necessary.
         */
-       wasLocked = sessionPrivate->locked;
+       wasLocked = prefsPrivate->locked;
        if (!wasLocked) {
-               if (!SCPreferencesLock(session, TRUE)) {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  SCPreferencesLock() failed"));
+               if (!SCPreferencesLock(prefs, TRUE)) {
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges SCPreferencesLock() failed"));
                        return FALSE;
                }
        }
 
-       if (!sessionPrivate->isRoot) {
+       if (!prefsPrivate->isRoot) {
                /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
                goto perUser;
        }
 
-       /* if necessary, create the session "apply" key */
-       if (sessionPrivate->sessionKeyApply == NULL) {
-               sessionPrivate->sessionKeyApply = _SCPNotificationKey(NULL,
-                                                                     sessionPrivate->prefsID,
-                                                                     sessionPrivate->perUser,
-                                                                     sessionPrivate->user,
-                                                                     kSCPreferencesKeyApply);
-       }
-
        /* post notification */
-       if (!SCDynamicStoreNotifyValue(sessionPrivate->session,
-                                      sessionPrivate->sessionKeyApply)) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  SCDynamicStoreNotifyValue() failed"));
+       if (!SCDynamicStoreNotifyValue(prefsPrivate->session,
+                                      prefsPrivate->sessionKeyApply)) {
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesApplyChanges SCDynamicStoreNotifyValue() failed"));
                _SCErrorSet(kSCStatusFailed);
                goto error;
        }
 
     perUser :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
        return TRUE;
 
     error :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
        return FALSE;
 }
index 8998e4bcd7a04c9c4008348c058d3c691d216a05..0ea6dc9a53e580a98f500ad00b5a1f35b6041cac 100644 (file)
@@ -63,21 +63,25 @@ writen(int d, const void *buf, size_t nbytes)
 
 
 Boolean
-SCPreferencesCommitChanges(SCPreferencesRef session)
+SCPreferencesCommitChanges(SCPreferencesRef prefs)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        Boolean                 wasLocked;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCommitChanges:"));
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
 
        /*
         * Determine if the we have exclusive access to the preferences
         * and acquire the lock if necessary.
         */
-       wasLocked = sessionPrivate->locked;
+       wasLocked = prefsPrivate->locked;
        if (!wasLocked) {
-               if (!SCPreferencesLock(session, TRUE)) {
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  SCPreferencesLock() failed"));
+               if (!SCPreferencesLock(prefs, TRUE)) {
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges SCPreferencesLock() failed"));
                        return FALSE;
                }
        }
@@ -85,7 +89,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
        /*
         * if necessary, apply changes
         */
-       if (sessionPrivate->changed) {
+       if (prefsPrivate->changed) {
                int             fd;
                CFDataRef       newPrefs;
                char *          path;
@@ -93,20 +97,20 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
                struct stat     statBuf;
                char *          thePath;
 
-               if (stat(sessionPrivate->path, &statBuf) == -1) {
+               if (stat(prefsPrivate->path, &statBuf) == -1) {
                        if (errno == ENOENT) {
                                bzero(&statBuf, sizeof(statBuf));
                                statBuf.st_mode = 0644;
                                statBuf.st_uid  = geteuid();
                                statBuf.st_gid  = getegid();
                        } else {
-                               SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno));
+                               SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges stat() failed: %s"), strerror(errno));
                                goto error;
                        }
                }
 
                /* create the (new) preferences file */
-               path = sessionPrivate->newPath ? sessionPrivate->newPath : sessionPrivate->path;
+               path = prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path;
                pathLen = strlen(path) + sizeof("-new");
                thePath = CFAllocatorAllocate(NULL, pathLen, 0);
                snprintf(thePath, pathLen, "%s-new", path);
@@ -116,7 +120,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
                fd = open(thePath, O_WRONLY|O_CREAT, statBuf.st_mode);
                if (fd == -1) {
                        if ((errno == ENOENT) &&
-                           ((sessionPrivate->prefsID == NULL) || !CFStringHasPrefix(sessionPrivate->prefsID, CFSTR("/")))) {
+                           ((prefsPrivate->prefsID == NULL) || !CFStringHasPrefix(prefsPrivate->prefsID, CFSTR("/")))) {
                                char    *ch;
 
                                ch = strrchr(thePath, '/');
@@ -131,7 +135,7 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
                                        }
                                }
                        }
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPCommit open() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges open() failed: %s"), strerror(errno));
                        CFAllocatorDeallocate(NULL, thePath);
                        goto error;
                }
@@ -141,84 +145,97 @@ SCPreferencesCommitChanges(SCPreferencesRef session)
                (void) fchmod(fd, statBuf.st_mode);
 
                /* write the new preferences */
-               newPrefs = CFPropertyListCreateXMLData(NULL, sessionPrivate->prefs);
+               newPrefs = CFPropertyListCreateXMLData(NULL, prefsPrivate->prefs);
                if (!newPrefs) {
                        _SCErrorSet(kSCStatusFailed);
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  CFPropertyListCreateXMLData() failed"));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges CFPropertyListCreateXMLData() failed"));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  prefs = %s"), path);
                        CFAllocatorDeallocate(NULL, thePath);
                        (void) close(fd);
                        goto error;
                }
                if (writen(fd, (void *)CFDataGetBytePtr(newPrefs), CFDataGetLength(newPrefs)) == -1) {
                        _SCErrorSet(errno);
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("write() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges write() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  path = %s"), thePath);
+                       (void) unlink(thePath);
+                       CFAllocatorDeallocate(NULL, thePath);
+                       (void) close(fd);
+                       CFRelease(newPrefs);
+                       goto error;
+               }
+               if (fsync(fd) == -1) {
+                       _SCErrorSet(errno);
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges fsync() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  path = %s"), thePath);
                        (void) unlink(thePath);
                        CFAllocatorDeallocate(NULL, thePath);
                        (void) close(fd);
                        CFRelease(newPrefs);
                        goto error;
                }
-               (void) close(fd);
+               if (close(fd) == -1) {
+                       _SCErrorSet(errno);
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges close() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  path = %s"), thePath);
+                       (void) unlink(thePath);
+                       CFAllocatorDeallocate(NULL, thePath);
+                       CFRelease(newPrefs);
+                       goto error;
+               }
                CFRelease(newPrefs);
 
                /* rename new->old */
                if (rename(thePath, path) == -1) {
                        _SCErrorSet(errno);
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("rename() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges rename() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  path = %s --> %s"), thePath, path);
                        CFAllocatorDeallocate(NULL, thePath);
                        goto error;
                }
                CFAllocatorDeallocate(NULL, thePath);
 
-               if (sessionPrivate->newPath) {
+               if (prefsPrivate->newPath) {
                        /* prefs file saved in "new" directory */
-                       (void) unlink(sessionPrivate->path);
-                       (void) symlink(sessionPrivate->newPath, sessionPrivate->path);
-                       CFAllocatorDeallocate(NULL, sessionPrivate->path);
-                       sessionPrivate->path = path;
-                       sessionPrivate->newPath = NULL;
+                       (void) unlink(prefsPrivate->path);
+                       (void) symlink(prefsPrivate->newPath, prefsPrivate->path);
+                       CFAllocatorDeallocate(NULL, prefsPrivate->path);
+                       prefsPrivate->path = path;
+                       prefsPrivate->newPath = NULL;
                }
 
                /* update signature */
                if (stat(path, &statBuf) == -1) {
                        _SCErrorSet(errno);
-                       SCLog(_sc_verbose, LOG_ERR, CFSTR("stat() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges stat() failed: %s"), strerror(errno));
+                       SCLog(_sc_verbose, LOG_ERR, CFSTR("  path = %s"), thePath);
                        goto error;
                }
-               CFRelease(sessionPrivate->signature);
-               sessionPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
+               CFRelease(prefsPrivate->signature);
+               prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
        }
 
-       if (!sessionPrivate->isRoot) {
+       if (!prefsPrivate->isRoot) {
                /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
                goto perUser;
        }
 
-       /* if necessary, create the session "commit" key */
-       if (sessionPrivate->sessionKeyCommit == NULL) {
-               sessionPrivate->sessionKeyCommit = _SCPNotificationKey(NULL,
-                                                                      sessionPrivate->prefsID,
-                                                                      sessionPrivate->perUser,
-                                                                      sessionPrivate->user,
-                                                                      kSCPreferencesKeyCommit);
-       }
-
        /* post notification */
-       if (!SCDynamicStoreNotifyValue(sessionPrivate->session,
-                                      sessionPrivate->sessionKeyCommit)) {
-               SCLog(_sc_verbose, LOG_ERR, CFSTR("  SCDynamicStoreNotifyValue() failed"));
+       if (!SCDynamicStoreNotifyValue(prefsPrivate->session,
+                                      prefsPrivate->sessionKeyCommit)) {
+               SCLog(_sc_verbose, LOG_ERR, CFSTR("SCPreferencesCommitChanges SCDynamicStoreNotifyValue() failed"));
                _SCErrorSet(kSCStatusFailed);
                goto error;
        }
 
     perUser :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
-       sessionPrivate->changed = FALSE;
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
+       prefsPrivate->changed = FALSE;
        return TRUE;
 
     error :
 
-       if (!wasLocked) (void) SCPreferencesUnlock(session);
+       if (!wasLocked) (void) SCPreferencesUnlock(prefs);
        return FALSE;
 }
index 896d27c6c5ade02c476328e70b84f337ec643b93..297107ec1871b4b41a82c40d0087641153e45885 100644 (file)
 #include "SCPreferencesInternal.h"
 
 CFPropertyListRef
-SCPreferencesGetValue(SCPreferencesRef session, CFStringRef key)
+SCPreferencesGetValue(SCPreferencesRef prefs, CFStringRef key)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        CFPropertyListRef       value;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesGetValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key   = %@"), key);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return NULL;
        }
 
-       sessionPrivate->accessed = TRUE;
-       value = CFDictionaryGetValue(sessionPrivate->prefs, key);
-       if (!value) {
+       __SCPreferencesAccess(prefs);
+
+       value = CFDictionaryGetValue(prefsPrivate->prefs, key);
+       if (value == NULL) {
                _SCErrorSet(kSCStatusNoKey);
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value = %@"), value);
        return value;
 }
index 1626811c08409faad29413e1fe153ee455abfa3d..8a4266f3cf17ebf4ec9eac325f3614cae26b2370 100644 (file)
 #include "SCPreferencesInternal.h"
 
 CFArrayRef
-SCPreferencesCopyKeyList(SCPreferencesRef session)
+SCPreferencesCopyKeyList(SCPreferencesRef prefs)
 {
-       CFAllocatorRef          allocator       = CFGetAllocator(session);
+       CFAllocatorRef          allocator       = CFGetAllocator(prefs);
        CFArrayRef              keys;
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        CFIndex                 prefsCnt;
        const void **           prefsKeys;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesCopyKeyList:"));
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return NULL;
+       }
+
+       __SCPreferencesAccess(prefs);
 
-       prefsCnt  = CFDictionaryGetCount(sessionPrivate->prefs);
+       prefsCnt  = CFDictionaryGetCount(prefsPrivate->prefs);
        if (prefsCnt > 0) {
                prefsKeys = CFAllocatorAllocate(allocator, prefsCnt * sizeof(CFStringRef), 0);
-               CFDictionaryGetKeysAndValues(sessionPrivate->prefs, prefsKeys, NULL);
+               CFDictionaryGetKeysAndValues(prefsPrivate->prefs, prefsKeys, NULL);
                keys = CFArrayCreate(allocator, prefsKeys, prefsCnt, &kCFTypeArrayCallBacks);
                CFAllocatorDeallocate(allocator, prefsKeys);
        } else {
                keys = CFArrayCreate(allocator, NULL, 0, &kCFTypeArrayCallBacks);
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  keys = %@"), keys);
-
-       sessionPrivate->accessed = TRUE;
        return keys;
 }
index 88bd2819c8c0d890a53b3f3f4a447848be5bf9c4..f7b155170cfb7d3cbd91062410f05f79fe232dcd 100644 (file)
 
 #include <fcntl.h>
 #include <unistd.h>
+#include <pthread.h>
 #include <sys/errno.h>
 
 Boolean
-SCPreferencesLock(SCPreferencesRef session, Boolean wait)
+SCPreferencesLock(SCPreferencesRef prefs, Boolean wait)
 {
-       CFAllocatorRef          allocator               = CFGetAllocator(session);
+       CFAllocatorRef          allocator               = CFGetAllocator(prefs);
        CFArrayRef              changes;
-       CFDataRef               currentSignature        = NULL;
        Boolean                 haveLock                = FALSE;
-       SCPreferencesPrivateRef sessionPrivate          = (SCPreferencesPrivateRef)session;
-       struct stat             statBuf;
+       SCPreferencesPrivateRef prefsPrivate            = (SCPreferencesPrivateRef)prefs;
        CFDateRef               value                   = NULL;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesLock:"));
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
 
-       if (sessionPrivate->locked) {
+       if (prefsPrivate->locked) {
                /* sorry, you already have the lock */
                _SCErrorSet(kSCStatusLocked);
                return FALSE;
        }
 
-       if (!sessionPrivate->isRoot) {
-               if (!sessionPrivate->perUser) {
+       if (!prefsPrivate->isRoot) {
+               if (!prefsPrivate->perUser) {
                        _SCErrorSet(kSCStatusAccessError);
                        return FALSE;
                } else {
@@ -68,35 +71,31 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
                }
        }
 
-       if (sessionPrivate->session == NULL) {
-               /* open a session */
-               sessionPrivate->session = SCDynamicStoreCreate(allocator,
-                                                              CFSTR("SCPreferencesLock"),
-                                                              NULL,
-                                                              NULL);
-               if (!sessionPrivate->session) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
-                       return FALSE;
-               }
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       if (prefsPrivate->session == NULL) {
+               __SCPreferencesAddSession(prefs);
        }
 
-       if (sessionPrivate->sessionKeyLock == NULL) {
+       if (prefsPrivate->sessionKeyLock == NULL) {
                /* create the session "lock" key */
-               sessionPrivate->sessionKeyLock = _SCPNotificationKey(allocator,
-                                                                    sessionPrivate->prefsID,
-                                                                    sessionPrivate->perUser,
-                                                                    sessionPrivate->user,
-                                                                    kSCPreferencesKeyLock);
+               prefsPrivate->sessionKeyLock = _SCPNotificationKey(allocator,
+                                                                  prefsPrivate->prefsID,
+                                                                  prefsPrivate->perUser,
+                                                                  prefsPrivate->user,
+                                                                  kSCPreferencesKeyLock);
        }
 
-       if (!SCDynamicStoreAddWatchedKey(sessionPrivate->session,
-                                        sessionPrivate->sessionKeyLock,
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       if (!SCDynamicStoreAddWatchedKey(prefsPrivate->session,
+                                        prefsPrivate->sessionKeyLock,
                                         FALSE)) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreAddWatchedKey() failed"));
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreAddWatchedKey() failed"));
                goto error;
        }
 
-       value  = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent());
+       value = CFDateCreate(allocator, CFAbsoluteTimeGetCurrent());
 
        while (TRUE) {
                CFArrayRef      changedKeys;
@@ -104,8 +103,8 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
                /*
                 * Attempt to acquire the lock
                 */
-               if (SCDynamicStoreAddTemporaryValue(sessionPrivate->session,
-                                                   sessionPrivate->sessionKeyLock,
+               if (SCDynamicStoreAddTemporaryValue(prefsPrivate->session,
+                                                   prefsPrivate->sessionKeyLock,
                                                    value)) {
                        haveLock = TRUE;
                        goto done;
@@ -119,13 +118,13 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
                /*
                 * Wait for the lock to be released
                 */
-               if (!SCDynamicStoreNotifyWait(sessionPrivate->session)) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreNotifyWait() failed"));
+               if (!SCDynamicStoreNotifyWait(prefsPrivate->session)) {
+                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreNotifyWait() failed"));
                        goto error;
                }
-               changedKeys = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session);
+               changedKeys = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
                if (!changedKeys) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
+                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreCopyNotifiedKeys() failed"));
                        goto error;
                }
                CFRelease(changedKeys);
@@ -136,88 +135,71 @@ SCPreferencesLock(SCPreferencesRef session, Boolean wait)
        CFRelease(value);
        value = NULL;
 
-       if (!SCDynamicStoreRemoveWatchedKey(sessionPrivate->session,
-                                           sessionPrivate->sessionKeyLock,
+       if (!SCDynamicStoreRemoveWatchedKey(prefsPrivate->session,
+                                           prefsPrivate->sessionKeyLock,
                                            0)) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveWatchedKey() failed"));
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreRemoveWatchedKey() failed"));
                goto error;
        }
 
-       changes = SCDynamicStoreCopyNotifiedKeys(sessionPrivate->session);
+       changes = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
        if (!changes) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCopyNotifiedKeys() failed"));
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesLock SCDynamicStoreCopyNotifiedKeys() failed"));
                goto error;
        }
        CFRelease(changes);
 
     perUser:
 
-       /*
-        * Check the signature
-        */
-       if (stat(sessionPrivate->path, &statBuf) == -1) {
-               if (errno == ENOENT) {
-                       bzero(&statBuf, sizeof(statBuf));
-               } else {
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("stat() failed: %s"), strerror(errno));
-                       _SCErrorSet(kSCStatusStale);
-                       goto error;
+       if (prefsPrivate->accessed) {
+               CFDataRef       currentSignature;
+               Boolean         match;
+               struct stat     statBuf;
+
+               /*
+                * the preferences have been accessed since the
+                * session was created so we need to compare
+                * the signature of the stored preferences.
+                */
+               if (stat(prefsPrivate->path, &statBuf) == -1) {
+                       if (errno == ENOENT) {
+                               bzero(&statBuf, sizeof(statBuf));
+                       } else {
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesLock stat() failed: %s"), strerror(errno));
+                               _SCErrorSet(kSCStatusStale);
+                               goto error;
+                       }
                }
-       }
 
-       currentSignature = __SCPSignatureFromStatbuf(&statBuf);
-       if (!CFEqual(sessionPrivate->signature, currentSignature)) {
-               if (sessionPrivate->accessed) {
+               currentSignature = __SCPSignatureFromStatbuf(&statBuf);
+               match = CFEqual(prefsPrivate->signature, currentSignature);
+               CFRelease(currentSignature);
+               if (!match) {
                        /*
-                        * the preferences have been accessed since the
-                        * session was created so we've got no choice
+                        * the preferences have been updated since the
+                        * session was accessed so we've got no choice
                         * but to deny the lock request.
                         */
                        _SCErrorSet(kSCStatusStale);
                        goto error;
-               } else {
-                       /*
-                        * the file contents have changed but since we
-                        * haven't accessed any of the preferences we
-                        * don't need to return an error.  Simply reload
-                        * the stored data and proceed.
-                        */
-                       SCPreferencesRef        newPrefs;
-                       SCPreferencesPrivateRef newPrivate;
-
-                       newPrefs = __SCPreferencesCreate(allocator,
-                                                        sessionPrivate->name,
-                                                        sessionPrivate->prefsID,
-                                                        sessionPrivate->perUser,
-                                                        sessionPrivate->user);
-                       if (!newPrefs) {
-                               /* if updated preferences could not be loaded */
-                               _SCErrorSet(kSCStatusStale);
-                               goto error;
-                       }
-
-                       /* synchronize this sessions prefs/signature */
-                       newPrivate = (SCPreferencesPrivateRef)newPrefs;
-                       CFRelease(sessionPrivate->prefs);
-                       sessionPrivate->prefs = newPrivate->prefs;
-                       CFRetain(sessionPrivate->prefs);
-                       CFRelease(sessionPrivate->signature);
-                       sessionPrivate->signature = CFRetain(newPrivate->signature);
-                       CFRelease(newPrefs);
                }
+//     } else {
+//             /*
+//              * the file contents have changed but since we
+//              * haven't accessed any of the preference data we
+//              * don't need to return an error.  Simply proceed.
+//              */
        }
-       CFRelease(currentSignature);
 
-       sessionPrivate->locked = TRUE;
+       prefsPrivate->locked = TRUE;
        return TRUE;
 
     error :
 
        if (haveLock) {
-               SCDynamicStoreRemoveValue(sessionPrivate->session,
-                                         sessionPrivate->sessionKeyLock);
+               SCDynamicStoreRemoveValue(prefsPrivate->session,
+                                         prefsPrivate->sessionKeyLock);
        }
-       if (currentSignature)   CFRelease(currentSignature);
        if (value)              CFRelease(value);
 
        return FALSE;
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@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
+ * February 16, 2004           Allan Nathanson <ajn@apple.com>
+ * - add preference notification APIs
+ *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
 #include <unistd.h>
 #include <sys/errno.h>
 
+
 static CFStringRef
 __SCPreferencesCopyDescription(CFTypeRef cf) {
        CFAllocatorRef          allocator       = CFGetAllocator(cf);
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)cf;
        CFMutableStringRef      result;
 
        result = CFStringCreateMutable(allocator, 0);
-       CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {\n"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("<SCPreferences %p [%p]> {"), cf, allocator);
+       CFStringAppendFormat(result, NULL, CFSTR("name = %@"), prefsPrivate->name);
+       CFStringAppendFormat(result, NULL, CFSTR(", id = %@"), prefsPrivate->prefsID);
+       if (prefsPrivate->perUser) {
+               CFStringAppendFormat(result, NULL, CFSTR(" (for user %@)"), prefsPrivate->user);
+       }
+       CFStringAppendFormat(result, NULL, CFSTR(", path = %s"),
+                            prefsPrivate->newPath ? prefsPrivate->newPath : prefsPrivate->path);
+       if (prefsPrivate->accessed) {
+               CFStringAppendFormat(result, NULL, CFSTR(", accessed"));
+       }
+       if (prefsPrivate->changed) {
+               CFStringAppendFormat(result, NULL, CFSTR(", changed"));
+       }
+       if (prefsPrivate->locked) {
+               CFStringAppendFormat(result, NULL, CFSTR(", locked"));
+       }
        CFStringAppendFormat(result, NULL, CFSTR("}"));
 
        return result;
@@ -57,22 +78,26 @@ __SCPreferencesCopyDescription(CFTypeRef cf) {
 static void
 __SCPreferencesDeallocate(CFTypeRef cf)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)cf;
-
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesDeallocate:"));
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)cf;
 
        /* release resources */
-       if (sessionPrivate->name)               CFRelease(sessionPrivate->name);
-       if (sessionPrivate->prefsID)            CFRelease(sessionPrivate->prefsID);
-       if (sessionPrivate->user)               CFRelease(sessionPrivate->user);
-       if (sessionPrivate->path)               CFAllocatorDeallocate(NULL, sessionPrivate->path);
-       if (sessionPrivate->newPath)            CFAllocatorDeallocate(NULL, sessionPrivate->newPath);
-       if (sessionPrivate->signature)          CFRelease(sessionPrivate->signature);
-       if (sessionPrivate->session)            CFRelease(sessionPrivate->session);
-       if (sessionPrivate->sessionKeyLock)     CFRelease(sessionPrivate->sessionKeyLock);
-       if (sessionPrivate->sessionKeyCommit)   CFRelease(sessionPrivate->sessionKeyCommit);
-       if (sessionPrivate->sessionKeyApply)    CFRelease(sessionPrivate->sessionKeyApply);
-       if (sessionPrivate->prefs)              CFRelease(sessionPrivate->prefs);
+
+       pthread_mutex_destroy(&prefsPrivate->lock);
+
+       if (prefsPrivate->name)                 CFRelease(prefsPrivate->name);
+       if (prefsPrivate->prefsID)              CFRelease(prefsPrivate->prefsID);
+       if (prefsPrivate->user)                 CFRelease(prefsPrivate->user);
+       if (prefsPrivate->path)                 CFAllocatorDeallocate(NULL, prefsPrivate->path);
+       if (prefsPrivate->newPath)              CFAllocatorDeallocate(NULL, prefsPrivate->newPath);
+       if (prefsPrivate->signature)            CFRelease(prefsPrivate->signature);
+       if (prefsPrivate->session)              CFRelease(prefsPrivate->session);
+       if (prefsPrivate->sessionKeyLock)       CFRelease(prefsPrivate->sessionKeyLock);
+       if (prefsPrivate->sessionKeyCommit)     CFRelease(prefsPrivate->sessionKeyCommit);
+       if (prefsPrivate->sessionKeyApply)      CFRelease(prefsPrivate->sessionKeyApply);
+       if (prefsPrivate->rlsContext.release != NULL) {
+               (*prefsPrivate->rlsContext.release)(prefsPrivate->rlsContext.info);
+       }
+       if (prefsPrivate->prefs)                CFRelease(prefsPrivate->prefs);
 
        return;
 }
@@ -82,14 +107,14 @@ static CFTypeID __kSCPreferencesTypeID     = _kCFRuntimeNotATypeID;
 
 
 static const CFRuntimeClass __SCPreferencesClass = {
-       0,                                      // version
-       "SCPreferences",                        // className
-       NULL,                                   // init
-       NULL,                                   // copy
+       0,                              // version
+       "SCPreferences",                // className
+       NULL,                           // init
+       NULL,                           // copy
        __SCPreferencesDeallocate,      // dealloc
-       NULL,                                   // equal
-       NULL,                                   // hash
-       NULL,                                   // copyFormattingDesc
+       NULL,                           // equal
+       NULL,                           // hash
+       NULL,                           // copyFormattingDesc
        __SCPreferencesCopyDescription  // copyDebugDesc
 };
 
@@ -112,32 +137,41 @@ __SCPreferencesCreatePrivate(CFAllocatorRef       allocator)
        /* initialize runtime */
        pthread_once(&initialized, __SCPreferencesInitialize);
 
-       /* allocate session */
+       /* allocate prefs session */
        size  = sizeof(SCPreferencesPrivate) - sizeof(CFRuntimeBase);
        prefsPrivate = (SCPreferencesPrivateRef)_CFRuntimeCreateInstance(allocator,
                                                                         __kSCPreferencesTypeID,
                                                                         size,
                                                                         NULL);
-       if (!prefsPrivate) {
+       if (prefsPrivate == NULL) {
                return NULL;
        }
 
-       prefsPrivate->name              = NULL;
-       prefsPrivate->prefsID           = NULL;
-       prefsPrivate->perUser           = FALSE;
-       prefsPrivate->user              = NULL;
-       prefsPrivate->path              = NULL;
-       prefsPrivate->newPath           = NULL;         // new prefs path
-       prefsPrivate->signature         = NULL;
-       prefsPrivate->session           = NULL;
-       prefsPrivate->sessionKeyLock    = NULL;
-       prefsPrivate->sessionKeyCommit  = NULL;
-       prefsPrivate->sessionKeyApply   = NULL;
-       prefsPrivate->prefs             = NULL;
-       prefsPrivate->accessed          = FALSE;
-       prefsPrivate->changed           = FALSE;
-       prefsPrivate->locked            = FALSE;
-       prefsPrivate->isRoot            = (geteuid() == 0);
+       pthread_mutex_init(&prefsPrivate->lock, NULL);
+
+       prefsPrivate->name                              = NULL;
+       prefsPrivate->prefsID                           = NULL;
+       prefsPrivate->perUser                           = FALSE;
+       prefsPrivate->user                              = NULL;
+       prefsPrivate->path                              = NULL;
+       prefsPrivate->newPath                           = NULL;         // new prefs path
+       prefsPrivate->signature                         = NULL;
+       prefsPrivate->session                           = NULL;
+       prefsPrivate->sessionKeyLock                    = NULL;
+       prefsPrivate->sessionKeyCommit                  = NULL;
+       prefsPrivate->sessionKeyApply                   = NULL;
+       prefsPrivate->rls                               = NULL;
+       prefsPrivate->rlsFunction                       = NULL;
+       prefsPrivate->rlsContext.info                   = NULL;
+       prefsPrivate->rlsContext.retain                 = NULL;
+       prefsPrivate->rlsContext.release                = NULL;
+       prefsPrivate->rlsContext.copyDescription        = NULL;
+       prefsPrivate->rlList                            = NULL;
+       prefsPrivate->prefs                             = NULL;
+       prefsPrivate->accessed                          = FALSE;
+       prefsPrivate->changed                           = FALSE;
+       prefsPrivate->locked                            = FALSE;
+       prefsPrivate->isRoot                            = (geteuid() == 0);
 
        return prefsPrivate;
 }
@@ -153,15 +187,12 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
        int                             fd              = -1;
        SCPreferencesPrivateRef         prefsPrivate;
        int                             sc_status       = kSCStatusOK;
-       struct stat                     statBuf;
-       CFMutableDataRef                xmlData;
-       CFStringRef                     xmlError;
 
        /*
-        * allocate and initialize a new session
+        * allocate and initialize a new prefs session
         */
        prefsPrivate = __SCPreferencesCreatePrivate(allocator);
-       if (!prefsPrivate) {
+       if (prefsPrivate == NULL) {
                return NULL;
        }
 
@@ -184,7 +215,9 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
         * open file
         */
        fd = open(prefsPrivate->path, O_RDONLY, 0644);
-       if (fd == -1) {
+       if (fd != -1) {
+               (void) close(fd);
+       } else {
                switch (errno) {
                        case ENOENT :
                                /* no prefs file */
@@ -211,9 +244,8 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                                        }
                                }
 
-                               /* start fresh */
-                               bzero(&statBuf, sizeof(statBuf));
-                               goto create_1;
+                               /* no preference data, start fresh */
+                               goto done;
                        case EACCES :
                                sc_status = kSCStatusAccessError;
                                break;
@@ -221,25 +253,78 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                                sc_status = kSCStatusFailed;
                                break;
                }
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("open() failed: %s"), strerror(errno));
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesCreate open() failed: %s"), strerror(errno));
                goto error;
        }
 
+    done :
+
        /*
-        * check file, create signature
+        * all OK
         */
-       if (fstat(fd, &statBuf) == -1) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("fstat() failed: %s"), strerror(errno));
-               sc_status = kSCStatusFailed;
+       prefsPrivate->name = CFStringCreateCopy(allocator, name);
+       if (prefsID != NULL) prefsPrivate->prefsID = CFStringCreateCopy(allocator, prefsID);
+       prefsPrivate->perUser = perUser;
+       if (user != NULL) prefsPrivate->user = CFStringCreateCopy(allocator, user);
+       return (SCPreferencesRef)prefsPrivate;
+
+    error :
+
+       if (fd != -1) (void) close(fd);
+       CFRelease(prefsPrivate);
+       _SCErrorSet(sc_status);
+       return NULL;
+}
+
+
+__private_extern__ Boolean
+__SCPreferencesAccess(SCPreferencesRef prefs)
+{
+       CFAllocatorRef                  allocator       = CFGetAllocator(prefs);
+       int                             fd              = -1;
+       SCPreferencesPrivateRef         prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+       int                             sc_status       = kSCStatusOK;
+       struct  stat                    statBuf;
+
+       if (prefsPrivate->accessed) {
+               // if preference data has already been accessed
+               return TRUE;
+       }
+
+       fd = open(prefsPrivate->path, O_RDONLY, 0644);
+       if (fd != -1) {
+               // create signature
+               if (fstat(fd, &statBuf) == -1) {
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess fstat() failed: %s"), strerror(errno));
+                       sc_status = kSCStatusFailed;
+                       goto error;
+               }
+       } else {
+               switch (errno) {
+                       case ENOENT :
+                               /* no preference data, start fresh */
+                               bzero(&statBuf, sizeof(statBuf));
+                               goto create_1;
+                       case EACCES :
+                               sc_status = kSCStatusAccessError;
+                               break;
+                       default :
+                               sc_status = kSCStatusFailed;
+                               break;
+               }
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess open() failed: %s"), strerror(errno));
                goto error;
        }
 
     create_1 :
 
+       if (prefsPrivate->signature != NULL) CFRelease(prefsPrivate->signature);
        prefsPrivate->signature = __SCPSignatureFromStatbuf(&statBuf);
 
        if (statBuf.st_size > 0) {
-               CFDictionaryRef dict;
+               CFDictionaryRef         dict;
+               CFMutableDataRef        xmlData;
+               CFStringRef             xmlError;
 
                /*
                 * extract property list
@@ -248,7 +333,7 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                CFDataSetLength(xmlData, statBuf.st_size);
                if (read(fd, (void *)CFDataGetBytePtr(xmlData), statBuf.st_size) != statBuf.st_size) {
                        /* corrupt prefs file, start fresh */
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen read(): could not load preference data."));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess read(): could not load preference data."));
                        CFRelease(xmlData);
                        xmlData = NULL;
                        goto create_2;
@@ -262,11 +347,11 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                                                       kCFPropertyListImmutable,
                                                       &xmlError);
                CFRelease(xmlData);
-               if (!dict) {
+               if (dict == NULL) {
                        /* corrupt prefs file, start fresh */
-                       if (xmlError) {
+                       if (xmlError != NULL) {
                                SCLog(TRUE, LOG_ERR,
-                                     CFSTR("_SCPOpen CFPropertyListCreateFromXMLData(): %@"),
+                                     CFSTR("__SCPreferencesAccess CFPropertyListCreateFromXMLData(): %@"),
                                      xmlError);
                                CFRelease(xmlError);
                        }
@@ -278,7 +363,7 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                 */
                if (!isA_CFDictionary(dict)) {
                        /* corrupt prefs file, start fresh */
-                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen CFGetTypeID(): not a dictionary."));
+                       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess CFGetTypeID(): not a dictionary."));
                        CFRelease(dict);
                        goto create_2;
                }
@@ -298,7 +383,7 @@ __SCPreferencesCreate(CFAllocatorRef        allocator,
                /*
                 * new file, create empty preferences
                 */
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("_SCPOpen(): creating new dictionary."));
+               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__SCPreferencesAccess(): creating new dictionary."));
                prefsPrivate->prefs = CFDictionaryCreateMutable(allocator,
                                                                0,
                                                                &kCFTypeDictionaryKeyCallBacks,
@@ -306,21 +391,15 @@ __SCPreferencesCreate(CFAllocatorRef      allocator,
                prefsPrivate->changed = TRUE;
        }
 
-       /*
-        * all OK
-        */
-       prefsPrivate->name = CFStringCreateCopy(allocator, name);
-       if (prefsID)    prefsPrivate->prefsID = CFStringCreateCopy(allocator, prefsID);
-       prefsPrivate->perUser = perUser;
-       if (user)       prefsPrivate->user    = CFStringCreateCopy(allocator, user);
-       return (SCPreferencesRef)prefsPrivate;
+       prefsPrivate->accessed = TRUE;
+       return TRUE;
 
     error :
 
        if (fd != -1)   (void) close(fd);
-       CFRelease(prefsPrivate);
        _SCErrorSet(sc_status);
-       return NULL;
+       return FALSE;
+
 }
 
 
@@ -329,12 +408,6 @@ SCPreferencesCreate(CFAllocatorRef         allocator,
                    CFStringRef                 name,
                    CFStringRef                 prefsID)
 {
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesCreate:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  name    = %@"), name);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  prefsID = %@"), prefsID);
-       }
-
        return __SCPreferencesCreate(allocator, name, prefsID, FALSE, NULL);
 }
 
@@ -345,13 +418,6 @@ SCUserPreferencesCreate(CFAllocatorRef                     allocator,
                        CFStringRef                     prefsID,
                        CFStringRef                     user)
 {
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCUserPreferencesCreate:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  name    = %@"), name);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  prefsID = %@"), prefsID);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  user    = %@"), user);
-       }
-
        return __SCPreferencesCreate(allocator, name, prefsID, TRUE, user);
 }
 
@@ -361,3 +427,282 @@ SCPreferencesGetTypeID(void) {
        pthread_once(&initialized, __SCPreferencesInitialize);  /* initialize runtime */
        return __kSCPreferencesTypeID;
 }
+
+
+static void
+prefsNotify(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info)
+{
+       void                            *context_info;
+       void                            (*context_release)(const void *);
+       CFIndex                         i;
+       CFIndex                         n;
+       SCPreferencesNotification       notify          = 0;
+       SCPreferencesRef                prefs           = (SCPreferencesRef)info;
+       SCPreferencesPrivateRef         prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+       SCPreferencesCallBack           rlsFunction;
+
+       n = (changedKeys != NULL) ? CFArrayGetCount(changedKeys) : 0;
+       for (i = 0; i < n; i++) {
+               CFStringRef     key;
+
+               key = CFArrayGetValueAtIndex(changedKeys, i);
+               if (CFEqual(key, prefsPrivate->sessionKeyCommit)) {
+                       // if preferences have been saved
+                       notify |= kSCPreferencesNotificationCommit;
+               }
+               if (CFEqual(key, prefsPrivate->sessionKeyApply)) {
+                       // if stored preferences should be applied to current configuration
+                       notify |= kSCPreferencesNotificationApply;
+               }
+       }
+
+       if (notify == 0) {
+               // if no changes
+               return;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       /* callout */
+       rlsFunction = prefsPrivate->rlsFunction;
+       if (prefsPrivate->rlsContext.retain != NULL) {
+               context_info    = (void *)prefsPrivate->rlsContext.retain(prefsPrivate->rlsContext.info);
+               context_release = prefsPrivate->rlsContext.release;
+       } else {
+               context_info    = prefsPrivate->rlsContext.info;
+               context_release = NULL;
+       }
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       if (rlsFunction != NULL) {
+               (*rlsFunction)(prefs, notify, context_info);
+       }
+
+       if (context_release != NULL) {
+               (*context_release)(context_info);
+       }
+
+       return;
+}
+
+
+__private_extern__ Boolean
+__SCPreferencesAddSession(SCPreferencesRef prefs)
+{
+       CFAllocatorRef                  allocator       = CFGetAllocator(prefs);
+       SCDynamicStoreContext           context         = { 0
+                                                         , (void *)prefs
+                                                         , NULL
+                                                         , NULL
+                                                         , NULL
+                                                         };
+       SCPreferencesPrivateRef         prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+
+       /* establish a dynamic store session */
+       prefsPrivate->session = SCDynamicStoreCreate(allocator,
+                                                    CFSTR("SCPreferences"),
+                                                    prefsNotify,
+                                                    &context);
+       if (prefsPrivate->session == NULL) {
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("__SCPreferencesAddSession SCDynamicStoreCreate() failed"));
+               return FALSE;
+       }
+
+       /* create the session "commit" key */
+       prefsPrivate->sessionKeyCommit = _SCPNotificationKey(NULL,
+                                                            prefsPrivate->prefsID,
+                                                            prefsPrivate->perUser,
+                                                            prefsPrivate->user,
+                                                            kSCPreferencesKeyCommit);
+
+       /* create the session "apply" key */
+       prefsPrivate->sessionKeyApply = _SCPNotificationKey(NULL,
+                                                            prefsPrivate->prefsID,
+                                                            prefsPrivate->perUser,
+                                                            prefsPrivate->user,
+                                                            kSCPreferencesKeyApply);
+
+       return TRUE;
+}
+
+
+Boolean
+SCPreferencesSetCallback(SCPreferencesRef       prefs,
+                        SCPreferencesCallBack  callout,
+                        SCPreferencesContext   *context)
+{
+       SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs;
+
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       if (prefsPrivate->rlsContext.release != NULL) {
+               /* let go of the current context */
+               (*prefsPrivate->rlsContext.release)(prefsPrivate->rlsContext.info);
+       }
+
+       prefsPrivate->rlsFunction                       = callout;
+       prefsPrivate->rlsContext.info                   = NULL;
+       prefsPrivate->rlsContext.retain                 = NULL;
+       prefsPrivate->rlsContext.release                = NULL;
+       prefsPrivate->rlsContext.copyDescription        = NULL;
+       if (context != NULL) {
+               bcopy(context, &prefsPrivate->rlsContext, sizeof(SCPreferencesContext));
+               if (context->retain != NULL) {
+                       prefsPrivate->rlsContext.info = (void *)(*context->retain)(context->info);
+               }
+       }
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+
+       return TRUE;
+}
+
+
+Boolean
+SCPreferencesScheduleWithRunLoop(SCPreferencesRef       prefs,
+                                CFRunLoopRef           runLoop,
+                                CFStringRef            runLoopMode)
+{
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       if (prefsPrivate->rls == NULL) {
+               CFMutableArrayRef       keys;
+
+               if (prefsPrivate->session == NULL) {
+                       __SCPreferencesAddSession(prefs);
+               }
+
+               CFRetain(prefs);        // hold a reference to the prefs
+
+               keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+               CFArrayAppendValue(keys, prefsPrivate->sessionKeyCommit);
+               CFArrayAppendValue(keys, prefsPrivate->sessionKeyApply);
+               (void)SCDynamicStoreSetNotificationKeys(prefsPrivate->session, keys, NULL);
+               CFRelease(keys);
+
+               prefsPrivate->rls    = SCDynamicStoreCreateRunLoopSource(NULL, prefsPrivate->session, 0);
+               prefsPrivate->rlList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       }
+
+       if (!_SC_isScheduled(NULL, runLoop, runLoopMode, prefsPrivate->rlList)) {
+               /*
+                * if we do not already have notifications scheduled with
+                * this runLoop / runLoopMode
+                */
+               CFRunLoopAddSource(runLoop, prefsPrivate->rls, runLoopMode);
+       }
+
+       _SC_schedule(prefs, runLoop, runLoopMode, prefsPrivate->rlList);
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+       return TRUE;
+}
+
+
+Boolean
+SCPreferencesUnscheduleFromRunLoop(SCPreferencesRef     prefs,
+                                  CFRunLoopRef         runLoop,
+                                  CFStringRef          runLoopMode)
+{
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+       CFIndex                 n;
+       Boolean                 ok              = FALSE;
+
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
+
+       pthread_mutex_lock(&prefsPrivate->lock);
+
+       if (prefsPrivate->rls == NULL) {
+               /* if not currently scheduled */
+               goto done;
+       }
+
+       if (!_SC_unschedule(NULL, runLoop, runLoopMode, prefsPrivate->rlList, FALSE)) {
+               /* if not currently scheduled */
+               goto done;
+       }
+
+       n = CFArrayGetCount(prefsPrivate->rlList);
+       if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, prefsPrivate->rlList)) {
+               /*
+                * if we are no longer scheduled to receive notifications for
+                * this runLoop / runLoopMode
+                */
+               CFRunLoopRemoveSource(runLoop, prefsPrivate->rls, runLoopMode);
+
+               if (n == 0) {
+                       CFArrayRef      changedKeys;
+
+                       /*
+                        * if *all* notifications have been unscheduled
+                        */
+                       CFRunLoopSourceInvalidate(prefsPrivate->rls);
+                       CFRelease(prefsPrivate->rls);
+                       prefsPrivate->rls = NULL;
+                       CFRelease(prefsPrivate->rlList);
+                       prefsPrivate->rlList = NULL;
+
+                       CFRelease(prefs);       // release our reference to the prefs
+
+                       // no need to track changes
+                       (void)SCDynamicStoreSetNotificationKeys(prefsPrivate->session, NULL, NULL);
+
+                       // clear out any pending notifications
+                       changedKeys = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session);
+                       if (changedKeys != NULL) {
+                               CFRelease(changedKeys);
+                       }
+               }
+       }
+
+       ok = TRUE;
+
+    done :
+
+       pthread_mutex_unlock(&prefsPrivate->lock);
+       return ok;
+}
+
+
+void
+SCPreferencesSynchronize(SCPreferencesRef       prefs)
+{
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
+
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return;
+       }
+
+       if (prefsPrivate->prefs != NULL) {
+               CFRelease(prefsPrivate->prefs);
+               prefsPrivate->prefs = NULL;
+       }
+       if (prefsPrivate->signature != NULL) {
+               CFRelease(prefsPrivate->signature);
+               prefsPrivate->signature = NULL;
+       }
+       prefsPrivate->accessed = FALSE;
+       prefsPrivate->changed  = FALSE;
+       return;
+}
index 1fd06ed1d999cd1526d83cea9281ca2332c6cc3e..2a700dea6b66b22a697708094aeb4b720010a55a 100644 (file)
@@ -77,7 +77,7 @@ normalizePath(CFStringRef path)
 
 
 static Boolean
-getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
+getPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef *entity)
 {
        CFStringRef             element;
        CFArrayRef              elements;
@@ -86,7 +86,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
        CFIndex                 nElements;
        CFIndex                 nLinks          = 0;
        Boolean                 ok              = FALSE;
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
        CFDictionaryRef         value           = NULL;
 
        elements = normalizePath(path);
@@ -95,14 +95,15 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
                return FALSE;
        }
 
+       __SCPreferencesAccess(prefs);
+
     restart :
 
        nElements = CFArrayGetCount(elements);
        for (i = 0; i < nElements; i++) {
                element = CFArrayGetValueAtIndex(elements, i);
                if (i == 0) {
-                       sessionPrivate->accessed = TRUE;
-                       value = CFDictionaryGetValue(sessionPrivate->prefs,
+                       value = CFDictionaryGetValue(prefsPrivate->prefs,
                                                     CFArrayGetValueAtIndex(elements, 0));
                } else {
                        value = CFDictionaryGetValue(value, element);
@@ -163,7 +164,7 @@ getPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef *entity)
 
 
 static Boolean
-setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
+setPath(SCPreferencesRef prefs, CFStringRef path, CFDictionaryRef entity)
 {
        CFStringRef             element;
        CFArrayRef              elements;
@@ -175,7 +176,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
        CFDictionaryRef         node            = NULL;
        CFMutableArrayRef       nodes;
        Boolean                 ok              = FALSE;
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
 
        elements = normalizePath(path);
        if (elements == NULL) {
@@ -183,6 +184,8 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
                return FALSE;
        }
 
+       __SCPreferencesAccess(prefs);
+
     restart :
 
        nElements = CFArrayGetCount(elements);
@@ -190,8 +193,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
        for (i = 0; i < nElements - 1; i++) {
                element = CFArrayGetValueAtIndex(elements, i);
                if (i == 0) {
-                       sessionPrivate->accessed = TRUE;
-                       node = CFDictionaryGetValue(sessionPrivate->prefs, element);
+                       node = CFDictionaryGetValue(prefsPrivate->prefs, element);
                } else {
                        node = CFDictionaryGetValue(node, element);
 
@@ -258,11 +260,11 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
                element = CFArrayGetValueAtIndex(elements, i);
                if (i == 0) {
                        if (newEntity) {
-                               CFDictionarySetValue(sessionPrivate->prefs, element, newEntity);
+                               CFDictionarySetValue(prefsPrivate->prefs, element, newEntity);
                        } else {
-                               CFDictionaryRemoveValue(sessionPrivate->prefs, element);
+                               CFDictionaryRemoveValue(prefsPrivate->prefs, element);
                        }
-                       sessionPrivate->changed  = TRUE;
+                       prefsPrivate->changed  = TRUE;
                        ok = TRUE;
                } else {
                        CFMutableDictionaryRef  newNode;
@@ -291,7 +293,7 @@ setPath(SCPreferencesRef session, CFStringRef path, CFDictionaryRef entity)
 
 
 CFStringRef
-SCPreferencesPathCreateUniqueChild(SCPreferencesRef    session,
+SCPreferencesPathCreateUniqueChild(SCPreferencesRef    prefs,
                                   CFStringRef          prefix)
 {
        CFStringRef             child;
@@ -300,12 +302,13 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef       session,
        CFUUIDRef               uuid;
        CFDictionaryRef         entity;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathCreateUniqueChild:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  prefix = %@"), prefix);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return NULL;
        }
 
-       if (getPath(session, prefix, &entity)) {
+       if (getPath(prefs, prefix, &entity)) {
                // if prefix path exists
                if (CFDictionaryContainsKey(entity, kSCResvLink)) {
                        /* the path is a link... */
@@ -328,9 +331,7 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef session,
                                            0,
                                            &kCFTypeDictionaryKeyCallBacks,
                                            &kCFTypeDictionaryValueCallBacks);
-       if (setPath(session, newPath, newDict)) {
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  child  = %@"), newPath);
-       } else {
+       if (!setPath(prefs, newPath, newDict)) {
                CFRelease(newPath);
                newPath = NULL;
        }
@@ -341,55 +342,55 @@ SCPreferencesPathCreateUniqueChild(SCPreferencesRef       session,
 
 
 CFDictionaryRef
-SCPreferencesPathGetValue(SCPreferencesRef     session,
+SCPreferencesPathGetValue(SCPreferencesRef     prefs,
                          CFStringRef           path)
 {
        CFDictionaryRef entity;
        CFStringRef     entityLink;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathGetValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  path  = %@"), path);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return NULL;
        }
 
-       if (!getPath(session, path, &entity)) {
+       if (!getPath(prefs, path, &entity)) {
                return NULL;
        }
 
        if (isA_CFDictionary(entity) &&
            (CFDictionaryGetValueIfPresent(entity, kSCResvLink, (const void **)&entityLink))) {
                /* if this is a dictionary AND it is a link */
-               if (!getPath(session, entityLink, &entity)) {
+               if (!getPath(prefs, entityLink, &entity)) {
                        /* if it was a bad link */
                        return NULL;
                }
        }
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  value = %@"), entity);
        return entity;
 }
 
 
 CFStringRef
-SCPreferencesPathGetLink(SCPreferencesRef      session,
+SCPreferencesPathGetLink(SCPreferencesRef      prefs,
                         CFStringRef            path)
 {
        CFDictionaryRef entity;
        CFStringRef     entityLink;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathGetLink:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  path = %@"), path);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return NULL;
        }
 
-       if (!getPath(session, path, &entity)) {
+       if (!getPath(prefs, path, &entity)) {
                return NULL;
        }
 
        if (isA_CFDictionary(entity) &&
            (CFDictionaryGetValueIfPresent(entity, kSCResvLink, (const void **)&entityLink))) {
                /* if this is a dictionary AND it is a link */
-               SCLog(_sc_verbose, LOG_DEBUG, CFSTR("  link = %@"), entityLink);
                return entityLink;
        }
 
@@ -398,16 +399,16 @@ SCPreferencesPathGetLink(SCPreferencesRef session,
 
 
 Boolean
-SCPreferencesPathSetValue(SCPreferencesRef     session,
+SCPreferencesPathSetValue(SCPreferencesRef     prefs,
                          CFStringRef           path,
                          CFDictionaryRef       value)
 {
        Boolean                 ok;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathSetValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  path  = %@"), path);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value = %@"), value);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
        }
 
        if (!value) {
@@ -415,13 +416,13 @@ SCPreferencesPathSetValue(SCPreferencesRef        session,
                return FALSE;
        }
 
-       ok = setPath(session, path, value);
+       ok = setPath(prefs, path, value);
        return ok;
 }
 
 
 Boolean
-SCPreferencesPathSetLink(SCPreferencesRef      session,
+SCPreferencesPathSetLink(SCPreferencesRef      prefs,
                         CFStringRef            path,
                         CFStringRef            link)
 {
@@ -429,10 +430,10 @@ SCPreferencesPathSetLink(SCPreferencesRef session,
        CFDictionaryRef         entity;
        Boolean                 ok;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathSetLink:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  path = %@"), path);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  link = %@"), link);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
        }
 
        if (!link) {
@@ -440,7 +441,7 @@ SCPreferencesPathSetLink(SCPreferencesRef   session,
                return FALSE;
        }
 
-       if (!getPath(session, link, &entity)) {
+       if (!getPath(prefs, link, &entity)) {
                // if bad link
                return FALSE;
        }
@@ -450,7 +451,7 @@ SCPreferencesPathSetLink(SCPreferencesRef   session,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
        CFDictionaryAddValue(dict, kSCResvLink, link);
-       ok = setPath(session, path, dict);
+       ok = setPath(prefs, path, dict);
        CFRelease(dict);
 
        return ok;
@@ -458,19 +459,20 @@ SCPreferencesPathSetLink(SCPreferencesRef session,
 
 
 Boolean
-SCPreferencesPathRemoveValue(SCPreferencesRef  session,
+SCPreferencesPathRemoveValue(SCPreferencesRef  prefs,
                             CFStringRef        path)
 {
        CFArrayRef              elements        = NULL;
        Boolean                 ok              = FALSE;
        CFDictionaryRef         value;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesPathRemoveValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  path = %@"), path);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
        }
 
-       if (!getPath(session, path, &value)) {
+       if (!getPath(prefs, path, &value)) {
                // if no such path
                return FALSE;
        }
@@ -481,7 +483,7 @@ SCPreferencesPathRemoveValue(SCPreferencesRef       session,
                return FALSE;
        }
 
-       ok = setPath(session, path, NULL);
+       ok = setPath(prefs, path, NULL);
 
        CFRelease(elements);
        return ok;
index 1de5c1df617dd16323972422eeaa764da237f9cb..9d7c73aec67a822def32b47f2cb3426ef2c2aea0 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
-SCPreferencesRemoveValue(SCPreferencesRef session, CFStringRef key)
+SCPreferencesRemoveValue(SCPreferencesRef prefs, CFStringRef key)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
 
-       if (_sc_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("SCPreferencesRemoveValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
        }
 
-       sessionPrivate->accessed = TRUE;
+       __SCPreferencesAccess(prefs);
 
-       if (!CFDictionaryContainsKey(sessionPrivate->prefs, key)) {
+       if (!CFDictionaryContainsKey(prefsPrivate->prefs, key)) {
                _SCErrorSet(kSCStatusNoKey);
                return FALSE;
        }
 
-       CFDictionaryRemoveValue(sessionPrivate->prefs, key);
-       sessionPrivate->changed  = TRUE;
+       CFDictionaryRemoveValue(prefsPrivate->prefs, key);
+       prefsPrivate->changed  = TRUE;
        return TRUE;
 }
index c5f6c3fb9fe300ba0bdd21422ace9330eda7f16e..ed4befffdd5ec29d44d165eaae9be165a3d8c475 100644 (file)
 #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;
 }
index c41ee1022a59a0ed2c0528eab4cf1102ac3c4a00..6b07676e8fc762dab6d91ae9b0e84e37d49904e9 100644 (file)
 #include "SCPreferencesInternal.h"
 
 Boolean
-SCPreferencesUnlock(SCPreferencesRef session)
+SCPreferencesUnlock(SCPreferencesRef prefs)
 {
-       SCPreferencesPrivateRef sessionPrivate  = (SCPreferencesPrivateRef)session;
+       SCPreferencesPrivateRef prefsPrivate    = (SCPreferencesPrivateRef)prefs;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("SCPreferencesUnlock:"));
+       if (prefs == NULL) {
+               /* sorry, you must provide a session */
+               _SCErrorSet(kSCStatusNoPrefsSession);
+               return FALSE;
+       }
 
-       if (!sessionPrivate->locked) {
+       if (!prefsPrivate->locked) {
                /* sorry, you don't have the lock */
                _SCErrorSet(kSCStatusNeedLock);
                return FALSE;
        }
 
-       if (!sessionPrivate->isRoot) {
+       if (!prefsPrivate->isRoot) {
                /* CONFIGD REALLY NEEDS NON-ROOT WRITE ACCESS */
                goto perUser;
        }
 
-       if (!SCDynamicStoreRemoveValue(sessionPrivate->session, sessionPrivate->sessionKeyLock)) {
-               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreRemoveValue() failed"));
+       if (!SCDynamicStoreRemoveValue(prefsPrivate->session, prefsPrivate->sessionKeyLock)) {
+               SCLog(_sc_verbose, LOG_INFO, CFSTR("SCPreferencesUnlock SCDynamicStoreRemoveValue() failed"));
                return FALSE;
        }
 
     perUser:
 
-       sessionPrivate->locked = FALSE;
+       prefsPrivate->locked = FALSE;
        return TRUE;
 }
index aaebc2a4b90d2911bcf461e917e1a86dd36f0ac5..b71d33dd26ae7e254c706831533040d5063317cd 100644 (file)
 
 
 #include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 
 
 /*!
        @header SCPreferences
-       The SCPreferencesXXX() APIs allow an application to load and
-       store XML configuration data in a controlled manner and provide
-       the necessary notifications to other applications that need to
-       be aware of configuration changes.
-
-       The stored XML configuration data is accessed using a prefsID. A
-       NULL value indicates that the default system preferences are to
-       be accessed.
-       A string which starts with a leading "/" character specifies the
-       path to the file containing te preferences to be accessed.
-       A string which does not start with a leading "/" character
-       specifies a file relative to the default system preferences
-       directory.
+       @discussion The SCPreferences API allows an application to load and
+               store XML configuration data in a controlled manner and provide
+               the necessary notifications to other applications that need to
+               be aware of configuration changes.
+
+               To access configuration preferences, you must first establish a
+               preferences session using the SCPreferencesCreate function.
+               To identify a specific set of preferences to access, you pass a
+               value in the prefsID parameter.
+               A NULL value indicates that the default system preferences are
+               to be accessed.
+               A string that starts with a leading "/" character specifies
+               the absolute path to the file containing the preferences to
+               be accessed.
+               A string that does not start with a leading "/" character
+               specifies a file relative to the default system preferences
+               directory.
+
+               When you are finished with the preferences session, use
+               CFRelease to close it.
  */
 
 
 /*!
        @typedef SCPreferencesRef
-       @discussion This is the handle to an open "session" for
+       @discussion This is the handle to an open preferences session for
                accessing system configuration preferences.
  */
 typedef const struct __SCPreferences * SCPreferencesRef;
 
+/*!
+       @enum SCPreferencesNotification
+       @discussion Used with the SCPreferencesCallBack callback
+               to describe the type of notification.
+       @constant kSCPreferencesNotificationCommit Indicates when new
+               preferences have been saved.
+       @constant kSCPreferencesNotificationApply Key Indicates when a
+               request has been made to apply the currently saved
+               preferences to the active system configuration.
+ */
+enum {
+       kSCPreferencesNotificationCommit        = 1<<0,
+       kSCPreferencesNotificationApply         = 1<<1
+};
+typedef        uint32_t        SCPreferencesNotification;
+
+/*!
+       @typedef SCPreferencesContext
+       Structure containing user-specified data and callbacks for SCPreferences.
+       @field version The version number of the structure type being passed
+               in as a parameter to the SCPreferencesSetCallback function.
+               This structure is version 0.
+       @field info A C pointer to a user-specified block of data.
+       @field retain The callback used to add a retain for the info field.
+               If this parameter is not a pointer to a function of the correct
+               prototype, the behavior is undefined.
+               The value may be NULL.
+       @field release The calllback used to remove a retain previously added
+               for the info field.
+               If this parameter is not a pointer to a function of the
+               correct prototype, the behavior is undefined.
+               The value may be NULL.
+       @field copyDescription The callback used to provide a description of
+               the info field.
+ */
+typedef struct {
+       CFIndex         version;
+       void *          info;
+       const void      *(*retain)(const void *info);
+       void            (*release)(const void *info);
+       CFStringRef     (*copyDescription)(const void *info);
+} SCPreferencesContext;
+
+/*!
+       @typedef SCPreferencesCallBack
+       @discussion Type of the callback function used when the
+               preferences have been updated and/or applied.
+       @param prefs The preferences session.
+       @param notificationType The type of notification, such as changes
+               committed, changes applied, etc.
+       @param info A C pointer to a user-specified block of data.
+ */
+typedef void (*SCPreferencesCallBack)   (
+                                       SCPreferencesRef                prefs,
+                                       SCPreferencesNotification       notificationType,
+                                       void                            *info
+                                       );
+
 
 __BEGIN_DECLS
 
 /*!
        @function SCPreferencesGetTypeID
-       Returns the type identifier of all SCPreferences instances.
+       @discussion Returns the type identifier of all SCPreferences instances.
  */
 CFTypeID
 SCPreferencesGetTypeID         (void);
 
-
 /*!
        @function SCPreferencesCreate
        @discussion Initiates access to the per-system set of configuration
                preferences.
-       @param allocator ...
+       @param allocator The CFAllocator that should be used to allocate
+               memory for this preferences session.
+               This parameter may be NULL in which case the current
+               default CFAllocator is used.
+               If this reference is not a valid CFAllocator, the behavior
+               is undefined.
        @param name A string that describes the name of the calling
                process.
        @param prefsID A string that identifies the name of the
-               group of preferences to be accessed/updated.
-       @result prefs A pointer to memory that will be filled with an
-               SCPreferencesRef handle to be used for all subsequent requests.
-               If a session cannot be established, the contents of
-               memory pointed to by this parameter are undefined.
+               group of preferences to be accessed or updated.
+       @result Returns a reference to the new SCPreferences.
+               You must release the returned value.
  */
 SCPreferencesRef
 SCPreferencesCreate            (
@@ -91,120 +159,116 @@ SCPreferencesCreate              (
        @function SCPreferencesLock
        @discussion Locks access to the configuration preferences.
 
-       This function obtains exclusive access to the configuration
-       preferences associated with this prefsID. Clients attempting
-       to obtain exclusive access to the preferences will either receive
-       an kSCStatusPrefsBusy error or block waiting for the lock to be
-       released.
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
+               This function obtains exclusive access to the configuration
+               preferences.  Clients attempting to obtain exclusive access
+               to the preferences will either receive a kSCStatusPrefsBusy
+               error or block waiting for the lock to be released.
+       @param prefs The preferences session.
        @param wait A boolean flag indicating whether the calling process
                should block waiting for another process to complete its update
                operation and release its lock.
-       @result TRUE if the lock was obtained; FALSE if an error occurred.
+       @result Returns TRUE if the lock was obtained;
+               FALSE if an error occurred.
  */
 Boolean
 SCPreferencesLock              (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                Boolean                 wait
                                );
 
 /*!
        @function SCPreferencesCommitChanges
        @discussion Commits changes made to the configuration preferences to
-               persitent storage.
-
-               This function commits any changes to permanent storage. An
-               implicit call to SCPreferencesLock/SCPreferencesUnlock will
-               be made if exclusive access has not already been established.
-
-               Note:  This routine commits changes to persistent storage.
-               Call SCPreferencesApplyChanges() to apply the changes
-               to the running system.
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
-       @result TRUE if the lock was obtained; FALSE if an error occurred.
+               persistent storage.
+
+               This function commits any changes to permanent storage.
+               Implicit calls to the SCPreferencesLock and SCPreferencesUnlock
+               functions will be made if exclusive access has not already been
+               established.
+
+               Note: This routine commits changes to persistent storage.
+               Call the SCPreferencesApplyChanges function to apply the
+               changes to the running system.
+       @param prefs The preferences session.
+       @result Returns TRUE if the lock was obtained;
+               FALSE if an error occurred.
  */
 Boolean
 SCPreferencesCommitChanges     (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesApplyChanges
        @discussion Requests that the currently stored configuration
                preferences be applied to the active configuration.
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
-       @result TRUE if the lock was obtained; FALSE if an error occurred.
+       @param prefs The preferences session.
+       @result Returns TRUE if the lock was obtained;
+               FALSE if an error occurred.
  */
 Boolean
 SCPreferencesApplyChanges      (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesUnlock
        @discussion Releases exclusive access to the configuration preferences.
 
-               This function releases the exclusive access "lock" for this prefsID.
-               Other clients will be now be able to establish exclusive access to
-               the preferences.
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
-       @result TRUE if the lock was obtained; FALSE if an error occurred.
+               This function releases the exclusive access lock to the
+               preferences.  Other clients will be now be able to establish
+               exclusive access to the preferences.
+       @param prefs The preferences session.
+       @result Returns TRUE if the lock was obtained;
+               FALSE if an error occurred.
  */
 Boolean
 SCPreferencesUnlock            (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesGetSignature
        @discussion Returns a sequence of bytes that can be used to determine
                if the saved configuration preferences have changed.
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
-       @param signature A pointer to a CFDataRef that will reflect
-               the signature of the configuration preferences at the time
-               of the call to SCPreferencesCreate().
-       @result A CFDataRef that reflects the signature of the configuration
-               preferences at the time of the call to SCPreferencesCreate().
+       @param prefs The preferences session.
+       @result Returns a CFDataRef that reflects the signature of the configuration
+               preferences at the time of the call to the SCPreferencesCreate function.
  */
 CFDataRef
 SCPreferencesGetSignature      (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesCopyKeyList
        @discussion Returns an array of currently defined preference keys.
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
-       @result The list of keys.  You must release the returned value.
+       @param prefs The preferences session.
+       @result Returns the list of keys.
+               You must release the returned value.
  */
 CFArrayRef
 SCPreferencesCopyKeyList       (
-                               SCPreferencesRef        session
+                               SCPreferencesRef        prefs
                                );
 
 /*!
        @function SCPreferencesGetValue
        @discussion Returns the data associated with a preference key.
 
-               This function retrieves data associated with a key for the prefsID.
+               This function retrieves data associated with the specified
+               key.
 
-               Note:  You could read stale data and not know it, unless you
-               first call SCPreferencesLock().
-       @param session An SCPreferencesRef handle that should be used for
-               all API calls.
+               Note: To avoid inadvertantly reading stale data, first call
+               the SCPreferencesLock function.
+       @param prefs The preferences session.
        @param key The preference key to be returned.
-       @result The value associated with the specified preference key; If no
-               value was located, NULL is returned.
+       @result Returns the value associated with the specified preference key;
+               NULL if no value was located.
  */
 CFPropertyListRef
 SCPreferencesGetValue          (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key
                                );
 
@@ -212,20 +276,20 @@ SCPreferencesGetValue             (
        @function SCPreferencesAddValue
        @discussion Adds data for a preference key.
 
-       This function associates new data with the specified key. In order
-       to commit these changes to permanent storage a call must be made to
-       SCPreferencesCommitChanges().
-       @param session The SCPreferencesRef handle that should be used to
-               communicate with the APIs.
+               This function associates new data with the specified key.
+               To commit these changes to permanent storage, a call must
+               be made to the SCPreferencesCommitChanges function.
+       @param prefs The preferences session.
        @param key The preference key to be updated.
        @param value The CFPropertyListRef object containing the
                value to be associated with the specified preference key.
-       @result TRUE if the value was added; FALSE if the key already exists or
+       @result Returns TRUE if the value was added;
+               FALSE if the key already exists or
                if an error occurred.
  */
 Boolean
 SCPreferencesAddValue          (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key,
                                CFPropertyListRef       value
                                );
@@ -234,19 +298,19 @@ SCPreferencesAddValue             (
        @function SCPreferencesSetValue
        @discussion Updates the data associated with a preference key.
 
-       This function adds or replaces the value associated with the
-       specified key. In order to commit these changes to permanent
-       storage a call must be made to SCPreferencesCommitChanges().
-       @param session The SCPreferencesRef handle that should be used to
-               communicate with the APIs.
+               This function adds or replaces the value associated with the
+               specified key.  To commit these changes to permanent storage
+               a call must be made to the SCPreferencesCommitChanges function.
+       @param prefs The preferences session.
        @param key The preference key to be updated.
        @param value The CFPropertyListRef object containing the
                data to be associated with the specified preference key.
-       @result TRUE if the value was set; FALSE if an error occurred.
+       @result Returns TRUE if the value was set;
+               FALSE if an error occurred.
  */
 Boolean
 SCPreferencesSetValue          (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key,
                                CFPropertyListRef       value
                                );
@@ -255,21 +319,96 @@ SCPreferencesSetValue             (
        @function SCPreferencesRemoveValue
        @discussion Removes the data associated with a preference key.
 
-       This function removes the data associated with the specified
-       key. In order to commit these changes to permanent storage a
-       call must be made to SCPreferencesCommitChanges().
-       @param session The SCPreferencesRef handle that should be used to
-               communicate with the APIs.
+               This function removes the data associated with the specified
+               key.  To commit these changes to permanent storage a call must
+               be made to the SCPreferencesCommitChanges function.
+       @param prefs The preferences session.
        @param key The preference key to be removed.
-       @result TRUE if the value was removed; FALSE if the key did not exist or
-               if an error occurred.
+       @result Returns TRUE if the value was removed;
+               FALSE if the key did not exist or if an error occurred.
  */
 Boolean
 SCPreferencesRemoveValue       (
-                               SCPreferencesRef        session,
+                               SCPreferencesRef        prefs,
                                CFStringRef             key
                                );
 
+/*!
+       @function SCPreferencesSetCallback
+       @discussion Assigns a callback to a preferences session.  The function
+               is called when the changes to the preferences have been
+               committed or applied.
+       @param prefs The preferences session.
+       @param callout The function to be called when the preferences have
+               been changed or applied.
+               If NULL, the current callback is removed.
+       @param context The SCPreferencesContext associated with
+               the callout.
+       @result Returns TRUE if the notification client was successfully set.
+ */
+Boolean
+SCPreferencesSetCallback               (
+                                       SCPreferencesRef        prefs,
+                                       SCPreferencesCallBack   callout,
+                                       SCPreferencesContext    *context
+                                       )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesScheduleWithRunLoop
+       @discussion Schedule commit and apply notifications for the specified
+               preferences session using the specified run loop and mode.
+       @param prefs The preferences session.
+       @param runLoop A reference to a run loop on which the notification
+               should be scheduled.
+               Must be non-NULL.
+       @param runLoopMode The mode on which to schedule the notification.
+               Must be non-NULL.
+       @result Returns TRUE if the notifications are successfully scheduled;
+               FALSE otherwise.
+ */
+Boolean
+SCPreferencesScheduleWithRunLoop       (
+                                       SCPreferencesRef        prefs,
+                                       CFRunLoopRef            runLoop,
+                                       CFStringRef             runLoopMode
+                                       )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesUnscheduleFromRunLoop
+       @discussion Unschedule commit and apply notifications for the specified
+               preferences session from the specified run loop and mode.
+       @param prefs The preferences session.
+       @param runLoop A reference to a run loop from which the notification
+               should be unscheduled.
+               Must be non-NULL.
+       @param runLoopMode The mode on which to unschedule the notification.
+               Must be non-NULL.
+       @result Returns TRUE if the notifications are successfully unscheduled;
+               FALSE otherwise.
+ */
+Boolean
+SCPreferencesUnscheduleFromRunLoop     (
+                                       SCPreferencesRef        prefs,
+                                       CFRunLoopRef            runLoop,
+                                       CFStringRef             runLoopMode
+                                       )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
+/*!
+       @function SCPreferencesSynchronize
+       @discussion Synchronizes accessed preferences with committed changes.
+
+               Any references to preference values returned by calls to the
+               SCPreferencesGetValue function are no longer valid unless they
+               were explicitly retained or copied.  Any preference values
+               that were updated (add, set, remove) but not committed will
+               be discarded.
+       @param prefs The preferences session.
+ */
+void
+SCPreferencesSynchronize               (
+                                       SCPreferencesRef        prefs
+                                       )                               AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+
 __END_DECLS
 
 #endif /* _SCPREFERENCES_H */
diff --git a/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h b/SystemConfiguration.fproj/SCPreferencesGetSpecificPrivate.h
new file mode 100644 (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;
 
+       /* lock */
+       pthread_mutex_t         lock;
+
        /* session name */
        CFStringRef             name;
 
@@ -58,7 +61,7 @@ typedef struct {
        Boolean                 perUser;
        CFStringRef             user;
 
-       /* configuration file path */
+       /* configuration file */
        char                    *path;
        char                    *newPath;
 
@@ -73,6 +76,12 @@ typedef struct {
        CFStringRef             sessionKeyCommit;
        CFStringRef             sessionKeyApply;
 
+       /* run loop source, callout, context, rl scheduling info */
+       CFRunLoopSourceRef      rls;
+       SCPreferencesCallBack   rlsFunction;
+       SCPreferencesContext    rlsContext;
+       CFMutableArrayRef       rlList;
+
        /* preferences */
        CFMutableDictionaryRef  prefs;
 
@@ -103,6 +112,12 @@ __SCPreferencesCreate                      (CFAllocatorRef         allocator,
                                         Boolean                perUser,
                                         CFStringRef            user);
 
+Boolean
+__SCPreferencesAccess                  (SCPreferencesRef       prefs);
+
+Boolean
+__SCPreferencesAddSession              (SCPreferencesRef       prefs);
+
 CFDataRef
 __SCPSignatureFromStatbuf              (const struct stat      *statBuf);
 
index e3a85cd272f2fc7b2dc732ebf3800aa8b1324d59..7db6e6a1c8ef8081f6c08c2f044c97dc16aab56e 100644 (file)
 
 /*!
        @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
-       SCPreferencesPathGetValue() API will return the dictionary
+       SCPreferencesPathGetValue function returns the dictionary
        specified by the link.
  */
 
@@ -79,15 +81,14 @@ __BEGIN_DECLS
        @function SCPreferencesPathCreateUniqueChild
        @discussion Creates a new path component within the dictionary
                hierarchy.
-       @param session The SCPreferencesRef handle that should be used to
-        communicate with the APIs.
+       @param prefs The preferences session.
        @param prefix A string that represents the parent path.
-       @result A string representing the new (unique) child path; NULL
+       @result Returns a string representing the new (unique) child path; NULL
                if the specified path does not exist.
  */
 CFStringRef
 SCPreferencesPathCreateUniqueChild     (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             prefix
                                        );
 
@@ -95,15 +96,14 @@ SCPreferencesPathCreateUniqueChild  (
        @function SCPreferencesPathGetValue
        @discussion Returns the dictionary associated with the specified
                path.
-       @param session The SCPreferencesRef handle that should be used to
-               communicate with the APIs.
+       @param prefs The preferences session.
        @param path A string that represents the path to be returned.
-       @result The dictionary associated with the specified path; NULL
+       @result Returns the dictionary associated with the specified path; NULL
                if the path does not exist.
  */
 CFDictionaryRef
 SCPreferencesPathGetValue              (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path
                                        );
 
@@ -111,31 +111,29 @@ SCPreferencesPathGetValue         (
        @function SCPreferencesPathGetLink
        @discussion Returns the link (if one exists) associated with the
                specified path.
-       @param session The SCPreferencesRef handle that should be used to
-        communicate with the APIs.
+       @param prefs The preferences session.
        @param path A string that represents the path to be returned.
-       @result The dictionary associated with the specified path; NULL
+       @result Returns the dictionary associated with the specified path; NULL
                if the path is not a link or does not exist.
  */
 CFStringRef
 SCPreferencesPathGetLink               (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path
                                        );
 
 /*!
        @function SCPreferencesPathSetValue
        @discussion Associates a dictionary with the specified path.
-       @param session The SCPreferencesRef handle that should be used to
-        communicate with the APIs.
+       @param prefs The preferences session.
        @param path A string that represents the path to be updated.
        @param value A dictionary that represents the data to be
                stored at the specified path.
-       @result A boolean indicating the success (or failure) of the call.
+       @result Returns TRUE if successful; FALSE otherwise.
  */
 Boolean
 SCPreferencesPathSetValue              (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path,
                                        CFDictionaryRef         value
                                        );
@@ -144,16 +142,15 @@ SCPreferencesPathSetValue         (
        @function SCPreferencesPathSetLink
        @discussion Associates a link to a second dictionary at the
                specified path.
-       @param session The SCPreferencesRef handle that should be used to
-               communicate with the APIs.
+       @param prefs The preferences session.
        @param path A string that represents the path to be updated.
        @param link A string that represents the link to be stored
                at the specified path.
-       @result A boolean indicating the success (or failure) of the call.
+       @result Returns TRUE if successful; FALSE otherwise.
  */
 Boolean
 SCPreferencesPathSetLink               (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path,
                                        CFStringRef             link
                                        );
@@ -161,14 +158,13 @@ SCPreferencesPathSetLink          (
 /*!
        @function SCPreferencesPathRemoveValue
        @discussion Removes the data associated with the specified path.
-       @param session The SCPreferencesRef handle that should be used to
-        communicate with the APIs.
+       @param prefs The preferences session.
        @param path A string that represents the path to be returned.
-       @result A boolean indicating the success (or failure) of the call.
+       @result Returns TRUE if successful; FALSE otherwise.
  */
 Boolean
 SCPreferencesPathRemoveValue           (
-                                       SCPreferencesRef        session,
+                                       SCPreferencesRef        prefs,
                                        CFStringRef             path
                                        );
 
diff --git a/SystemConfiguration.fproj/SCPreferencesPathKey.c b/SystemConfiguration.fproj/SCPreferencesPathKey.c
new file mode 100644 (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
 
+
+#include <sys/cdefs.h>
+#include <AvailabilityMacros.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <SystemConfiguration/SCPreferences.h>
 
 
+/*!
+       @header SCPreferencesPrivate
+ */
+
 /*!
        @enum SCPreferencesKeyType
        @discussion Used with the SCDynamicStoreKeyCreatePreferences() function
@@ -46,6 +53,7 @@ enum {
 };
 typedef        int32_t SCPreferencesKeyType;
 
+
 __BEGIN_DECLS
 
 /*!
@@ -65,7 +73,7 @@ SCDynamicStoreKeyCreatePreferences    (
                                        CFAllocatorRef          allocator,
                                        CFStringRef             prefsID,
                                        SCPreferencesKeyType    keyType
-                                       );
+                                       )       AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
 
 SCPreferencesRef
 SCUserPreferencesCreate                        (
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@
  * 
 
 /*!
        @header SCPreferencesSetSpecific
-       The following APIs allow an application to set specific
-       configuration information about the current system (e.g. the
-       computer/sharing name).
+       @discussion The functions in the SCPreferencesSetSpecific API allow
+               an application to set specific configuration information
+               about the current system (for example, the computer or
+               sharing name).
+
+               To access configuration preferences, you must first establish
+               a preferences session using the SCPreferencesCreate function.
  */
 
 
@@ -41,16 +45,16 @@ __BEGIN_DECLS
 
 /*!
        @function SCPreferencesSetComputerName
-       @discussion Updates the computer/host name in the system preferences.
+       @discussion Updates the computer name preference.
 
-       Note: In order to commit these changes to permanent storage a call
-       must be made to SCPreferencesCommitChanges().
-       A call to SCPreferencesApplyChanges() is also required for the new
-       name to become active.
-       @param prefs An SCPreferencesRef that should be used for all API calls.
-       @param name The computer/host name to be set.
-       @param nameEncoding The encoding associated with the computer/host name.
-       @result A boolean indicating the success (or failure) of the call.
+               Note: To commit these changes to permanent storage you must
+               call the SCPreferencesCommitChanges function.
+               In addition, you must call the SCPreferencesApplyChanges
+               function for the new name to become active.
+       @param prefs The preferences session.
+       @param name The computer name to be set.
+       @param nameEncoding The encoding associated with the computer name.
+       @result Returns TRUE if successful; FALSE otherwise.
  */
 Boolean
 SCPreferencesSetComputerName           (
@@ -61,18 +65,18 @@ SCPreferencesSetComputerName                (
 
 /*!
        @function SCPreferencesSetLocalHostName
-       @discussion Updates the local host name in the system preferences.
+       @discussion Updates the local host name.
 
-       Note: In order to commit these changes to permanent storage a call
-       must be made to SCPreferencesCommitChanges().
-       A call to SCPreferencesApplyChanges() is also required for the new
-       name to become active.
-       @param prefs An SCPreferencesRef that should be used for all API calls.
+               Note: To commit these changes to permanent storage you must
+               call the SCPreferencesCommitChanges function.
+               In addition, you must call theSCPreferencesApplyChanges
+               function for the new name to become active.
+       @param prefs The preferences session.
        @param name The local host name to be set.
 
-       Note: the string must conform to the naming conventions of a DNS host
+       Note: this string must conform to the naming conventions of a DNS host
                name as specified in RFC 1034 (section 3.5).
-       @result A boolean indicating the success (or failure) of the call.
+       @result Returns TRUE if successful; FALSE otherwise.
  */
 Boolean
 SCPreferencesSetLocalHostName          (
diff --git a/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h b/SystemConfiguration.fproj/SCPreferencesSetSpecificPrivate.h
new file mode 100644 (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@
  * 
@@ -25,6 +25,8 @@
 #define _SCPRIVATE_H
 
 #include <sys/cdefs.h>
+#include <sys/syslog.h>
+#include <mach/message.h>
 
 #include <CoreFoundation/CoreFoundation.h>
 
 #include <SystemConfiguration/SCDynamicStoreSetSpecificPrivate.h>
 
 #include <SystemConfiguration/SCPreferencesPrivate.h>
+#include <SystemConfiguration/SCPreferencesGetSpecificPrivate.h>
+#include <SystemConfiguration/SCPreferencesSetSpecificPrivate.h>
+
+/*!
+       @header SCPrivate
+ */
 
 /* framework variables */
 extern Boolean _sc_debug;      /* TRUE if debugging enabled */
@@ -43,19 +51,19 @@ __BEGIN_DECLS
 
 /*!
        @function _SCErrorSet
-       @discussion Returns a last SystemConfiguration.framework API error code.
-       @result The last error encountered.
+       @discussion Sets the last SystemConfiguration.framework API error code.
+       @param error The error encountered.
  */
 void           _SCErrorSet                     (int                    error);
 
-/*
+/*!
        @function _SCSerialize
        @discussion Serialize a CFPropertyList object for passing
                to/from configd.
        @param obj CFPropertyList object to serialize
        @param xml A pointer to a CFDataRef, NULL if data should be
                vm_allocated.
-       @param data A pointer to the newly allocated/serialized data
+       @param dataRef A pointer to the newly allocated/serialized data
        @param dataLen A pointer to the length in bytes of the newly
                allocated/serialized data
  */
@@ -64,14 +72,14 @@ Boolean             _SCSerialize                    (CFPropertyListRef      obj,
                                                 void                   **dataRef,
                                                 CFIndex                *dataLen);
 
-/*
+/*!
        @function _SCUnserialize
        @discussion Unserialize a stream of bytes passed from/to configd
                into a CFPropertyList object.
        @param obj A pointer to memory that will be filled with the CFPropertyList
                associated with the stream of bytes.
        @param xml CFDataRef with the serialized data
-       @param data A pointer to the serialized data
+       @param dataRef A pointer to the serialized data
        @param dataLen A pointer to the length of the serialized data
 
        Specify either "xml" or "data/dataLen".
@@ -81,14 +89,14 @@ Boolean             _SCUnserialize                  (CFPropertyListRef      *obj,
                                                 void                   *dataRef,
                                                 CFIndex                dataLen);
 
-/*
+/*!
        @function _SCSerializeString
        @discussion Serialize a CFString object for passing
                to/from configd.
        @param str CFString key to serialize
        @param data A pointer to a CFDataRef, NULL if storage should be
                vm_allocated.
-       @param data A pointer to the newly allocated/serialized data
+       @param dataRef A pointer to the newly allocated/serialized data
        @param dataLen A pointer to the length in bytes of the newly
                allocated/serialized data
  */
@@ -97,14 +105,14 @@ Boolean            _SCSerializeString              (CFStringRef            str,
                                                 void                   **dataRef,
                                                 CFIndex                *dataLen);
 
-/*
+/*!
        @function _SCUnserializeString
        @discussion Unserialize a stream of bytes passed from/to configd
                into a CFString object.
        @param str A pointer to memory that will be filled with the CFPropertyList
                associated with the stream of bytes.
        @param utf8 CFDataRef with the serialized data
-       @param data A pointer to the serialized data
+       @param dataRef A pointer to the serialized data
        @param dataLen A pointer to the length of the serialized data
 
        Specify either "utf8" or "data/dataLen".
@@ -114,12 +122,12 @@ Boolean           _SCUnserializeString            (CFStringRef            *str,
                                                 void                   *dataRef,
                                                 CFIndex                dataLen);
 
-/*
+/*!
        @function _SCSerializeData
        @discussion Serialize a CFData object for passing
                to/from configd.
        @param data CFData key to serialize
-       @param data A pointer to the newly allocated/serialized data
+       @param dataRef A pointer to the newly allocated/serialized data
        @param dataLen A pointer to the length in bytes of the newly
                allocated/serialized data
  */
@@ -127,20 +135,20 @@ Boolean           _SCSerializeData                (CFDataRef              data,
                                                 void                   **dataRef,
                                                 CFIndex                *dataLen);
 
-/*
+/*!
        @function _SCUnserializeData
        @discussion Unserialize a stream of bytes passed from/to configd
                into a CFData object.
        @param data A pointer to memory that will be filled with the CFPropertyList
                associated with the stream of bytes.
-       @param data A pointer to the serialized data
+       @param dataRef A pointer to the serialized data
        @param dataLen A pointer to the length of the serialized data
  */
 Boolean                _SCUnserializeData              (CFDataRef              *data,
                                                 void                   *dataRef,
                                                 CFIndex                dataLen);
 
-/*
+/*!
        @function _SCSerializeMultiple
        @discussion Convert a CFDictionary containing a set of CFPropertlyList
                values into a CFDictionary containing a set of serialized CFData
@@ -150,7 +158,7 @@ Boolean             _SCUnserializeData              (CFDataRef              *data,
  */
 CFDictionaryRef        _SCSerializeMultiple            (CFDictionaryRef        dict);
 
-/*
+/*!
        @function _SCUnserializeMultiple
        @discussion Convert a CFDictionary containing a set of CFData
                values into a CFDictionary containing a set of serialized
@@ -160,11 +168,11 @@ CFDictionaryRef   _SCSerializeMultiple            (CFDictionaryRef        dict);
  */
 CFDictionaryRef        _SCUnserializeMultiple          (CFDictionaryRef        dict);
 
-/*
+/*!
        @function _SC_cfstring_to_cstring
        @discussion Extracts a C-string from a CFString.
        @param cfstr The CFString to extract the data from.
-       @param buf A user provided buffer of the specefied length.  If NULL,
+       @param buf A user provided buffer of the specified length.  If NULL,
                a new buffer will be allocated to contain the C-string.  It
                is the responsiblity of the caller to free an allocated
                buffer.
@@ -179,7 +187,18 @@ char *             _SC_cfstring_to_cstring         (CFStringRef            cfstr,
                                                 int                    bufLen,
                                                 CFStringEncoding       encoding);
 
-/*
+/*!
+ *      @function _SC_sockaddr_to_string
+ *      @discussion Formats a "struct sockaddr" for reporting
+ *      @param address The address to format
+ *     @param buf A user provided buffer of the specified length.
+ *     @param bufLen The size of the user provided buffer.
+ */
+void           _SC_sockaddr_to_string          (const struct sockaddr  *address,
+                                                char                   *buf,
+                                                size_t                 bufLen);
+
+/*!
        @function SCLog
        @discussion Conditionally issue a log message.
        @param condition A boolean value indicating if the message should be logged
@@ -193,7 +212,7 @@ void                SCLog                           (Boolean                condition,
                                                 CFStringRef            formatString,
                                                 ...);
 
-/*
+/*!
        @function SCPrint
        @discussion Conditionally issue a debug message.
        @param condition A boolean value indicating if the message should be written
@@ -207,7 +226,7 @@ void                SCPrint                         (Boolean                condition,
                                                 CFStringRef            formatString,
                                                 ...);
 
-/*
+/*!
        @function SCTrace
        @discussion Conditionally issue a debug message with a time stamp.
        @param condition A boolean value indicating if the message should be written
@@ -221,6 +240,33 @@ void               SCTrace                         (Boolean                condition,
                                                 CFStringRef            formatString,
                                                 ...);
 
+/*
+ * object / CFRunLoop  management
+ */
+void
+_SC_signalRunLoop                              (CFTypeRef              obj,
+                                                CFRunLoopSourceRef     rls,
+                                                CFArrayRef             rlList);
+
+Boolean
+_SC_isScheduled                                        (CFTypeRef              obj,
+                                                CFRunLoopRef           runLoop,
+                                                CFStringRef            runLoopMode,
+                                                CFMutableArrayRef      rlList);
+
+void
+_SC_schedule                                   (CFTypeRef              obj,
+                                                CFRunLoopRef           runLoop,
+                                                CFStringRef            runLoopMode,
+                                                CFMutableArrayRef      rlList);
+
+Boolean
+_SC_unschedule                                 (CFTypeRef              obj,
+                                                CFRunLoopRef           runLoop,
+                                                CFStringRef            runLoopMode,
+                                                CFMutableArrayRef      rlList,
+                                                Boolean                all);
+
 __END_DECLS
 
 #endif /* _SCPRIVATE_H */
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@
  * 
@@ -32,6 +32,9 @@
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
+#include <netdb.h>
+
+
 CFStringRef
 SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator)
 {
@@ -41,39 +44,222 @@ SCDynamicStoreKeyCreateProxies(CFAllocatorRef allocator)
 }
 
 
+static void
+validate_proxy_content(CFMutableDictionaryRef  proxies,
+                      CFStringRef              proxy_enable,
+                      CFStringRef              proxy_host,
+                      CFStringRef              proxy_port,
+                      const char *             proxy_service,
+                      int                      proxy_defaultport)
+{
+       int             enabled = 0;
+       CFNumberRef     num;
+       CFStringRef     host;
+       CFNumberRef     port    = NULL;
+
+       num = CFDictionaryGetValue(proxies, proxy_enable);
+       if (num != NULL) {
+               if (!isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
+                       // if we don't like the enabled key/value
+                       goto disable;
+               }
+       }
+
+       host = CFDictionaryGetValue(proxies, proxy_host);
+       if (((enabled == 0) && (host != NULL)) ||
+           ((enabled != 0) && !isA_CFString(host))) {
+               // pass only valid proxy hosts and only when enabled
+               goto disable;
+       }
+
+       if (proxy_port != NULL) {
+               port = CFDictionaryGetValue(proxies, proxy_port);
+               if (((enabled == 0) && (port != NULL)) ||
+                   ((enabled != 0) && (port != NULL) && !isA_CFNumber(port))) {
+                       // pass only provided/valid proxy ports and only when enabled
+                       goto disable;
+               }
+
+               if ((enabled != 0) && (port == NULL)) {
+                       struct servent  *service;
+
+                       service = getservbyname(proxy_service, "tcp");
+                       num = CFNumberCreate(NULL,
+                                            kCFNumberIntType,
+                                            (service != NULL) ? &service->s_port : &proxy_defaultport);
+                       CFDictionarySetValue(proxies, proxy_port, num);
+                       CFRelease(num);
+               }
+       }
+
+       return;
+
+    disable :
+
+       enabled = 0;
+       num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
+       CFDictionarySetValue(proxies, proxy_enable, num);
+       CFRelease(num);
+       CFDictionaryRemoveValue(proxies, proxy_host);
+       if (proxy_port != NULL) {
+               CFDictionaryRemoveValue(proxies, proxy_port);
+       }
+
+       return;
+}
+
+
 CFDictionaryRef
 SCDynamicStoreCopyProxies(SCDynamicStoreRef store)
 {
-       CFDictionaryRef         dict            = NULL;
+       CFArrayRef              array;
        CFStringRef             key;
-       CFDictionaryRef         proxies         = NULL;
+       CFMutableDictionaryRef  newProxies      = NULL;
+       CFNumberRef             num;
+       CFDictionaryRef         proxies;
        Boolean                 tempSession     = FALSE;
 
-       if (!store) {
+
+
+       /* copy proxy information from dynamic store */
+
+       if (store == NULL) {
                store = SCDynamicStoreCreate(NULL,
                                             CFSTR("SCDynamicStoreCopyProxies"),
                                             NULL,
                                             NULL);
-               if (!store) {
-                       SCLog(_sc_verbose, LOG_INFO, CFSTR("SCDynamicStoreCreate() failed"));
+               if (store == NULL) {
                        return NULL;
                }
                tempSession = TRUE;
        }
 
-       key  = SCDynamicStoreKeyCreateProxies(NULL);
-       dict = SCDynamicStoreCopyValue(store, key);
+       key = SCDynamicStoreKeyCreateProxies(NULL);
+       proxies = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
-       if (!isA_CFDictionary(dict)) {
-               _SCErrorSet(kSCStatusNoKey);
-               goto done;
+
+    validate :
+
+       if (proxies != NULL) {
+               if (isA_CFDictionary(proxies)) {
+                       newProxies = CFDictionaryCreateMutableCopy(NULL, 0, proxies);
+               }
+               CFRelease(proxies);
+       }
+
+       if (newProxies == NULL) {
+               newProxies = CFDictionaryCreateMutable(NULL,
+                                                      0,
+                                                      &kCFTypeDictionaryKeyCallBacks,
+                                                      &kCFTypeDictionaryValueCallBacks);
        }
 
-       proxies = CFRetain(dict);
+       /* validate [and augment] proxy content */
+
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesFTPEnable,
+                              kSCPropNetProxiesFTPProxy,
+                              kSCPropNetProxiesFTPPort,
+                              "ftp",
+                              21);
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesGopherEnable,
+                              kSCPropNetProxiesGopherProxy,
+                              kSCPropNetProxiesGopherPort,
+                              "gopher",
+                              70);
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesHTTPEnable,
+                              kSCPropNetProxiesHTTPProxy,
+                              kSCPropNetProxiesHTTPPort,
+                              "http",
+                              80);
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesHTTPSEnable,
+                              kSCPropNetProxiesHTTPSProxy,
+                              kSCPropNetProxiesHTTPSPort,
+                              "https",
+                              443);
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesRTSPEnable,
+                              kSCPropNetProxiesRTSPProxy,
+                              kSCPropNetProxiesRTSPPort,
+                              "rtsp",
+                              554);
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesSOCKSEnable,
+                              kSCPropNetProxiesSOCKSProxy,
+                              kSCPropNetProxiesSOCKSPort,
+                              "socks",
+                              1080);
+       validate_proxy_content(newProxies,
+                              kSCPropNetProxiesProxyAutoConfigEnable,
+                              kSCPropNetProxiesProxyAutoConfigURLString,
+                              NULL,
+                              NULL,
+                              0);
+
+       // validate WPAD setting
+       num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesProxyAutoDiscoveryEnable);
+       if (num != NULL) {
+               int     enabled;
+
+               if (!isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
+                       // if we don't like the enabled key/value
+                       enabled = 0;
+                       num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
+                       CFDictionarySetValue(newProxies,
+                                            kSCPropNetProxiesProxyAutoDiscoveryEnable,
+                                            num);
+                       CFRelease(num);
+               }
+       }
+
+       // validate proxy exception list
+       array = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExceptionsList);
+       if (array != NULL) {
+               CFIndex         i;
+               CFIndex         n;
+
+               n = isA_CFArray(array) ? CFArrayGetCount(array) : 0;
+               for (i = 0; i < n; i++) {
+                       CFStringRef     str;
+
+                       str = CFArrayGetValueAtIndex(array, i);
+                       if (!isA_CFString(str)) {
+                               // if we don't like the array contents
+                               n = 0;
+                               break;
+                       }
+               }
+
+               if (n == 0) {
+                       CFDictionaryRemoveValue(newProxies, kSCPropNetProxiesExceptionsList);
+               }
+       }
+
+       // validate exclude simple hostnames setting
+       num = CFDictionaryGetValue(newProxies, kSCPropNetProxiesExcludeSimpleHostnames);
+       if (num != NULL) {
+               int     enabled;
+
+               if (!isA_CFNumber(num) ||
+                   !CFNumberGetValue(num, kCFNumberIntType, &enabled)) {
+                       // if we don't like the enabled key/value
+                       enabled = 0;
+                       num = CFNumberCreate(NULL, kCFNumberIntType, &enabled);
+                       CFDictionarySetValue(newProxies,
+                                            kSCPropNetProxiesExcludeSimpleHostnames,
+                                            num);
+                       CFRelease(num);
+               }
+       }
 
-    done :
+       proxies = CFDictionaryCreateCopy(NULL, newProxies);
+       CFRelease(newProxies);
 
        if (tempSession)        CFRelease(store);
-       if (dict)               CFRelease(dict);
        return proxies;
 }
diff --git a/SystemConfiguration.fproj/SCSchemaDefinitions.c b/SystemConfiguration.fproj/SCSchemaDefinitions.c
new file mode 100644 (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 kSCStatusKeyExists            Data associated with key already defined
        @constant kSCStatusLocked               Lock already held
        @constant kSCStatusNeedLock             Lock required for this operation
-
        @constant kSCStatusNoStoreSession       Configuration daemon session not active
-       @constant kSCStatusNoStoreServer        Configuration daemon not (no longer) available
+       @constant kSCStatusNoStoreServer        Configuration daemon not (or no longer) available
        @constant kSCStatusNotifierActive       Notifier is currently active
-
-       @constant kSCStatusNoPrefsSession       Preference session not active
+       @constant kSCStatusNoPrefsSession       Preferences session not active
        @constant kSCStatusPrefsBusy            Preferences update currently in progress
        @constant kSCStatusNoConfigFile         Configuration file not found
        @constant kSCStatusNoLink               No such link
        @constant kSCStatusStale                Write attempted on stale version of object
        @constant kSCStatusMaxLink              Maximum link count exceeded
-
        @constant kSCStatusReachabilityUnknown
                A determination could not be made regarding the reachability
-               of the specified nodename/address.
+               of the specified nodename or address.
 */
 enum {
        /*
-        * Generic status codes
+        * Generic error codes
         */
        kSCStatusOK                             = 0,    /* Success */
        kSCStatusFailed                         = 1001, /* Non-specific failure */
@@ -88,13 +83,13 @@ enum {
        kSCStatusLocked                         = 1006, /* Lock already held */
        kSCStatusNeedLock                       = 1007, /* Lock required for this operation */
        /*
-        * SCDynamicStore status codes
+        * SCDynamicStore error codes
         */
        kSCStatusNoStoreSession                 = 2001, /* Configuration daemon session not active */
        kSCStatusNoStoreServer                  = 2002, /* Configuration daemon not (no longer) available */
        kSCStatusNotifierActive                 = 2003, /* Notifier is currently active */
        /*
-        * SCPreferences status codes
+        * SCPreferences error codes
         */
        kSCStatusNoPrefsSession                 = 3001, /* Preference session not active */
        kSCStatusPrefsBusy                      = 3002, /* Preferences update currently in progress */
@@ -103,7 +98,7 @@ enum {
        kSCStatusStale                          = 3005, /* Write attempted on stale version of object */
        kSCStatusMaxLink                        = 3006, /* Maximum link count exceeded */
        /*
-        * SCNetwork status codes
+        * SCNetwork error codes
         */
        kSCStatusReachabilityUnknown            = 4001  /* Network reachability cannot be determined */
 };
@@ -118,6 +113,9 @@ enum {
 #include <SystemConfiguration/SCPreferences.h>
 #include <SystemConfiguration/SCPreferencesPath.h>
 
+/* network configuration */
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+
 /* store and preference scheme definitions */
 #include <SystemConfiguration/SCSchemaDefinitions.h>
 
@@ -130,17 +128,18 @@ __BEGIN_DECLS
 
 /*!
        @function SCError
-       @discussion Returns a last SystemConfiguration.framework API error code.
-       @result The last error encountered.
+       @discussion Returns the most recent status or error code generated
+               as the result of calling a System Configuration framework API.
+       @result Returns the last error encountered.
  */
 int    SCError                         ();
 
 /*!
        @function SCErrorString
-       @discussion Returns a pointer to the error message string associated
-               with the specified status.
+       @discussion Returns a pointer to the message string
+               associated with the specified status or error.
        @param status The SCDynamicStoreStatus to be returned.
-       @result The error message string.
+       @result Returns a pointer to the error message string.
  */
 const char *   SCErrorString           (int    status);
 
index 70728920960e088532f178848bc247aa99cbb620..97367ce8e681ac0aca7f9bb9bccba578e1cc3609 100644 (file)
 #include <CoreFoundation/CFRuntime.h>
 
 #include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCNetworkConfigurationInternal.h>
 #include <SystemConfiguration/SCValidation.h>
 #include <SystemConfiguration/SCPrivate.h>
 
 #include <ifaddrs.h>
 #include <pthread.h>
+#include <unistd.h>
 #include <sys/types.h>
-#define        KERNEL_PRIVATE
 #include <sys/ioctl.h>
-#undef KERNEL_PRIVATE
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <net/ethernet.h>
-#define        KERNEL_PRIVATE  1
+#define        KERNEL_PRIVATE
 #include <net/if.h>
 #include <net/if_var.h>
 #undef KERNEL_PRIVATE
@@ -73,60 +73,9 @@ inet_dgram_socket()
 }
 
 
-static Boolean
-_VLAN_create(int s, CFStringRef interface)
-{
-#ifdef SIOCIFCREATE
-       struct ifreq    ifr;
-
-       bzero(&ifr, sizeof(ifr));
-       (void) _SC_cfstring_to_cstring(interface,
-                                      ifr.ifr_name,
-                                      sizeof(ifr.ifr_name),
-                                      kCFStringEncodingASCII);
-
-       if (ioctl(s, SIOCIFCREATE, &ifr) == -1) {
-               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCIFCREATE) failed: %s"), strerror(errno));
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
-       }
-
-       return TRUE;
-#else  /* SIOCIFCREATE */
-       return FALSE;
-#endif /* SIOCIFCREATE */
-}
-
-
-static Boolean
-_VLAN_destroy(int s, CFStringRef interface)
-{
-#ifdef SIOCIFDESTROY
-       struct ifreq    ifr;
-
-       bzero(&ifr, sizeof(ifr));
-       (void) _SC_cfstring_to_cstring(interface,
-                                      ifr.ifr_name,
-                                      sizeof(ifr.ifr_name),
-                                      kCFStringEncodingASCII);
-
-       if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) {
-               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCIFDESTROY) failed: %s"), strerror(errno));
-               _SCErrorSet(kSCStatusFailed);
-               return FALSE;
-       }
-
-       return TRUE;
-#else  /* SIOCIFDESTROY */
-       return FALSE;
-#endif /* SIOCIFDESTROY */
-}
-
-
 static Boolean
 _VLANDevice_set(int s, CFStringRef interface, CFStringRef device, CFNumberRef tag)
 {
-#ifdef SIOCSETVLAN
        struct ifreq    ifr;
        int             tag_val;
        struct vlanreq  vreq;
@@ -152,23 +101,25 @@ _VLANDevice_set(int s, CFStringRef interface, CFStringRef device, CFNumberRef ta
        vreq.vlr_tag = tag_val;
 
        // update parent device and tag
-       if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) {
-               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSETVLAN) failed: %s"), strerror(errno));
+       if (ioctl(s, SIOCSIFVLAN, (caddr_t)&ifr) == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSIFVLAN) failed: %s"), strerror(errno));
+               _SCErrorSet(kSCStatusFailed);
+               return FALSE;
+       }
+
+       // mark the parent device "up"
+       if (!__markInterfaceUp(s, device)) {
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
 
        return TRUE;
-#else  /* SIOCSETVLAN */
-       return FALSE;
-#endif /* SIOCSETVLAN */
 }
 
 
 static Boolean
 _VLANDevice_unset(int s, CFStringRef interface)
 {
-#ifdef SIOCSETVLAN
        struct ifreq    ifr;
        struct vlanreq  vreq;
 
@@ -189,16 +140,13 @@ _VLANDevice_unset(int s, CFStringRef interface)
        vreq.vlr_tag = 0;
 
        // update parent device and tag
-       if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1) {
-               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSETVLAN) failed: %s"), strerror(errno));
+       if (ioctl(s, SIOCSIFVLAN, (caddr_t)&ifr) == -1) {
+               SCLog(TRUE, LOG_ERR, CFSTR("ioctl(SIOCSIFVLAN) failed: %s"), strerror(errno));
                _SCErrorSet(kSCStatusFailed);
                return FALSE;
        }
 
        return TRUE;
-#else  /* SIOCSETVLAN */
-       return FALSE;
-#endif /* SIOCSETVLAN */
 }
 
 
@@ -217,7 +165,7 @@ IsVLANSupported(CFStringRef device)
 
        /* get the interface index */
 
-       if_name = _SC_cfstring_to_cstring(device, NULL, NULL, kCFStringEncodingASCII);
+       if_name = _SC_cfstring_to_cstring(device, NULL, 0, kCFStringEncodingASCII);
        if (if_name == NULL) {
                return FALSE;   // if conversion error
        }
@@ -335,8 +283,6 @@ __VLANInterfaceDeallocate(CFTypeRef cf)
 {
        VLANInterfacePrivateRef vlanPrivate     = (VLANInterfacePrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceDeallocate:"));
-
        /* release resources */
 
        CFRelease(vlanPrivate->ifname);
@@ -430,8 +376,6 @@ __VLANInterfaceCreatePrivate(CFAllocatorRef allocator,
        VLANInterfacePrivateRef         vlanPrivate;
        uint32_t                        size;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANInterfaceCreatePrivate:"));
-
        /* initialize runtime */
        pthread_once(&vlanInterface_init, __VLANInterfaceInitialize);
 
@@ -655,8 +599,6 @@ __VLANPreferencesDeallocate(CFTypeRef cf)
 {
        VLANPreferencesPrivateRef       prefsPrivate    = (VLANPreferencesPrivateRef)cf;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesDeallocate:"));
-
        /* release resources */
 
        pthread_mutex_destroy(&prefsPrivate->lock);
@@ -736,7 +678,7 @@ _VLANPreferencesCopyActiveInterfaces()
                                strncpy(ifr.ifr_name, ifp->ifa_name, sizeof(ifr.ifr_name));
                                ifr.ifr_data = (caddr_t)&vreq;
 
-                               if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1) {
+                               if (ioctl(s, SIOCGIFVLAN, (caddr_t)&ifr) == -1) {
                                        SCLog(TRUE, LOG_ERR, CFSTR("ioctl() failed: %s"), strerror(errno));
                                        _SCErrorSet(kSCStatusFailed);
                                        CFRelease(vlans);
@@ -854,8 +796,6 @@ VLANPreferencesCreate(CFAllocatorRef allocator)
        VLANPreferencesPrivateRef       prefsPrivate;
        uint32_t                        size;
 
-       SCLog(_sc_verbose, LOG_DEBUG, CFSTR("__VLANPreferencesCreate:"));
-
        /* initialize runtime */
        pthread_once(&vlanPreferences_init, __VLANPreferencesInitialize);
 
@@ -865,7 +805,7 @@ VLANPreferencesCreate(CFAllocatorRef allocator)
                                                                           __kVLANPreferencesTypeID,
                                                                           size,
                                                                           NULL);
-       if (!prefsPrivate) {
+       if (prefsPrivate == NULL) {
                return NULL;
        }
 
@@ -1099,6 +1039,9 @@ VLANPreferencesAddInterface(VLANPreferencesRef    prefs,
 
                newVlan = __VLANInterfaceCreatePrivate(allocator, vlan_if, device, tag, options);
 
+               /* yes, we're going to be changing the configuration */
+               setConfigurationChanged(prefs);
+
                /* save in the prefs */
 
                if (nConfig == 0) {
@@ -1112,9 +1055,6 @@ VLANPreferencesAddInterface(VLANPreferencesRef    prefs,
                (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
                CFRelease(newVlans);
 
-               /* yes, we've change the configuration */
-               setConfigurationChanged(prefs);
-
            next_if :
                CFRelease(vlan_if);
        }
@@ -1253,19 +1193,18 @@ VLANPreferencesUpdateInterface(VLANPreferencesRef       prefs,
                CFDictionaryAddValue(newDict, __kVLANInterface_options, newOptions);
        }
 
+       /* yes, we're going to be changing the configuration */
+       setConfigurationChanged(prefs);
+
        /* update the prefs */
 
        newVlans = CFArrayCreateMutableCopy(allocator, 0, vlans);
-       CFArrayRemoveValueAtIndex(newVlans, cur_if);
-       CFArrayAppendValue(newVlans, newDict);
+       CFArraySetValueAtIndex(newVlans, cur_if, newDict);
        CFRelease(newDict);
 
        (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
        CFRelease(newVlans);
 
-       /* yes, we've change the configuration */
-       setConfigurationChanged(prefs);
-
        ok = TRUE;
 
     done :
@@ -1313,6 +1252,9 @@ VLANPreferencesRemoveInterface(VLANPreferencesRef prefs,
                goto done;
        }
 
+       /* yes, we're going to be changing the configuration */
+       setConfigurationChanged(prefs);
+
        /* remove the vlan */
 
        allocator = CFGetAllocator(prefs);
@@ -1322,9 +1264,6 @@ VLANPreferencesRemoveInterface(VLANPreferencesRef prefs,
        (void) SCPreferencesSetValue(prefsPrivate->prefs, VLAN_PREFERENCES_VLANS, newVlans);
        CFRelease(newVlans);
 
-       /* yes, we've change the configuration */
-       setConfigurationChanged(prefs);
-
        ok = TRUE;
 
     done :
@@ -1433,8 +1372,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs)
                                s = inet_dgram_socket();
                        }
 
-                       ok = _VLAN_destroy(s, a_vlan_if);
+                       ok = __destroyInterface(s, a_vlan_if);
                        if (!ok) {
+                               _SCErrorSet(kSCStatusFailed);
                                goto done;
                        }
                }
@@ -1491,8 +1431,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs)
                                                }
                                        } else {
                                                // if the new [parent] device does not support VLANs
-                                               ok = _VLAN_destroy(s, c_vlan_if);
+                                               ok = __destroyInterface(s, c_vlan_if);
                                                if (!ok) {
+                                                       _SCErrorSet(kSCStatusFailed);
                                                        goto done;
                                                }
                                        }
@@ -1509,8 +1450,9 @@ _VLANPreferencesUpdateConfiguration(VLANPreferencesRef prefs)
                                s = inet_dgram_socket();
                        }
 
-                       ok = _VLAN_create(s, c_vlan_if);
+                       ok = __createInterface(s, c_vlan_if);
                        if (!ok) {
+                               _SCErrorSet(kSCStatusFailed);
                                goto done;
                        }
 
@@ -1563,8 +1505,6 @@ VLANPreferencesApplyChanges(VLANPreferencesRef prefs)
                goto done;
        }
 
-       ok = TRUE;
-
     done :
 
        pthread_mutex_unlock(&prefsPrivate->lock);
index bfa115e35c705196f60e89e1cce9c9baebafc3f6..9fa8c9be9173fac6c069b0a7656bd54cdd267413 100644 (file)
@@ -24,6 +24,9 @@
 #ifndef _VLANCONFIGURATION_H
 #define _VLANCONFIGURATION_H
 
+/*!
+       @header VLANConfiguration
+*/
 
 #include <sys/cdefs.h>
 #include <CoreFoundation/CoreFoundation.h>
index 811e616520ae65b943579b03d28f6208a522337b..bf0b4054ef54440188e6c2fcd0829cc31cf97958 100644 (file)
 #include <CoreFoundation/CoreFoundation.h>
 
 
+#include <SystemConfiguration/VLANConfiguration.h>
+
+
+/*!
+       @header VLANConfigurationPrivate
+ */
+
+
 #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;
+                               options         : xmlData;
                         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)
 {
-       static CFMutableDictionaryRef (*dyfunc)(mach_port_t, unsigned int, const char *) = NULL;
+       #undef IOBSDNameMatching
+       static typeof (IOBSDNameMatching) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOBSDNameMatching", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -73,7 +74,8 @@ _IOBSDNameMatching(mach_port_t masterPort, unsigned int options, const char *bsd
 __private_extern__ io_object_t
 _IOIteratorNext(io_iterator_t iterator)
 {
-       static io_object_t (*dyfunc)(io_iterator_t) = NULL;
+       #undef IOIteratorNext
+       static typeof (IOIteratorNext) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOIteratorNext", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -85,7 +87,8 @@ _IOIteratorNext(io_iterator_t iterator)
 __private_extern__ kern_return_t
 _IOMasterPort(mach_port_t bootstrapPort, mach_port_t *masterPort)
 {
-       static kern_return_t (*dyfunc)(mach_port_t, mach_port_t *) = NULL;
+       #undef IOMasterPort
+       static typeof (IOMasterPort) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOMasterPort", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -94,10 +97,37 @@ _IOMasterPort(mach_port_t bootstrapPort, mach_port_t *masterPort)
 }
 
 
+__private_extern__ boolean_t
+_IOObjectConformsTo(io_object_t object, const io_name_t className)
+{
+       #undef IOObjectConformsTo
+       static typeof (IOObjectConformsTo) *dyfunc = NULL;
+       if (!dyfunc) {
+               void *image = __loadIOKit();
+               if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOObjectConformsTo", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+       }
+       return dyfunc ? dyfunc(object, className) : FALSE;
+}
+
+
+__private_extern__ boolean_t
+_IOObjectGetClass(io_object_t object, io_name_t className)
+{
+       #undef IOObjectGetClass
+       static typeof (IOObjectGetClass) *dyfunc = NULL;
+       if (!dyfunc) {
+               void *image = __loadIOKit();
+               if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOObjectGetClass", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+       }
+       return dyfunc ? dyfunc(object, className) : FALSE;
+}
+
+
 __private_extern__ kern_return_t
 _IOObjectRelease(io_object_t object)
 {
-       static kern_return_t (*dyfunc)(io_object_t) = NULL;
+       #undef IOObjectRelease
+       static typeof (IOObjectRelease) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOObjectRelease", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -109,7 +139,8 @@ _IOObjectRelease(io_object_t object)
 __private_extern__ CFTypeRef
 _IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options)
 {
-       static CFTypeRef (*dyfunc)(io_registry_entry_t, CFStringRef, CFAllocatorRef, IOOptionBits) = NULL;
+       #undef IORegistryEntryCreateCFProperty
+       static typeof (IORegistryEntryCreateCFProperty) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryCreateCFProperty", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -121,7 +152,8 @@ _IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFA
 __private_extern__ kern_return_t
 _IORegistryEntryCreateCFProperties(io_registry_entry_t entry, CFMutableDictionaryRef *properties, CFAllocatorRef allocator, IOOptionBits options)
 {
-       static kern_return_t (*dyfunc)(io_registry_entry_t, CFMutableDictionaryRef *, CFAllocatorRef, IOOptionBits) = NULL;
+       #undef IORegistryEntryCreateCFProperties
+       static typeof (IORegistryEntryCreateCFProperties) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryCreateCFProperties", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -130,22 +162,50 @@ _IORegistryEntryCreateCFProperties(io_registry_entry_t entry, CFMutableDictionar
 }
 
 
+__private_extern__ kern_return_t
+_IORegistryEntryCreateIterator(mach_port_t masterPort, const io_name_t plane, IOOptionBits options, io_iterator_t *iterator)
+{
+       #undef IORegistryEntryCreateIterator
+       static typeof (IORegistryEntryCreateIterator) *dyfunc = NULL;
+       if (!dyfunc) {
+               void *image = __loadIOKit();
+               if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryCreateIterator", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+       }
+       return dyfunc ? dyfunc(masterPort, plane, options, iterator) : KERN_FAILURE;
+}
+
+
+__private_extern__ kern_return_t
+_IORegistryEntryGetName(io_registry_entry_t entry, io_name_t name)
+{
+       #undef IORegistryEntryGetName
+       static typeof (IORegistryEntryGetName) *dyfunc = NULL;
+       if (!dyfunc) {
+               void *image = __loadIOKit();
+               if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryGetName", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+       }
+       return dyfunc ? dyfunc(entry, name) : KERN_FAILURE;
+}
+
+
 __private_extern__ kern_return_t
 _IORegistryEntryGetParentEntry(io_registry_entry_t entry, const io_name_t plane, io_registry_entry_t *parent)
 {
-       static kern_return_t (*dyfunc)(io_registry_entry_t, const io_name_t, io_registry_entry_t *) = NULL;
+       #undef IORegistryEntryGetParentEntry
+       static typeof (IORegistryEntryGetParentEntry) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryGetParentEntry", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
        }
-       return dyfunc ? dyfunc(entry, plane, parent) : NULL;
+       return dyfunc ? dyfunc(entry, plane, parent) : KERN_FAILURE;
 }
 
 
 __private_extern__ kern_return_t
 _IORegistryEntryGetPath(io_registry_entry_t entry, const io_name_t plane, io_string_t path)
 {
-       static kern_return_t (*dyfunc)(io_registry_entry_t, const io_name_t, io_string_t) = NULL;
+       #undef IORegistryEntryGetPath
+       static typeof (IORegistryEntryGetPath) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntryGetPath", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -154,10 +214,24 @@ _IORegistryEntryGetPath(io_registry_entry_t entry, const io_name_t plane, io_str
 }
 
 
+__private_extern__ CFTypeRef
+_IORegistryEntrySearchCFProperty(io_registry_entry_t entry, const io_name_t plane, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options)
+{
+       #undef IORegistryEntrySearchCFProperty
+       static typeof (IORegistryEntrySearchCFProperty) *dyfunc = NULL;
+       if (!dyfunc) {
+               void *image = __loadIOKit();
+               if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IORegistryEntrySearchCFProperty", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
+       }
+       return dyfunc ? dyfunc(entry, plane, key, allocator, options) : NULL;
+}
+
+
 __private_extern__ kern_return_t
 _IOServiceGetMatchingServices(mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t *existing)
 {
-       static kern_return_t (*dyfunc)(mach_port_t, CFDictionaryRef, io_iterator_t *) = NULL;
+       #undef IOServiceGetMatchingServices
+       static typeof (IOServiceGetMatchingServices) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOServiceGetMatchingServices", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -169,7 +243,8 @@ _IOServiceGetMatchingServices(mach_port_t masterPort, CFDictionaryRef matching,
 __private_extern__ CFMutableDictionaryRef
 _IOServiceMatching(const char *name)
 {
-       static CFMutableDictionaryRef (*dyfunc)(const char *) = NULL;
+       #undef IOServiceMatching
+       static typeof (IOServiceMatching) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadIOKit();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_IOServiceMatching", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -201,7 +276,8 @@ __loadSecurity(void) {
 __private_extern__ OSStatus
 _SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData)
 {
-       static OSStatus (*dyfunc)(SecKeychainItemRef, SecItemClass *, SecKeychainAttributeList *, UInt32 *, void **) = NULL;
+       #undef SecKeychainItemCopyContent
+       static typeof (SecKeychainItemCopyContent) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadSecurity();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainItemCopyContent", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -212,7 +288,8 @@ _SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass,
 __private_extern__ OSStatus
 _SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *itemRef)
 {
-       static OSStatus (*dyfunc)(SecKeychainSearchRef, SecKeychainItemRef *) = NULL;
+       #undef SecKeychainSearchCopyNext
+       static typeof (SecKeychainSearchCopyNext) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadSecurity();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCopyNext", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
@@ -223,7 +300,8 @@ _SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *i
 __private_extern__ OSStatus
 _SecKeychainSearchCreateFromAttributes(CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef)
 {
-       static OSStatus (*dyfunc)(CFTypeRef, SecItemClass, const SecKeychainAttributeList *, SecKeychainSearchRef *) = NULL;
+       #undef SecKeychainSearchCreateFromAttributes
+       static typeof (SecKeychainSearchCreateFromAttributes) *dyfunc = NULL;
        if (!dyfunc) {
                void *image = __loadSecurity();
                if (image) dyfunc = NSAddressOfSymbol(NSLookupSymbolInImage(image, "_SecKeychainSearchCreateFromAttributes", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
index 6560839ad444ce1301582a2865a9486903e81733..e21bcb8ce73939c347a6243f3a8b47f6e2586a17 100644 (file)
@@ -54,6 +54,20 @@ _IOMasterPort                                (
                                        );
 #define IOMasterPort _IOMasterPort
 
+boolean_t
+_IOObjectConformsTo                    (
+                                       io_object_t             object,
+                                       const io_name_t         className
+                                       );
+#define IOObjectConformsTo _IOObjectConformsTo
+
+boolean_t
+_IOObjectGetClass                      (
+                                       io_object_t             object,
+                                       io_name_t               className
+                                       );
+#define IOObjectGetClass _IOObjectGetClass
+
 kern_return_t
 _IOObjectRelease                       (
                                        io_object_t             object
@@ -78,6 +92,22 @@ _IORegistryEntryCreateCFProperties   (
                                        );
 #define IORegistryEntryCreateCFProperties _IORegistryEntryCreateCFProperties
 
+kern_return_t
+_IORegistryEntryCreateIterator         (
+                                       io_registry_entry_t     entry,
+                                       const io_name_t         plane,
+                                       IOOptionBits            options,
+                                       io_iterator_t           *iterator
+                                       );
+#define IORegistryEntryCreateIterator _IORegistryEntryCreateIterator
+
+kern_return_t
+_IORegistryEntryGetName                        (
+                                       io_registry_entry_t     entry,
+                                       io_name_t               name
+                                       );
+#define        IORegistryEntryGetName _IORegistryEntryGetName
+
 kern_return_t
 _IORegistryEntryGetParentEntry         (
                                        io_registry_entry_t     entry,
@@ -94,6 +124,16 @@ _IORegistryEntryGetPath                     (
                                        );
 #define IORegistryEntryGetPath _IORegistryEntryGetPath
 
+CFTypeRef
+_IORegistryEntrySearchCFProperty       (
+                                       io_registry_entry_t     entry,
+                                       const io_name_t         plane,
+                                       CFStringRef             key,
+                                       CFAllocatorRef          allocator,
+                                       IOOptionBits            options
+                                       );
+#define IORegistryEntrySearchCFProperty _IORegistryEntrySearchCFProperty
+
 kern_return_t
 _IOServiceGetMatchingServices          (
                                        mach_port_t             masterPort,
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@
  * 
 /*
  * Modification History
  *
+ * 4 March 2004                        Allan Nathanson (ajn@apple.com)
+ * - an alternate scheme to help facilitate access to the schema
+ *   definitions for cross-compilation to earlier releases AND
+ *   access to CFM applications.
+ *
  * 16 July 2003                        Allan Nathanson (ajn@apple.com)
  * - changes to facilitate cross-compilation to earlier releases
  *
@@ -54,7 +59,7 @@
 
 char copyright_string[] =
 "/*\n"
-" * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.\n"
+" * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.\n"
 " *\n"
 " * @APPLE_LICENSE_HEADER_START@\n"
 " * \n"
@@ -79,13 +84,16 @@ char copyright_string[] =
 
 typedef enum {
        COMMENT,
-       OBSOLETE,
-       REGULAR,
-       DEFINE,
-       FUTURE,
+       GROUP,
+       SC_10_1,
+       SC_10_2,
+       SC_10_1_10_3,   // deprecated in 10.4
+       SC_10_3,
+       SC_10_4,
        END
 } controlType;
 
+#define SC_SCHEMA_KV           "SC_SCHEMA_KV"
 #define SC_SCHEMA_DECLARATION  "SC_SCHEMA_DECLARATION"
 
 #define KEY_PREFIX             "kSC"
@@ -116,7 +124,7 @@ typedef enum {
 #define CFNUMBER_BOOL          "CFNumber (0 or 1)"
 #define CFSTRING               "CFString"
 
-#define ACSPENABLED            "ACSPEnabled"           // Apple Client Server Protocol
+#define ACSP                   "ACSP"                  // Apple Client Server Protocol
 #define ACTIVE                 "Active"
 #define ADDRESSES              "Addresses"
 #define AFTER                  "After"
@@ -127,14 +135,15 @@ typedef enum {
 #define ANYREGEX               "AnyRegex"
 #define APPLETALK              "AppleTalk"
 #define AUTH                   "Auth"
+#define AUTOCONFIG             "AutoConfig"
+#define AUTODISCOVERY          "AutoDiscovery"
 #define AUTOMATIC              "Automatic"
 #define BEFORE                 "Before"
 #define BINDINGMETHODS         "BindingMethods"
 #define BOOTP                  "BOOTP"
 #define BROADCAST              "Broadcast"
-#define BROADCASTADDRESSES     "BroadcastAddresses"
-#define BROADCASTSERVERTAG     "BroadcastServerTag"
 #define CALLWAITINGAUDIBLEALERT        "CallWaitingAudibleAlert"
+#define CAUSE                  "Cause"
 #define CCP                    "CCP"
 #define CHAP                   "CHAP"
 #define COMM                   "Comm"
@@ -150,9 +159,9 @@ typedef enum {
 #define CONSOLEUSER            "ConsoleUser"
 #define CURRENTSET             "CurrentSet"
 #define DATACOMPRESSION                "DataCompression"
-#define DEFAULTSERVERTAG       "DefaultServerTag"
+#define DEFAULT                        "Default"
 #define DEFAULTZONE            "DefaultZone"
-#define DESTADDRESSES          "DestAddresses"
+#define DEST                   "Dest"
 #define DETACHING              "Detaching"
 #define DEVICE                 "Device"
 #define DEVICENAME             "DeviceName"
@@ -161,6 +170,7 @@ typedef enum {
 #define DIALMODE               "DialMode"
 #define DIALONDEMAND           "DialOnDemand"
 #define DISCONNECTONANSWER     "DisconnectOnAnswer"
+#define DISCONNECTONFASTUSERSWITCH     "DisconnectOnFastUserSwitch"
 #define DISCONNECTONIDLE       "DisconnectOnIdle"
 #define DISCONNECTONIDLETIMER  "DisconnectOnIdleTimer"
 #define DISCONNECTONLOGOUT     "DisconnectOnLogout"
@@ -169,39 +179,32 @@ typedef enum {
 #define DISPLAYTERMINALWINDOW  "DisplayTerminalWindow"
 #define DNS                    "DNS"
 #define DOMAIN                         "Domain"
-#define DOMAINNAME             "DomainName"
-#define DOMAINSEPARATOR                "DomainSeparator"
+#define DOMAINS                        "Domains"
 #define EAP                    "EAP"
-#define ECHOENABLED            "EchoEnabled"
+#define ECHO                   "Echo"
 #define ECHOFAILURE            "EchoFailure"
 #define ECHOINTERVAL           "EchoInterval"
+#define ENABLE                 "Enable"
 #define ENABLED                        "Enabled"
 #define ENCODING               "Encoding"
 #define ENCRYPTION             "Encryption"
 #define ERRORCORRECTION                "ErrorCorrection"
 #define ETHERNET               "Ethernet"
 #define EXCEPTIONSLIST         "ExceptionsList"
+#define EXCLUDESIMPLEHOSTNAMES "ExcludeSimpleHostnames"
 #define FILE                   "File"
 #define FIREWIRE               "FireWire"
+#define FIRST                  "First"
 #define FLAGS                  "Flags"
-#define FTPENABLE              "FTPEnable"
-#define FTPPASSIVE             "FTPPassive"
-#define FTPPORT                        "FTPPort"
-#define FTPPROXY               "FTPProxy"
+#define FTP                    "FTP"
 #define GID                    "GID"
 #define GLOBAL                 "Global"
-#define GOPHERENABLE           "GopherEnable"
-#define GOPHERPORT             "GopherPort"
-#define GOPHERPROXY            "GopherProxy"
+#define GOPHER                 "Gopher"
 #define HARDWARE               "Hardware"
 #define HOLD                   "Hold"
 #define HOSTNAMES              "HostNames"
-#define HTTPENABLE             "HTTPEnable"
-#define HTTPPORT               "HTTPPort"
-#define HTTPPROXY              "HTTPProxy"
-#define HTTPSENABLE            "HTTPSEnable"
-#define HTTPSPORT              "HTTPSPort"
-#define HTTPSPROXY             "HTTPSProxy"
+#define HTTP                   "HTTP"
+#define HTTPS                  "HTTPS"
 #define IDLEREMINDER           "IdleReminder"
 #define IDLEREMINDERTIMER      "IdleReminderTimer"
 #define IGNOREDIALTONE         "IgnoreDialTone"
@@ -218,8 +221,7 @@ typedef enum {
 #define JOINMODE               "JoinMode"
 #define KEYCHAIN               "Keychain"
 #define L2TP                   "L2TP"
-#define LASTCAUSE              "LastCause"
-#define LASTUPDATED            "LastUpdated"
+#define LAST                   "Last"
 #define LCP                    "LCP"
 #define LINK                   "Link"
 #define LINKLOCAL              "LinkLocal"
@@ -227,9 +229,12 @@ typedef enum {
 #define LOGFILE                        "Logfile"
 #define MACADDRESS             "MACAddress"
 #define MANUAL                 "Manual"
+#define MATCH                  "Match"
 #define MEDIA                  "Media"
 #define OPTIONS                        "Options"
 #define MODEM                  "Modem"
+#define MPPE40                 "MPPE40"
+#define MPPE128                        "MPPE128"
 #define MRU                    "MRU"
 #define MSCHAP1                        "MSCHAP1"
 #define MSCHAP2                        "MSCHAP2"
@@ -240,23 +245,25 @@ typedef enum {
 #define NETWORKID              "NetworkID"
 #define NETWORKRANGE           "NetworkRange"
 #define NETWORKSERVICES                "NetworkServices"
-#define NIS                    "NIS"
 #define NODE                   "Node"
 #define NODEID                 "NodeID"
 #define NOTE                   "Note"
+#define ORDER                  "Order"
+#define ORDERS                 "Orders"
 #define OVERRIDEPRIMARY                "OverridePrimary"
 #define PAP                    "PAP"
+#define PASSIVE                        "Passive"
 #define PASSWORD               "Password"
+#define PEERDNS                        "PeerDNS"
 #define PLUGIN                 "Plugin"
 #define PLUGINS                        "Plugins"
-#define POWERENABLED           "PowerEnabled"
+#define POWER                  "Power"
+#define PORT                   "Port"
 #define PPP                    "PPP"
 #define PPPOE                  "PPPoE"
-#define PPPOVERRIDEPRIMARY     "PPPOverridePrimary"
 #define PPPSERIAL              "PPPSerial"
 #define PPTP                   "PPTP"
 #define PREFERRED              "Preferred"
-#define PREFERREDNETWORK       "PreferredNetwork"
 #define PREFIXLENGTH           "PrefixLength"
 #define PREFS                  "Prefs"
 #define PRIMARYINTERFACE       "PrimaryInterface"
@@ -264,13 +271,12 @@ typedef enum {
 #define PROMPT                 "Prompt"
 #define PROTOCOL               "Protocol"
 #define PROXIES                        "Proxies"
-#define PROXYAUTOCONFIGENABLE  "ProxyAutoConfigEnable"
-#define PROXYAUTOCONFIGURLSTRING       "ProxyAutoConfigURLString"
+#define PROXY                  "Proxy"
 #define PULSEDIAL              "PulseDial"
 #define RECEIVEACCM            "ReceiveACCM"
 #define RECENT                 "Recent"
 #define REDIALCOUNT            "RedialCount"
-#define REDIALENABLED          "RedialEnabled"
+#define REDIAL                 "Redial"
 #define REDIALINTERVAL         "RedialInterval"
 #define RELAY                  "Relay"
 #define REMINDER               "Reminder"
@@ -280,26 +286,20 @@ typedef enum {
 #define ROOTSEPARATOR          "RootSeparator"
 #define ROUTER                 "Router"
 #define ROUTERADVERTISEMENT    "RouterAdvertisement"
-#define RTSPENABLE             "RTSPEnable"
-#define RTSPPORT               "RTSPPort"
-#define RTSPPROXY              "RTSPProxy"
+#define RTSP                   "RTSP"
 #define SAVEPASSWORDS          "SavePasswords"
-#define SEARCHDOMAINS          "SearchDomains"
+#define SEARCH                 "Search"
 #define SEEDNETWORKRANGE       "SeedNetworkRange"
 #define SEEDROUTER             "SeedRouter"
 #define SEEDZONES              "SeedZones"
-#define SERVERADDRESSES                "ServerAddresses"
-#define SERVERTAGS             "ServerTags"
+#define SERVER                 "Server"
 #define SERVICE                        "Service"
 #define SERVICEIDS             "ServiceIDs"
-#define SERVICEORDER           "ServiceOrder"
 #define SESSIONTIMER           "SessionTimer"
 #define SETS                   "Sets"
 #define SETUP                  "Setup"
 #define        SHAREDSECRET            "SharedSecret"
-#define SOCKSENABLE            "SOCKSEnable"
-#define SOCKSPORT              "SOCKSPort"
-#define SOCKSPROXY             "SOCKSProxy"
+#define SOCKS                  "SOCKS"
 #define SORTLIST               "SortList"
 #define SPEAKER                        "Speaker"
 #define SPEED                  "Speed"
@@ -309,13 +309,19 @@ typedef enum {
 #define STRONGEST              "Strongest"
 #define SUBNETMASKS            "SubnetMasks"
 #define SUBTYPE                        "SubType"
+#define SUPPLEMENTAL           "Supplemental"
 #define SUPPORTSMODEMONHOLD    "SupportsModemOnHold"
 #define SYSTEM                 "System"
+#define TAG                    "Tag"
+#define TAGS                   "Tags"
 #define TERMINALSCRIPT         "TerminalScript"
+#define TIMEOUT                        "Timeout"
 #define TRANSMITACCM           "TransmitACCM"
 #define TRANSPORT              "Transport"
 #define TYPE                   "Type"
 #define UID                    "UID"
+#define UPDATED                        "Updated"
+#define URLSTRING              "URLString"
 #define USERDEFINEDNAME                "UserDefinedName"
 #define USE                    "Use"
 #define USERS                  "Users"
@@ -329,391 +335,434 @@ struct {
     const char *               value;
     const char *               type;
 } names[] = {
-    { COMMENT, "/*\n * Reserved Keys\n */", NULL, NULL },
-    { REGULAR, RESV, LINK,     "__LINK__", CFSTRING },
-    { REGULAR, RESV, INACTIVE, "__INACTIVE__", NULL },
+
+  { GROUP, NULL, "Reserved Keys", NULL, NULL },
+
+    { SC_10_1, RESV, LINK,     "__LINK__", CFSTRING },
+    { SC_10_1, RESV, INACTIVE, "__INACTIVE__", NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Generic Keys\n */", NULL },
-    { DEFINE , PROP, INTERFACENAME, NULL, CFSTRING },
-    { REGULAR, PROP, MACADDRESS, NULL, CFSTRING },
-    { REGULAR, PROP, USERDEFINEDNAME, NULL, CFSTRING },
-    { DEFINE , PROP, VERSION, NULL, CFSTRING },
+  { GROUP, NULL, "Generic Keys", NULL, NULL },
+
+    { SC_10_1, PROP, INTERFACENAME, NULL, CFSTRING },
+    { SC_10_1, PROP, MACADDRESS, NULL, CFSTRING },
+    { SC_10_1, PROP, USERDEFINEDNAME, NULL, CFSTRING },
+    { SC_10_1, PROP, VERSION, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Preference Keys\n */", NULL },
-    { REGULAR, PREF, CURRENTSET, NULL, CFSTRING },
-    { REGULAR, PREF, NETWORKSERVICES, NULL, CFDICTIONARY },
-    { REGULAR, PREF, SETS, NULL, CFDICTIONARY },
-    { REGULAR, PREF, SYSTEM, NULL, CFDICTIONARY },
+  { GROUP, PREF, "Preference Keys", NULL, NULL },
+
+    { SC_10_1, PREF, CURRENTSET, NULL, CFSTRING },
+    { SC_10_1, PREF, NETWORKSERVICES, NULL, CFDICTIONARY },
+    { SC_10_1, PREF, SETS, NULL, CFDICTIONARY },
+    { SC_10_1, PREF, SYSTEM, NULL, CFDICTIONARY },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Component Keys\n */", NULL },
-    { REGULAR, COMP, NETWORK, NULL, NULL },
-    { REGULAR, COMP, SERVICE, NULL, NULL },
-    { REGULAR, COMP, GLOBAL, NULL, NULL },
-    { DEFINE , COMP, HOSTNAMES, NULL, NULL },
-    { REGULAR, COMP, INTERFACE, NULL, NULL },
-    { REGULAR, COMP, SYSTEM, NULL, NULL },
-    { REGULAR, COMP, USERS, NULL, NULL },
+  { GROUP, COMP, "Component Keys", NULL, NULL },
+
+    { SC_10_1, COMP, NETWORK, NULL, NULL },
+    { SC_10_1, COMP, SERVICE, NULL, NULL },
+    { SC_10_1, COMP, GLOBAL, NULL, NULL },
+    { SC_10_2, COMP, HOSTNAMES, NULL, NULL },
+    { SC_10_1, COMP, INTERFACE, NULL, NULL },
+    { SC_10_1, COMP, SYSTEM, NULL, NULL },
+    { SC_10_1, COMP, USERS, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Regex key which matches any component\n */", NULL },
-    { REGULAR, COMP, ANYREGEX, "[^/]+", NULL },
+    { COMMENT, "--- Regex pattern which matches any component ---", NULL },
+    { SC_10_1, COMP, ANYREGEX, "[^/]+", NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Network Entity Keys\n */", NULL },
-    { REGULAR, NETENT, AIRPORT, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, APPLETALK, NULL, CFDICTIONARY },
-    { DEFINE , NETENT, DHCP, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, DNS, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, ETHERNET, NULL, CFDICTIONARY },
-    { DEFINE , NETENT, FIREWIRE, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, INTERFACE, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, IPV4, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, IPV6, NULL, CFDICTIONARY },
-    { DEFINE , NETENT, L2TP, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, LINK, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, MODEM, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, NETINFO, NULL, CFDICTIONARY },
-    { FUTURE , NETENT, NIS, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, PPP, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, PPPOE, NULL, CFDICTIONARY },
-    { DEFINE , NETENT, PPPSERIAL, NULL, CFDICTIONARY },
-    { DEFINE , NETENT, PPTP, NULL, CFDICTIONARY },
-    { REGULAR, NETENT, PROXIES, NULL, CFDICTIONARY },
-    { DEFINE , NETENT, STF, NULL, CFDICTIONARY },
+  { GROUP, NETENT, "Network Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETENT, AIRPORT, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, APPLETALK, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, DHCP, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, DNS, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, ETHERNET, NULL, CFDICTIONARY },
+    { SC_10_3, NETENT, FIREWIRE, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, INTERFACE, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, IPV4, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, IPV6, NULL, CFDICTIONARY },
+    { SC_10_3, NETENT, L2TP, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, LINK, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, MODEM, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, NETINFO, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, PPP, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, PPPOE, NULL, CFDICTIONARY },
+    { SC_10_3, NETENT, PPPSERIAL, NULL, CFDICTIONARY },
+    { SC_10_3, NETENT, PPTP, NULL, CFDICTIONARY },
+    { SC_10_1, NETENT, PROXIES, NULL, CFDICTIONARY },
+    { SC_10_3, NETENT, STF, NULL, CFDICTIONARY },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK " Properties\n */", NULL },
-    { DEFINE , NETPROP, OVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP, SERVICEORDER, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP, PPPOVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
+  { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK " Properties", NULL, NULL },
+
+    { SC_10_2, NETPROP, OVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP, SERVICE ORDER, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP, PPP OVERRIDEPRIMARY, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK INTERFACE " Properties\n */", NULL },
-    { DEFINE , NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
+  { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK INTERFACE " Properties", NULL, NULL },
+
+    { SC_10_2, NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX COMP NETWORK HOSTNAMES " Properties\n */", NULL },
-    { DEFINE , NETPROP, LOCALHOSTNAME, NULL, CFSTRING },
+  { GROUP, NETPROP AIRPORT, KEY_PREFIX COMP NETWORK HOSTNAMES " Properties", NULL, NULL },
+
+    { SC_10_2, NETPROP, LOCALHOSTNAME, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
-    { DEFINE , NETPROP AIRPORT, ALLOWNETCREATION, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFDATA },
-    { REGULAR, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
-    { DEFINE , NETPROP AIRPORT, JOINMODE, NULL, CFSTRING },
-    { REGULAR, NETPROP AIRPORT, POWERENABLED, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP AIRPORT, PREFERREDNETWORK, NULL, CFSTRING },
-    { DEFINE , NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL },
+  { GROUP, NETPROP AIRPORT, KEY_PREFIX NETENT AIRPORT " (Hardware) Entity Keys", NULL, NULL },
+
+    { SC_10_2, NETPROP AIRPORT, ALLOWNETCREATION, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP AIRPORT, AUTH PASSWORD, NULL, CFDATA },
+    { SC_10_1, NETPROP AIRPORT, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+    { SC_10_2, NETPROP AIRPORT, JOINMODE, NULL, CFSTRING },
+    { SC_10_1, NETPROP AIRPORT, POWER ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP AIRPORT, PREFERRED NETWORK, NULL, CFSTRING },
+    { SC_10_2, NETPROP AIRPORT, SAVEPASSWORDS, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP AIRPORT JOINMODE " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL AIRPORT JOINMODE, AUTOMATIC, NULL, NULL },
-    { DEFINE , NETVAL AIRPORT JOINMODE, PREFERRED, NULL, NULL },
-    { DEFINE , NETVAL AIRPORT JOINMODE, RECENT, NULL, NULL },
-    { DEFINE , NETVAL AIRPORT JOINMODE, STRONGEST, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP AIRPORT JOINMODE " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL AIRPORT JOINMODE, AUTOMATIC, NULL, NULL },
+    { SC_10_2, NETVAL AIRPORT JOINMODE, PREFERRED, NULL, NULL },
+    { SC_10_2, NETVAL AIRPORT JOINMODE, RECENT, NULL, NULL },
+    { SC_10_2, NETVAL AIRPORT JOINMODE, STRONGEST, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP AIRPORT PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL AIRPORT AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT APPLETALK " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP APPLETALK, COMPUTERNAME, NULL, CFSTRING },
-    { REGULAR, NETPROP APPLETALK, COMPUTERNAME ENCODING, NULL, CFNUMBER },
-    { REGULAR, NETPROP APPLETALK, CONFIGMETHOD, NULL, CFSTRING },
-    { REGULAR, NETPROP APPLETALK, DEFAULTZONE, NULL, CFSTRING },
-    { REGULAR, NETPROP APPLETALK, NETWORKID, NULL, CFNUMBER },
-    { REGULAR, NETPROP APPLETALK, NETWORKRANGE, NULL, CFARRAY_CFNUMBER },
-    { REGULAR, NETPROP APPLETALK, NODEID, NULL, CFNUMBER },
-    { REGULAR, NETPROP APPLETALK, SEEDNETWORKRANGE, NULL, CFARRAY_CFNUMBER },
-    { REGULAR, NETPROP APPLETALK, SEEDZONES, NULL, CFARRAY_CFSTRING },
+  { GROUP, NETPROP APPLETALK, KEY_PREFIX NETENT APPLETALK " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP APPLETALK, COMPUTERNAME, NULL, CFSTRING },
+    { SC_10_1, NETPROP APPLETALK, COMPUTERNAME ENCODING, NULL, CFNUMBER },
+    { SC_10_1, NETPROP APPLETALK, CONFIGMETHOD, NULL, CFSTRING },
+    { SC_10_1, NETPROP APPLETALK, DEFAULTZONE, NULL, CFSTRING },
+    { SC_10_1, NETPROP APPLETALK, NETWORKID, NULL, CFNUMBER },
+    { SC_10_2, NETPROP APPLETALK, NETWORKRANGE, NULL, CFARRAY_CFNUMBER },
+    { SC_10_1, NETPROP APPLETALK, NODEID, NULL, CFNUMBER },
+    { SC_10_1, NETPROP APPLETALK, SEEDNETWORKRANGE, NULL, CFARRAY_CFNUMBER },
+    { SC_10_1, NETPROP APPLETALK, SEEDZONES, NULL, CFARRAY_CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP APPLETALK CONFIGMETHOD " values */", NULL, NULL, NULL },
-    { REGULAR, NETVAL APPLETALK CONFIGMETHOD, NODE, NULL, NULL },
-    { REGULAR, NETVAL APPLETALK CONFIGMETHOD, ROUTER, NULL, NULL },
-    { REGULAR, NETVAL APPLETALK CONFIGMETHOD, SEEDROUTER, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP APPLETALK CONFIGMETHOD " values ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL APPLETALK CONFIGMETHOD, NODE, NULL, NULL },
+    { SC_10_1, NETVAL APPLETALK CONFIGMETHOD, ROUTER, NULL, NULL },
+    { SC_10_1, NETVAL APPLETALK CONFIGMETHOD, SEEDROUTER, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT DNS " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP DNS, DOMAINNAME, NULL, CFSTRING },
-    { REGULAR, NETPROP DNS, SEARCHDOMAINS, NULL, CFARRAY_CFSTRING},
-    { REGULAR, NETPROP DNS, SERVERADDRESSES, NULL, CFARRAY_CFSTRING },
-    { DEFINE , NETPROP DNS, SORTLIST, NULL, CFARRAY_CFSTRING },
+  { GROUP, NETPROP DNS, KEY_PREFIX NETENT DNS " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP DNS, DOMAIN NAME, NULL, CFSTRING },
+    { SC_10_4, NETPROP DNS, OPTIONS, NULL, CFSTRING },
+    { SC_10_1, NETPROP DNS, SEARCH DOMAINS, NULL, CFARRAY_CFSTRING},
+    { SC_10_4, NETPROP DNS, SEARCH ORDER, NULL, CFNUMBER},
+    { SC_10_1, NETPROP DNS, SERVER ADDRESSES, NULL, CFARRAY_CFSTRING },
+    { SC_10_4, NETPROP DNS, SERVER PORT, NULL, CFNUMBER },
+    { SC_10_4, NETPROP DNS, SERVER TIMEOUT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP DNS, SORTLIST, NULL, CFARRAY_CFSTRING },
+    { SC_10_4, NETPROP DNS, SUPPLEMENTAL MATCH DOMAINS, NULL, CFARRAY_CFSTRING},
+    { SC_10_4, NETPROP DNS, SUPPLEMENTAL MATCH ORDERS, NULL, CFARRAY_CFNUMBER},
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT ETHERNET " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
-    { DEFINE , NETPROP ETHERNET, MEDIA SUBTYPE, NULL, CFSTRING },
-    { DEFINE , NETPROP ETHERNET, MEDIA OPTIONS, NULL, CFARRAY_CFSTRING },
-    { DEFINE , NETPROP ETHERNET, MTU, NULL, CFNUMBER },
+  { GROUP, NETPROP ETHERNET, KEY_PREFIX NETENT ETHERNET " (Hardware) Entity Keys", NULL, NULL },
+
+    { SC_10_2, NETPROP ETHERNET, MEDIA SUBTYPE, NULL, CFSTRING },
+    { SC_10_2, NETPROP ETHERNET, MEDIA OPTIONS, NULL, CFARRAY_CFSTRING },
+    { SC_10_2, NETPROP ETHERNET, MTU, NULL, CFNUMBER },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT FIREWIRE " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
-    { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+  { GROUP, NETPROP FIREWIRE, KEY_PREFIX NETENT FIREWIRE " (Hardware) Entity Keys", NULL, NULL },
+
+    { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT INTERFACE " Entity Keys\n */", NULL },
-    { REGULAR, NETPROP INTERFACE, DEVICENAME, NULL, CFSTRING },
-    { REGULAR, NETPROP INTERFACE, HARDWARE, NULL, CFSTRING },
-    { REGULAR, NETPROP INTERFACE, TYPE, NULL, CFSTRING },
-    { REGULAR, NETPROP INTERFACE, SUBTYPE, NULL, CFSTRING },
-    { DEFINE , NETPROP INTERFACE, SUPPORTSMODEMONHOLD, NULL, CFNUMBER_BOOL },
+  { GROUP, NETPROP INTERFACE, KEY_PREFIX NETENT INTERFACE " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP INTERFACE, DEVICENAME, NULL, CFSTRING },
+    { SC_10_1, NETPROP INTERFACE, HARDWARE, NULL, CFSTRING },
+    { SC_10_1, NETPROP INTERFACE, TYPE, NULL, CFSTRING },
+    { SC_10_1, NETPROP INTERFACE, SUBTYPE, NULL, CFSTRING },
+    { SC_10_2, NETPROP INTERFACE, SUPPORTSMODEMONHOLD, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP INTERFACE TYPE " values */", NULL, NULL, NULL },
-    { REGULAR, NETVAL INTERFACE TYPE, ETHERNET, NULL, NULL },
-    { DEFINE , NETVAL INTERFACE TYPE, FIREWIRE, NULL, NULL },
-    { REGULAR, NETVAL INTERFACE TYPE, PPP, NULL, NULL },
-    { DEFINE , NETVAL INTERFACE TYPE, STF, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP INTERFACE TYPE " values ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL INTERFACE TYPE, ETHERNET, NULL, NULL },
+    { SC_10_3, NETVAL INTERFACE TYPE, FIREWIRE, NULL, NULL },
+    { SC_10_1, NETVAL INTERFACE TYPE, PPP, NULL, NULL },
+    { SC_10_3, NETVAL INTERFACE TYPE, STF, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP SERVICE SUBTYPE " values (for " PPP ") */", NULL, NULL, NULL },
-    { REGULAR, NETVAL INTERFACE SUBTYPE, PPPOE, NULL, NULL },
-    { REGULAR, NETVAL INTERFACE SUBTYPE, PPPSERIAL, NULL, NULL },
-    { DEFINE , NETVAL INTERFACE SUBTYPE, PPTP, NULL, NULL },
-    { DEFINE , NETVAL INTERFACE SUBTYPE, L2TP, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP SERVICE SUBTYPE " values (for " PPP ") ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL INTERFACE SUBTYPE, PPPOE, NULL, NULL },
+    { SC_10_1, NETVAL INTERFACE SUBTYPE, PPPSERIAL, NULL, NULL },
+    { SC_10_2, NETVAL INTERFACE SUBTYPE, PPTP, NULL, NULL },
+    { SC_10_3, NETVAL INTERFACE SUBTYPE, L2TP, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV4 " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP IPV4, ADDRESSES, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP IPV4, CONFIGMETHOD, NULL, CFSTRING },
-    { REGULAR, NETPROP IPV4, DHCPCLIENTID, NULL, CFSTRING },
-    { REGULAR, NETPROP IPV4, ROUTER, NULL, CFSTRING },
-    { REGULAR, NETPROP IPV4, SUBNETMASKS, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP IPV4, DESTADDRESSES, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP IPV4, BROADCASTADDRESSES, NULL, CFARRAY_CFSTRING },
+  { GROUP, NETPROP IPV4, KEY_PREFIX NETENT IPV4 " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP IPV4, ADDRESSES, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP IPV4, CONFIGMETHOD, NULL, CFSTRING },
+    { SC_10_1, NETPROP IPV4, DHCPCLIENTID, NULL, CFSTRING },
+    { SC_10_1, NETPROP IPV4, ROUTER, NULL, CFSTRING },
+    { SC_10_1, NETPROP IPV4, SUBNETMASKS, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP IPV4, DEST ADDRESSES, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP IPV4, BROADCAST ADDRESSES, NULL, CFARRAY_CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP IPV4 CONFIGMETHOD " values */", NULL, NULL, NULL },
-    { REGULAR, NETVAL IPV4 CONFIGMETHOD, BOOTP, NULL, NULL },
-    { REGULAR, NETVAL IPV4 CONFIGMETHOD, DHCP, NULL, NULL },
-    { REGULAR, NETVAL IPV4 CONFIGMETHOD, INFORM, NULL, NULL },
-    { REGULAR, NETVAL IPV4 CONFIGMETHOD, LINKLOCAL, NULL, NULL },
-    { REGULAR, NETVAL IPV4 CONFIGMETHOD, MANUAL, NULL, NULL },
-    { REGULAR, NETVAL IPV4 CONFIGMETHOD, PPP, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP IPV4 CONFIGMETHOD " values ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL IPV4 CONFIGMETHOD, BOOTP, NULL, NULL },
+    { SC_10_1, NETVAL IPV4 CONFIGMETHOD, DHCP, NULL, NULL },
+    { SC_10_1, NETVAL IPV4 CONFIGMETHOD, INFORM, NULL, NULL },
+    { SC_10_2, NETVAL IPV4 CONFIGMETHOD, LINKLOCAL, NULL, NULL },
+    { SC_10_1, NETVAL IPV4 CONFIGMETHOD, MANUAL, NULL, NULL },
+    { SC_10_1, NETVAL IPV4 CONFIGMETHOD, PPP, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT IPV6 " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP IPV6, ADDRESSES, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP IPV6, CONFIGMETHOD, NULL, CFSTRING },
-    { DEFINE , NETPROP IPV6, DESTADDRESSES, NULL, CFARRAY_CFSTRING },
-    { DEFINE , NETPROP IPV6, FLAGS, NULL, CFNUMBER },
-    { DEFINE , NETPROP IPV6, PREFIXLENGTH, NULL, CFARRAY_CFNUMBER },
-    { DEFINE , NETPROP IPV6, ROUTER, NULL, CFSTRING },
+  { GROUP, NETPROP IPV6, KEY_PREFIX NETENT IPV6 " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP IPV6, ADDRESSES, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP IPV6, CONFIGMETHOD, NULL, CFSTRING },
+    { SC_10_3, NETPROP IPV6, DEST ADDRESSES, NULL, CFARRAY_CFSTRING },
+    { SC_10_3, NETPROP IPV6, FLAGS, NULL, CFNUMBER },
+    { SC_10_3, NETPROP IPV6, PREFIXLENGTH, NULL, CFARRAY_CFNUMBER },
+    { SC_10_3, NETPROP IPV6, ROUTER, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP IPV6 CONFIGMETHOD " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL IPV6 CONFIGMETHOD, AUTOMATIC, NULL, NULL },
-    { DEFINE , NETVAL IPV6 CONFIGMETHOD, MANUAL, NULL, NULL },
-    { DEFINE , NETVAL IPV6 CONFIGMETHOD, ROUTERADVERTISEMENT, NULL, NULL },
-    { DEFINE , NETVAL IPV6 CONFIGMETHOD, STF, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP IPV6 CONFIGMETHOD " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL IPV6 CONFIGMETHOD, AUTOMATIC, NULL, NULL },
+    { SC_10_3, NETVAL IPV6 CONFIGMETHOD, MANUAL, NULL, NULL },
+    { SC_10_3, NETVAL IPV6 CONFIGMETHOD, ROUTERADVERTISEMENT, NULL, NULL },
+    { SC_10_3, NETVAL IPV6 CONFIGMETHOD, STF, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT STF " Entity Keys\n */", NULL, NULL, NULL },
-    { DEFINE , NETPROP STF, RELAY, NULL, CFSTRING },
+  { GROUP, NETPROP STF, KEY_PREFIX NETENT STF " Entity Keys", NULL, NULL },
+
+    { SC_10_3, NETPROP STF, RELAY, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT LINK " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP LINK, ACTIVE, NULL, CFBOOLEAN },
-    { DEFINE , NETPROP LINK, DETACHING, NULL, CFBOOLEAN },
+  { GROUP, NETPROP LINK, KEY_PREFIX NETENT LINK " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP LINK, ACTIVE, NULL, CFBOOLEAN },
+    { SC_10_2, NETPROP LINK, DETACHING, NULL, CFBOOLEAN },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT MODEM " (Hardware) Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP MODEM, CONNECTIONSCRIPT, NULL, CFSTRING },
-    { DEFINE , NETPROP MODEM, CONNECTSPEED, NULL, CFNUMBER },
-    { DEFINE , NETPROP MODEM, DATACOMPRESSION, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP MODEM, DIALMODE, NULL, CFSTRING },
-    { DEFINE , NETPROP MODEM, ERRORCORRECTION, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP MODEM, HOLD CALLWAITINGAUDIBLEALERT, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP MODEM, HOLD DISCONNECTONANSWER, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP MODEM, HOLD ENABLED, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP MODEM, HOLD REMINDER, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP MODEM, HOLD REMINDERTIME, NULL, CFNUMBER },
-    { DEFINE , NETPROP MODEM, NOTE, NULL, CFSTRING },
-    { REGULAR, NETPROP MODEM, PULSEDIAL, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP MODEM, SPEAKER, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP MODEM, SPEED, NULL, CFNUMBER },
+  { GROUP, NETPROP MODEM, KEY_PREFIX NETENT MODEM " (Hardware) Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP MODEM, CONNECTIONSCRIPT, NULL, CFSTRING },
+    { SC_10_2, NETPROP MODEM, CONNECTSPEED, NULL, CFNUMBER },
+    { SC_10_1, NETPROP MODEM, DATACOMPRESSION, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP MODEM, DIALMODE, NULL, CFSTRING },
+    { SC_10_1, NETPROP MODEM, ERRORCORRECTION, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP MODEM, HOLD CALLWAITINGAUDIBLEALERT, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP MODEM, HOLD DISCONNECTONANSWER, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP MODEM, HOLD ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP MODEM, HOLD REMINDER, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP MODEM, HOLD REMINDERTIME, NULL, CFNUMBER },
+    { SC_10_2, NETPROP MODEM, NOTE, NULL, CFSTRING },
+    { SC_10_1, NETPROP MODEM, PULSEDIAL, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP MODEM, SPEAKER, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP MODEM, SPEED, NULL, CFNUMBER },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP MODEM DIALMODE " values */", NULL, NULL, NULL },
-    { REGULAR, NETVAL MODEM DIALMODE, IGNOREDIALTONE, NULL, NULL },
-    { REGULAR, NETVAL MODEM DIALMODE, MANUAL, NULL, NULL },
-    { REGULAR, NETVAL MODEM DIALMODE, WAITFORDIALTONE, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP MODEM DIALMODE " values ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL MODEM DIALMODE, IGNOREDIALTONE, NULL, NULL },
+    { SC_10_1, NETVAL MODEM DIALMODE, MANUAL, NULL, NULL },
+    { SC_10_1, NETVAL MODEM DIALMODE, WAITFORDIALTONE, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT NETINFO " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP NETINFO, BINDINGMETHODS, NULL, CFSTRING },
-    { REGULAR, NETPROP NETINFO, SERVERADDRESSES, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP NETINFO, SERVERTAGS, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP NETINFO, BROADCASTSERVERTAG, NULL, CFSTRING },
-    { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP NETINFO BINDINGMETHODS " values */", NULL, NULL, NULL },
-    { REGULAR, NETVAL NETINFO BINDINGMETHODS, BROADCAST, NULL, NULL },
-    { REGULAR, NETVAL NETINFO BINDINGMETHODS, DHCP, NULL, NULL },
-    { REGULAR, NETVAL NETINFO BINDINGMETHODS, MANUAL, NULL, NULL },
+  { GROUP, NETPROP NETINFO, KEY_PREFIX NETENT NETINFO " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP NETINFO, BINDINGMETHODS, NULL, CFSTRING },
+    { SC_10_1, NETPROP NETINFO, SERVER ADDRESSES, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP NETINFO, SERVER TAGS, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP NETINFO, BROADCAST SERVER TAG, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP NETINFO BROADCASTSERVERTAG " default value */", NULL, NULL, NULL },
-    { REGULAR, NETVAL NETINFO, DEFAULTSERVERTAG, "network", NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP NETINFO BINDINGMETHODS " values ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL NETINFO BINDINGMETHODS, BROADCAST, NULL, NULL },
+    { SC_10_1, NETVAL NETINFO BINDINGMETHODS, DHCP, NULL, NULL },
+    { SC_10_1, NETVAL NETINFO BINDINGMETHODS, MANUAL, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
-
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT NIS " Entity Keys\n */", NULL, NULL, NULL },
-    { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP NETINFO BROADCAST SERVER TAG " default value ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL NETINFO, DEFAULT SERVER TAG, "network", NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT PPP " Entity Keys\n */", NULL, NULL, NULL },
-    { DEFINE , NETPROP PPP, ACSPENABLED, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP PPP, CONNECTTIME, NULL, CFNUMBER },
-    { DEFINE , NETPROP PPP, DEVICE LASTCAUSE, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, DIALONDEMAND, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, DISCONNECTONIDLE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP PPP, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP PPP, DISCONNECTTIME, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP PPP, LASTCAUSE, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, LOGFILE, NULL, CFSTRING },
-    { DEFINE , NETPROP PPP, PLUGINS, NULL, CFARRAY_CFSTRING },
-    { DEFINE , NETPROP PPP, RETRYCONNECTTIME, NULL, CFNUMBER },
-    { DEFINE , NETPROP PPP, SESSIONTIMER, NULL, CFNUMBER },
-    { DEFINE , NETPROP PPP, STATUS, NULL, CFNUMBER },
-    { DEFINE , NETPROP PPP, USE SESSIONTIMER, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, VERBOSELOGGING, NULL, CFNUMBER_BOOL },
+  { GROUP, NETPROP PPP, KEY_PREFIX NETENT PPP " Entity Keys", NULL, NULL },
+
+    { SC_10_3, NETPROP PPP, ACSP ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP PPP, CONNECTTIME, NULL, CFNUMBER },
+    { SC_10_2, NETPROP PPP, DEVICE LAST CAUSE, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, DIALONDEMAND, NULL, CFNUMBER_BOOL },
+    { SC_10_4, NETPROP PPP, DISCONNECTONFASTUSERSWITCH, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, DISCONNECTONIDLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, DISCONNECTONIDLETIMER, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, DISCONNECTONLOGOUT, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP PPP, DISCONNECTONSLEEP, NULL, CFNUMBER_BOOL },
+    { SC_10_3, NETPROP PPP, DISCONNECTTIME, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, IDLEREMINDERTIMER, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, IDLEREMINDER, NULL, CFNUMBER_BOOL },
+    { SC_10_2, NETPROP PPP, LAST CAUSE, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, LOGFILE, NULL, CFSTRING },
+    { SC_10_2, NETPROP PPP, PLUGINS, NULL, CFARRAY_CFSTRING },
+    { SC_10_3, NETPROP PPP, RETRYCONNECTTIME, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, SESSIONTIMER, NULL, CFNUMBER },
+    { SC_10_2, NETPROP PPP, STATUS, NULL, CFNUMBER },
+    { SC_10_2, NETPROP PPP, USE SESSIONTIMER, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, VERBOSELOGGING, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/* " AUTH ": */", NULL, NULL, NULL },
-    { DEFINE , NETPROP PPP, AUTH EAP PLUGINS, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP PPP, AUTH NAME, NULL, CFSTRING },
-    { REGULAR, NETPROP PPP, AUTH PASSWORD, NULL, CFSTRING },
-    { REGULAR, NETPROP PPP, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
-    { DEFINE , NETPROP PPP, AUTH PROMPT, NULL, CFSTRING },
-    { REGULAR, NETPROP PPP, AUTH PROTOCOL, NULL, CFARRAY_CFSTRING },
+    { COMMENT, "--- " AUTH ": ---", NULL, NULL, NULL },
+    { SC_10_3, NETPROP PPP, AUTH EAP PLUGINS, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, NETPROP PPP, AUTH NAME, NULL, CFSTRING },
+    { SC_10_1, NETPROP PPP, AUTH PASSWORD, NULL, CFSTRING },
+    { SC_10_1, NETPROP PPP, AUTH PASSWORD ENCRYPTION, NULL, CFSTRING },
+    { SC_10_3, NETPROP PPP, AUTH PROMPT, NULL, CFSTRING },
+    { SC_10_1, NETPROP PPP, AUTH PROTOCOL, NULL, CFARRAY_CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PASSWORD ENCRYPTION " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL PPP AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP PPP AUTH PASSWORD ENCRYPTION " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL PPP AUTH PASSWORD ENCRYPTION, KEYCHAIN, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROMPT " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL PPP AUTH PROMPT, BEFORE, NULL, CFSTRING },
-    { DEFINE , NETVAL PPP AUTH PROMPT, AFTER, NULL, CFSTRING },
+    { COMMENT, "--- " KEY_PREFIX NETPROP PPP AUTH PROMPT " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL PPP AUTH PROMPT, BEFORE, NULL, CFSTRING },
+    { SC_10_3, NETVAL PPP AUTH PROMPT, AFTER, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP PPP AUTH PROTOCOL " values */", NULL, NULL, NULL },
-    { REGULAR, NETVAL PPP AUTH PROTOCOL, CHAP, NULL, CFSTRING },
-    { DEFINE , NETVAL PPP AUTH PROTOCOL, EAP, NULL, CFSTRING },
-    { DEFINE , NETVAL PPP AUTH PROTOCOL, MSCHAP1, NULL, CFSTRING },
-    { DEFINE , NETVAL PPP AUTH PROTOCOL, MSCHAP2, NULL, CFSTRING },
-    { REGULAR, NETVAL PPP AUTH PROTOCOL, PAP, NULL, CFSTRING },
-
-    { COMMENT, "\n/* " COMM ": */", NULL, NULL, NULL },
-    { REGULAR, NETPROP PPP, COMM ALTERNATEREMOTEADDRESS, NULL, CFSTRING },
-    { REGULAR, NETPROP PPP, COMM CONNECTDELAY, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, COMM DISPLAYTERMINALWINDOW, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, COMM REDIALCOUNT, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, COMM REDIALENABLED, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, COMM REDIALINTERVAL, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, COMM REMOTEADDRESS, NULL, CFSTRING },
-    { REGULAR, NETPROP PPP, COMM TERMINALSCRIPT, NULL, CFSTRING },
-    { DEFINE , NETPROP PPP, COMM USE TERMINALSCRIPT, NULL, CFNUMBER_BOOL },
-
-    { COMMENT, "\n/* " CCP ": */", NULL, NULL, NULL },
-    { DEFINE , NETPROP PPP, CCP ENABLED, NULL, CFNUMBER_BOOL },
-
-    { COMMENT, "\n/* " IPCP ": */", NULL, NULL, NULL },
-    { REGULAR, NETPROP PPP, IPCP COMPRESSIONVJ, NULL, CFNUMBER_BOOL },
-
-    { COMMENT, "\n/* " LCP ": */", NULL, NULL, NULL },
-    { REGULAR, NETPROP PPP, LCP ECHOENABLED, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, LCP ECHOFAILURE, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, LCP ECHOINTERVAL, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, LCP COMPRESSIONACFIELD, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, LCP COMPRESSIONPFIELD, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PPP, LCP MRU, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, LCP MTU, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, LCP RECEIVEACCM, NULL, CFNUMBER },
-    { REGULAR, NETPROP PPP, LCP TRANSMITACCM, NULL, CFNUMBER },
+    { COMMENT, "--- " KEY_PREFIX NETPROP PPP AUTH PROTOCOL " values ---", NULL, NULL, NULL },
+    { SC_10_1, NETVAL PPP AUTH PROTOCOL, CHAP, NULL, CFSTRING },
+    { SC_10_3, NETVAL PPP AUTH PROTOCOL, EAP, NULL, CFSTRING },
+    { SC_10_3, NETVAL PPP AUTH PROTOCOL, MSCHAP1, NULL, CFSTRING },
+    { SC_10_3, NETVAL PPP AUTH PROTOCOL, MSCHAP2, NULL, CFSTRING },
+    { SC_10_1, NETVAL PPP AUTH PROTOCOL, PAP, NULL, CFSTRING },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT PPPOE " Entity Keys\n */", NULL, NULL, NULL },
-    { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+    { COMMENT, "--- " COMM ": ---", NULL, NULL, NULL },
+    { SC_10_1, NETPROP PPP, COMM ALTERNATEREMOTEADDRESS, NULL, CFSTRING },
+    { SC_10_1, NETPROP PPP, COMM CONNECTDELAY, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, COMM DISPLAYTERMINALWINDOW, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, COMM REDIALCOUNT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, COMM REDIAL ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, COMM REDIALINTERVAL, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, COMM REMOTEADDRESS, NULL, CFSTRING },
+    { SC_10_1, NETPROP PPP, COMM TERMINALSCRIPT, NULL, CFSTRING },
+    { SC_10_2, NETPROP PPP, COMM USE TERMINALSCRIPT, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT PPPSERIAL " Entity Keys\n */", NULL, NULL, NULL },
-    { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+    { COMMENT, "--- " CCP ": ---", NULL, NULL, NULL },
+    { SC_10_2, NETPROP PPP, CCP ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_4, NETPROP PPP, CCP MPPE40 ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_4, NETPROP PPP, CCP MPPE128 ENABLED, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT PPTP " Entity Keys\n */", NULL, NULL, NULL },
-    { COMMENT, "/* RESERVED FOR FUTURE USE */", NULL, NULL, NULL },
+    { COMMENT, "--- " IPCP ": ---", NULL, NULL, NULL },
+    { SC_10_1, NETPROP PPP, IPCP COMPRESSIONVJ, NULL, CFNUMBER_BOOL },
+    { SC_10_4, NETPROP PPP, IPCP USE PEERDNS, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT L2TP " Entity Keys\n */", NULL, NULL, NULL },
-    { DEFINE , NETPROP L2TP, IPSEC SHAREDSECRET, NULL, CFSTRING },
-    { DEFINE , NETPROP L2TP, IPSEC SHAREDSECRET ENCRYPTION, NULL, CFSTRING },
-    { DEFINE , NETPROP L2TP, TRANSPORT, NULL, CFSTRING },
+    { COMMENT, "--- " LCP ": ---", NULL, NULL, NULL },
+    { SC_10_1, NETPROP PPP, LCP ECHO ENABLED, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, LCP ECHOFAILURE, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, LCP ECHOINTERVAL, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, LCP COMPRESSIONACFIELD, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, LCP COMPRESSIONPFIELD, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PPP, LCP MRU, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, LCP MTU, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, LCP RECEIVEACCM, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PPP, LCP TRANSMITACCM, NULL, CFNUMBER },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP L2TP IPSEC SHAREDSECRET ENCRYPTION " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL L2TP IPSEC SHAREDSECRET ENCRYPTION, KEYCHAIN, NULL, NULL },
+
+  { GROUP, NETPROP PPPOE, KEY_PREFIX NETENT PPPOE " Entity Keys", NULL, NULL },
+
+    { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
-    { COMMENT, "/* " KEY_PREFIX NETPROP L2TP TRANSPORT " values */", NULL, NULL, NULL },
-    { DEFINE , NETVAL L2TP TRANSPORT, IP, NULL, NULL },
-    { DEFINE , NETVAL L2TP TRANSPORT, IPSEC, NULL, NULL },
+
+  { GROUP, NETPROP PPPSERIAL, KEY_PREFIX NETENT PPPSERIAL " Entity Keys", NULL, NULL },
+
+    { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX NETENT PROXIES " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, NETPROP PROXIES, EXCEPTIONSLIST, NULL, CFARRAY_CFSTRING },
-    { REGULAR, NETPROP PROXIES, FTPENABLE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PROXIES, FTPPASSIVE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PROXIES, FTPPORT, NULL, CFNUMBER },
-    { REGULAR, NETPROP PROXIES, FTPPROXY, NULL, CFSTRING },
-    { REGULAR, NETPROP PROXIES, GOPHERENABLE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PROXIES, GOPHERPORT, NULL, CFNUMBER },
-    { REGULAR, NETPROP PROXIES, GOPHERPROXY, NULL, CFSTRING },
-    { REGULAR, NETPROP PROXIES, HTTPENABLE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PROXIES, HTTPPORT, NULL, CFNUMBER },
-    { REGULAR, NETPROP PROXIES, HTTPPROXY, NULL, CFSTRING },
-    { DEFINE , NETPROP PROXIES, HTTPSENABLE, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP PROXIES, HTTPSPORT, NULL, CFNUMBER },
-    { DEFINE , NETPROP PROXIES, HTTPSPROXY, NULL, CFSTRING },
-    { REGULAR, NETPROP PROXIES, RTSPENABLE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PROXIES, RTSPPORT, NULL, CFNUMBER },
-    { REGULAR, NETPROP PROXIES, RTSPPROXY, NULL, CFSTRING },
-    { REGULAR, NETPROP PROXIES, SOCKSENABLE, NULL, CFNUMBER_BOOL },
-    { REGULAR, NETPROP PROXIES, SOCKSPORT, NULL, CFNUMBER },
-    { REGULAR, NETPROP PROXIES, SOCKSPROXY, NULL, CFSTRING },
-    { DEFINE , NETPROP PROXIES, PROXYAUTOCONFIGENABLE, NULL, CFNUMBER_BOOL },
-    { DEFINE , NETPROP PROXIES, PROXYAUTOCONFIGURLSTRING, NULL, CFSTRING },
+  { GROUP, NETPROP PPTP, KEY_PREFIX NETENT PPTP " Entity Keys", NULL, NULL },
+
+    { COMMENT, "* RESERVED FOR FUTURE USE *", NULL, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n " KEY_PREFIX COMP USERS " Entity Keys\n */", NULL, NULL, NULL },
-    { REGULAR, USERSENT, CONSOLEUSER, NULL, NULL },
+  { GROUP, NETPROP L2TP, KEY_PREFIX NETENT L2TP " Entity Keys", NULL, NULL },
+
+    { SC_10_3, NETPROP L2TP, IPSEC SHAREDSECRET, NULL, CFSTRING },
+    { SC_10_3, NETPROP L2TP, IPSEC SHAREDSECRET ENCRYPTION, NULL, CFSTRING },
+    { SC_10_3, NETPROP L2TP, TRANSPORT, NULL, CFSTRING },
+    { COMMENT, "", NULL, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP L2TP IPSEC SHAREDSECRET ENCRYPTION " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL L2TP IPSEC SHAREDSECRET ENCRYPTION, KEYCHAIN, NULL, NULL },
+    { COMMENT, "", NULL, NULL, NULL },
+    { COMMENT, "--- " KEY_PREFIX NETPROP L2TP TRANSPORT " values ---", NULL, NULL, NULL },
+    { SC_10_3, NETVAL L2TP TRANSPORT, IP, NULL, NULL },
+    { SC_10_3, NETVAL L2TP TRANSPORT, IPSEC, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * " KEY_PREFIX COMP SYSTEM " Properties\n */", NULL, NULL, NULL },
-    { REGULAR, SYSTEMPROP, COMPUTERNAME, NULL, CFSTRING },
-    { REGULAR, SYSTEMPROP, COMPUTERNAME ENCODING, NULL, CFNUMBER },
+  { GROUP, NETPROP PROXIES, KEY_PREFIX NETENT PROXIES " Entity Keys", NULL, NULL },
+
+    { SC_10_1, NETPROP PROXIES, EXCEPTIONSLIST, NULL, CFARRAY_CFSTRING },
+    { SC_10_4, NETPROP PROXIES, EXCLUDESIMPLEHOSTNAMES, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, FTP ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, FTP PASSIVE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, FTP PORT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PROXIES, FTP PROXY, NULL, CFSTRING },
+    { SC_10_1, NETPROP PROXIES, GOPHER ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, GOPHER PORT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PROXIES, GOPHER PROXY, NULL, CFSTRING },
+    { SC_10_1, NETPROP PROXIES, HTTP ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, HTTP PORT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PROXIES, HTTP PROXY, NULL, CFSTRING },
+    { SC_10_1, NETPROP PROXIES, HTTPS ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, HTTPS PORT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PROXIES, HTTPS PROXY, NULL, CFSTRING },
+    { SC_10_1, NETPROP PROXIES, RTSP ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, RTSP PORT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PROXIES, RTSP PROXY, NULL, CFSTRING },
+    { SC_10_1, NETPROP PROXIES, SOCKS ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_1, NETPROP PROXIES, SOCKS PORT, NULL, CFNUMBER },
+    { SC_10_1, NETPROP PROXIES, SOCKS PROXY, NULL, CFSTRING },
+    { SC_10_4, NETPROP PROXIES, PROXY AUTOCONFIG ENABLE, NULL, CFNUMBER_BOOL },
+    { SC_10_4, NETPROP PROXIES, PROXY AUTOCONFIG URLSTRING, NULL, CFSTRING },
+    { SC_10_4, NETPROP PROXIES, PROXY AUTODISCOVERY ENABLE, NULL, CFNUMBER_BOOL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Configuration Store Definitions\n */", NULL },
-    { COMMENT, "/* domain prefixes */", NULL },
-    { DEFINE , DYNAMICSTORE DOMAIN, FILE, "File:", NULL },
-    { DEFINE , DYNAMICSTORE DOMAIN, PLUGIN, "Plugin:", NULL },
-    { DEFINE , DYNAMICSTORE DOMAIN, SETUP, "Setup:", NULL },
-    { DEFINE , DYNAMICSTORE DOMAIN, STATE, "State:", NULL },
-    { DEFINE , DYNAMICSTORE DOMAIN, PREFS, "Prefs:", NULL },
+  { GROUP, USERSENT CONSOLEUSER, KEY_PREFIX COMP USERS " Entity Keys", NULL, NULL },
+
+    { SC_10_1, USERSENT, CONSOLEUSER, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/* " KEY_PREFIX DYNAMICSTORE DOMAIN SETUP " Properties */", NULL },
-    { DEFINE , DYNAMICSTORE SETUPPROP, CURRENTSET, NULL, CFSTRING },
-    { DEFINE , DYNAMICSTORE SETUPPROP, LASTUPDATED, NULL, NULL },
+  { GROUP, SYSTEMPROP COMPUTERNAME, KEY_PREFIX COMP SYSTEM " Properties", NULL, NULL },
+
+    { SC_10_1, SYSTEMPROP, COMPUTERNAME, NULL, CFSTRING },
+    { SC_10_1, SYSTEMPROP, COMPUTERNAME ENCODING, NULL, CFNUMBER },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/* Properties */", NULL },
-    { DEFINE , DYNAMICSTORE NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
-    { DEFINE , DYNAMICSTORE NETPROP, PRIMARYINTERFACE, NULL, CFSTRING },
-    { DEFINE , DYNAMICSTORE NETPROP, PRIMARYSERVICE, NULL, CFSTRING },
-    { DEFINE , DYNAMICSTORE NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING },
+  { GROUP, DYNAMICSTORE DOMAIN, "SCDynamicStore \"domain\" prefixes", NULL, NULL },
+
+    { SC_10_1, DYNAMICSTORE DOMAIN, FILE, "File:", NULL },
+    { SC_10_1, DYNAMICSTORE DOMAIN, PLUGIN, "Plugin:", NULL },
+    { SC_10_1, DYNAMICSTORE DOMAIN, SETUP, "Setup:", NULL },
+    { SC_10_1, DYNAMICSTORE DOMAIN, STATE, "State:", NULL },
+    { SC_10_1, DYNAMICSTORE DOMAIN, PREFS, "Prefs:", NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
-    { COMMENT, "/*\n * Obsolete schema definitions which will be removed \"soon\".\n */", NULL },
-    { OBSOLETE, USERSPROP CONSOLEUSER, NAME, NULL, CFSTRING },
-    { OBSOLETE, USERSPROP CONSOLEUSER, UID, NULL, CFNUMBER },
-    { OBSOLETE, USERSPROP CONSOLEUSER, GID, NULL, CFNUMBER },
+  { GROUP, DYNAMICSTORE SETUPPROP, "Preference (\"location\") Keys", NULL, NULL },
+
+    { SC_10_1, DYNAMICSTORE SETUPPROP, CURRENTSET, NULL, CFSTRING },
+    { SC_10_1, DYNAMICSTORE SETUPPROP, LAST UPDATED, NULL, NULL },
     { COMMENT, "", NULL, NULL, NULL },
 
+  { GROUP, DYNAMICSTORE NETPROP, "Common/shared Keys", NULL, NULL },
+
+    { SC_10_1, DYNAMICSTORE NETPROP, INTERFACES, NULL, CFARRAY_CFSTRING },
+    { SC_10_1, DYNAMICSTORE NETPROP, PRIMARYINTERFACE, NULL, CFSTRING },
+    { SC_10_1, DYNAMICSTORE NETPROP, PRIMARYSERVICE, NULL, CFSTRING },
+    { SC_10_1, DYNAMICSTORE NETPROP, SERVICEIDS, NULL, CFARRAY_CFSTRING },
+//  { COMMENT, "", NULL, NULL, NULL },
+
+//{ GROUP, "DEPRECATED", "Deprecated schema definition keys", NULL, NULL },
+
+    { SC_10_1_10_3, USERSPROP CONSOLEUSER, NAME, NULL, CFSTRING },
+    { SC_10_1_10_3, USERSPROP CONSOLEUSER, UID, NULL, CFNUMBER },
+    { SC_10_1_10_3, USERSPROP CONSOLEUSER, GID, NULL, CFNUMBER },
+//  { COMMENT, "", NULL, NULL, NULL },
+
     { END, NULL, NULL, NULL, NULL },
 };
 
@@ -733,6 +782,8 @@ setmax(int *max, char **maxstr, char *str)
 
 enum {
     gen_header_e,
+    gen_comments_e,
+    gen_headerdoc_e,
     gen_hfile_e,
     gen_cfile_e,
 };
@@ -752,195 +803,205 @@ dump_names(int type)
                goto done;
                break;
            }
+
            case COMMENT: {
                switch (type) {
-               case gen_header_e:
-               case gen_hfile_e:
-                   if (names[i].prefix)
-                       printf("%s\n", names[i].prefix);
-                   break;
-               default:
-                   break;
+                   case gen_header_e:
+                       break;
+                   case gen_comments_e:
+                       if (names[i].prefix)
+                           printf(" *   %s\n", names[i].prefix);
+                       break;
+                   case gen_hfile_e:
+//                     if (names[i].prefix)
+//                         printf("%s\n", names[i].prefix);
+                       break;
+                   default:
+                       break;
                }
                break;
            }
-           case DEFINE: {
-               char kbuf[256];
-               char vbuf[256];
 
+           case GROUP: {
                switch (type) {
-               case gen_header_e:
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   if (names[i].value)
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].value);
-                   else
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].key);
-
-                   if (names[i].type)
-                       printf("#define %-40s %-40s /* %s */\n",
-                              kbuf, vbuf, names[i].type);
-                   else
-                       printf("#define %-40s %-40s\n",
-                              kbuf, vbuf);
-                   break;
-               case gen_hfile_e:
-                   snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
-                            names[i].prefix, names[i].key);
-                   setmax(&maxkbuf, &maxkstr, kbuf);
-
-                   snprintf(vbuf, sizeof(vbuf), "\"%s\"",
-                            names[i].value ? names[i].value : names[i].key);
-                   setmax(&maxvbuf, &maxvstr, vbuf);
-
-                   printf("SC_SCHEMA_DECLARATION%-42s /* %-17s %-30s */\n",
-                          kbuf,
-                          names[i].type ? names[i].type : "",
-                          vbuf);
-                   break;
-               case gen_cfile_e:
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   if (names[i].value)
-                       printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
-                              kbuf, names[i].value);
-                   else
-                       printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
-                              kbuf, names[i].key);
-                   break;
-               default:
-                   break;
+                   case gen_header_e:
+                       break;
+                   case gen_comments_e:
+                       if (names[i].key)
+                           printf(" * %s\n *\n", names[i].key);
+                       break;
+                   case gen_headerdoc_e:
+                       if (names[i].prefix)
+                           printf("\n/*!\n  @group %s\n */\n", names[i].key);
+                       break;
+                   default:
+                       break;
                }
                break;
            }
-           case REGULAR: {
-               char kbuf[256];
-               char vbuf[256];
 
-               switch (type) {
-               case gen_header_e:
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   if (names[i].value)
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].value);
-                   else
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].key);
-
-                   if (names[i].type)
-                       printf("#define %-40s %-40s /* %s */\n",
-                              kbuf, vbuf, names[i].type);
-                   else
-                       printf("#define %-40s %-40s\n",
-                              kbuf, vbuf);
-                   break;
-               case gen_hfile_e:
-                   snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
-                            names[i].prefix, names[i].key);
-                   setmax(&maxkbuf, &maxkstr, kbuf);
-
-                   snprintf(vbuf, sizeof(vbuf), "\"%s\"",
-                            names[i].value ? names[i].value : names[i].key);
-                   setmax(&maxvbuf, &maxvstr, vbuf);
-
-                   printf("SC_SCHEMA_DECLARATION%-42s /* %-17s %-30s */\n",
-                          kbuf,
-                          names[i].type ? names[i].type : "",
-                          vbuf);
-                   break;
-               case gen_cfile_e:
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   if (names[i].value)
-                       printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
-                              kbuf, names[i].value);
-                   else
-                       printf("const CFStringRef %-45s = CFSTR(\"%s\");\n",
-                              kbuf, names[i].key);
-                   break;
-               default:
-                   break;
-               }
-               break;
-           }
-           case OBSOLETE: {
-               static int nObsolete = 0;
+           default: {
                char kbuf[256];
                char vbuf[256];
 
                switch (type) {
-               case gen_hfile_e:
-                   if (nObsolete++ == 0) {
-                       printf("#ifndef  SCSTR\n");
-                       printf("#include <CoreFoundation/CFString.h>\n");
-                       printf("#define  SCSTR(s) CFSTR(s)\n");
-                       printf("#endif\n");
-                   }
-
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   if (names[i].value)
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].value);
-                   else
-                       snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
-                                names[i].key);
-
-                   printf("#define %-40s %-40s /* %s */\n",
-                          kbuf,
-                          vbuf,
-                          names[i].type ? names[i].type : "");
-                   break;
-               default:
-                   break;
-               }
-               break;
-           }
-           case FUTURE: {
-               char kbuf[256];
-
-               switch (type) {
-               case gen_header_e:
-                   snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
-                            names[i].prefix, names[i].key);
-
-                   printf("// #define %-37s %-40s /* %s */\n",
-                          kbuf,
-                          "SCSTR(\"???\") */",
-                          "RESERVED FOR FUTURE USE");
-                   break;
-               case gen_hfile_e:
-                   snprintf(kbuf, sizeof(kbuf), "(" KEY_PREFIX "%s%s);",
-                            names[i].prefix, names[i].key);
-                   setmax(&maxkbuf, &maxkstr, kbuf);
-
-                   printf("// SC_SCHEMA_DECLARATION%-39s /* %s */\n",
-                          kbuf, "RESERVED FOR FUTURE USE");
-                   break;
-               default:
-                   break;
+                   case gen_header_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+
+                       if (names[i].value)
+                           snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
+                                    names[i].value);
+                       else
+                           snprintf(vbuf, sizeof(vbuf), "SCSTR(\"%s\")",
+                                    names[i].key);
+
+                       printf("#define %-50s %s\n",
+                              kbuf, vbuf);
+                       break;
+                   case gen_comments_e:
+                       switch (names[i].control) {
+                           case SC_10_1_10_3:
+                               // don't report deprecated keys
+                               break;
+                           default:
+                               snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                        names[i].prefix, names[i].key);
+
+                               snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+                                        names[i].value ? names[i].value : names[i].key);
+
+                               if (names[i].type)
+                                   printf(" *   %-50s %-30s %s\n",
+                                          kbuf, vbuf, names[i].type);
+                               else
+                                   printf(" *   %-50s %s\n",
+                                          kbuf, vbuf);
+                               break;
+                       }
+                       break;
+                   case gen_headerdoc_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+                       setmax(&maxkbuf, &maxkstr, kbuf);
+
+                       snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+                                names[i].value ? names[i].value : names[i].key);
+                       setmax(&maxvbuf, &maxvstr, vbuf);
+
+                       printf("\n");
+
+                       printf("/*!\n");
+                       printf("  @const %s\n", kbuf);
+                       switch (names[i].control) {
+                           case SC_10_1:
+                               printf("  @availability Introduced in Mac OS X 10.1.\n");
+                               break;
+                           case SC_10_2:
+                               printf("  @availability Introduced in Mac OS X 10.2.\n");
+                               break;
+                           case SC_10_1_10_3:
+                               printf("  @availability Introduced in Mac OS X 10.1, but later deprecated in Mac OS X 10.4.\n");
+                               break;
+                           case SC_10_3:
+                               printf("  @availability Introduced in Mac OS X 10.3.\n");
+                               break;
+                           case SC_10_4:
+                               printf("  @availability Introduced in Mac OS X 10.4.\n");
+                               break;
+                       }
+                       printf(" */\n");
+                       printf("extern const CFStringRef %s;\n", kbuf);
+
+                       break;
+                   case gen_hfile_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+                       setmax(&maxkbuf, &maxkstr, kbuf);
+
+                       snprintf(vbuf, sizeof(vbuf), "\"%s\"",
+                                names[i].value ? names[i].value : names[i].key);
+                       setmax(&maxvbuf, &maxvstr, vbuf);
+
+                       printf("\n");
+
+                       switch (names[i].control) {
+                           case SC_10_2:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2\n");
+                               break;
+                           case SC_10_1_10_3:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_1 && \\\n");
+                               printf("    MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_3\n");
+                               break;
+                           case SC_10_3:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3\n");
+                               break;
+                           case SC_10_4:
+                               printf("#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4\n");
+                               break;
+                       }
+
+                       printf("#define %-48s              \\\n",
+                              kbuf);
+                       printf("\tSC_SCHEMA_KV(%-48s \\\n",
+                              kbuf);
+                       printf("\t            ,%-48s \\\n",
+                              vbuf);
+                       printf("\t            ,%-48s )\n",
+                              names[i].type ? names[i].type : "");
+
+                       switch (names[i].control) {
+                           case SC_10_2:
+                           case SC_10_3:
+                           case SC_10_1_10_3:
+                           case SC_10_4:
+                               printf("#endif\n");
+                               break;
+                       }
+
+                       switch (names[i].control) {
+                           case SC_10_2:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER);\n", kbuf);
+                               break;
+                           case SC_10_3:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER);\n", kbuf);
+                               break;
+                           case SC_10_1_10_3:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4);\n", kbuf);
+                               break;
+                           case SC_10_4:
+                               printf("\tSC_SCHEMA_DECLARATION(%s, AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER);\n", kbuf);
+                               break;
+                           default:
+                               printf("\tSC_SCHEMA_DECLARATION(%s,);\n", kbuf);
+                               break;
+                       }
+
+                       break;
+                   case gen_cfile_e:
+                       snprintf(kbuf, sizeof(kbuf), KEY_PREFIX "%s%s",
+                                names[i].prefix, names[i].key);
+
+                       if (names[i].value)
+                           printf("const CFStringRef %-48s = CFSTR(\"%s\");\n",
+                                  kbuf, names[i].value);
+                       else
+                           printf("const CFStringRef %-48s = CFSTR(\"%s\");\n",
+                                  kbuf, names[i].key);
+                       break;
+                   default:
+                       break;
                }
                break;
            }
-           default: {
-               break;
-           }
        }
     }
  done:
     switch (type) {
-    case gen_hfile_e:
-       fprintf(stderr, "max key: length = %2d, string = %s\n", maxkbuf, maxkstr);
-       fprintf(stderr, "max val: length = %2d, string = %s\n", maxvbuf, maxvstr);
-       break;
+       case gen_hfile_e:
+           fprintf(stderr, "max key: length = %2d, string = %s\n", maxkbuf, maxkstr);
+           fprintf(stderr, "max val: length = %2d, string = %s\n", maxvbuf, maxvstr);
+           break;
     }
     return;
 }
@@ -967,13 +1028,22 @@ main(int argc, char * argv[])
 
        printf("#ifndef _SCSCHEMADEFINITIONS_10_1_H\n#define _SCSCHEMADEFINITIONS_10_1_H\n\n");
 
-       printf("#ifndef  SCSTR\n");
-       printf("#include <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) {
@@ -981,35 +1051,115 @@ main(int argc, char * argv[])
        printf("/*\n * This file is automatically generated\n * DO NOT EDIT!\n */\n\n");
 
        printf("/*\n");
-       printf(" * Note: For Cocoa/Obj-C/Foundation programs accessing these preference\n");
-       printf(" *       keys you may want to consider the following:\n");
+       dump_names(gen_comments_e);
+       printf(" */\n\n\n");
+
+       printf("/*\n");
+       printf(" * Note: The MACOSX_DEPLOYMENT_TARGET environment variable should be used\n");
+       printf(" *       when building an application targeted for an earlier version of\n");
+       printf(" *       Mac OS X.  Please reference Technical Note TN2064 for more details.\n");
+       printf(" */\n\n");
+
+       printf("/*\n");
+       printf(" * Note: For Cocoa/Obj-C/Foundation applications accessing these preference\n");
+       printf(" *       keys you may want to consider the following :\n");
        printf(" *\n");
-       printf(" *       #define " SC_SCHEMA_DECLARATION "(x)\t\textern NSString * x\n");
+       printf(" *       #define " SC_SCHEMA_DECLARATION "(k,q)\textern NSString * k\n");
        printf(" *       #import <SystemConfiguration/SystemConfiguration.h>\n");
        printf(" */\n\n");
 
+       printf("/*\n");
+       printf(" * Note: For CFM applications using these schema keys you may want to\n");
+       printf(" *       consider the following :\n");
+       printf(" *\n");
+       printf(" *       #define SC_SCHEMA_KV(k,v,t)\tlookup_SC_key( CFSTR( #k ) )\n");
+       printf(" *       #define SC_SCHEMA_DECLARATION(k,q)\n");
+       printf(" *       #include <SystemConfiguration/SystemConfiguration.h>\n");
+       printf(" *\n");
+       printf(" *       CFStringRef lookup_SC_key(CFStringRef key)\n");
+       printf(" *       {\n");
+       printf(" *         // this function should [dynamically, on-demand] load the\n");
+       printf(" *         // SystemConfiguration.framework, look up the provided key,\n");
+       printf(" *         // and return the associated value.\n");
+       printf(" *       }\n");
+       printf(" */\n\n");
+
+       printf("/*\n");
+       printf(" * Note: Earlier versions of this header file defined a \"SCSTR\" macro\n");
+       printf(" *       which helped to facilitate Obj-C development. Use of this macro\n");
+       printf(" *       has been deprecated (in Mac OS X 10.4) in favor of the newer\n");
+       printf(" *       \"SC_SCHEMA_KV\" and \"SC_SCHEMA_DECLARATION\" macros\n");
+       printf(" */\n\n\n");
+
        printf("#ifndef _SCSCHEMADEFINITIONS_H\n#define _SCSCHEMADEFINITIONS_H\n\n");
 
-       printf("#ifndef SC_SCHEMA_DECLARATION\n");
-       printf("#ifndef SCSTR\n");
-       printf("#include <CoreFoundation/CFString.h>\n");
-       printf("#define " SC_SCHEMA_DECLARATION "(x)\textern const CFStringRef x\n");
-       printf("#else\n");
-       printf("#import <Foundation/NSString.h>\n");
-       printf("#define " SC_SCHEMA_DECLARATION "(x)\textern NSString * x\n");
-       printf("#endif\n");
-       printf("#endif\n");
+       printf("/* -------------------- Macro declarations -------------------- */\n\n");
 
-       printf("\n");
-       dump_names(gen_hfile_e);
+       printf("#include <AvailabilityMacros.h>\n\n");
+
+       printf("/*\n");
+       printf(" * let's \"do the right thing\" for those wishing to build for\n");
+       printf(" * Mac OS X 10.1 and 10.2\n");
+       printf(" */\n");
 
-       printf("#include <AvailabilityMacros.h>\n");
        printf("#if MAC_OS_X_VERSION_10_3 > MAC_OS_X_VERSION_MIN_REQUIRED\n");
        printf("  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
-       printf("    #include <SystemConfiguration/SCSchemaDefinitions_10_1.h>\n");
+       printf("    #ifndef SCSTR\n");
+       printf("      #include <CoreFoundation/CFString.h>\n");
+       printf("      #define SCSTR(s) CFSTR(s)\n");
+       printf("    #endif\n");
+       printf("    #ifndef SC_SCHEMA_KV\n");
+       printf("      #define SC_SCHEMA_KV(k,v,t)\tSCSTR( v )\n");
+       printf("    #endif\n");
+       printf("    #ifndef SC_SCHEMA_DECLARATION\n");
+       printf("      #define SC_SCHEMA_DECLARATION(k,q)\n");
+       printf("    #endif\n");
        printf("  #endif\n");
        printf("#endif\n\n");
 
+       printf("/*\n");
+       printf(" * Define a schema key/value/type tuple\n");
+       printf(" */\n");
+       printf("#ifndef SC_SCHEMA_KV\n");
+       printf("  #define " SC_SCHEMA_KV "(k,v,t)\tk\n");
+       printf("#endif\n\n");
+
+       printf("/*\n");
+       printf(" * Provide an \"extern\" for the key/value\n");
+       printf(" */\n");
+       printf("#ifndef SC_SCHEMA_DECLARATION\n");
+       printf("  #ifndef SCSTR\n");
+       printf("    #include <CoreFoundation/CFString.h>\n");
+       printf("    #define " SC_SCHEMA_DECLARATION "(k,q)\textern const CFStringRef k q\n");
+       printf("  #else\n");
+       printf("    #import <Foundation/NSString.h>\n");
+       printf("    #define " SC_SCHEMA_DECLARATION "(k,q)\textern NSString * k q\n");
+       printf("  #endif\n");
+       printf("#endif\n");
+
+       // The SCSTR() macro should be availble for 10.1 ... 10.4
+       printf("#if MAC_OS_X_VERSION_10_4 >= MAC_OS_X_VERSION_MIN_REQUIRED\n");
+       printf("  #if MAC_OS_X_VERSION_10_1 <= MAC_OS_X_VERSION_MIN_REQUIRED\n");
+       printf("    #ifndef SCSTR\n");
+       printf("      #include <CoreFoundation/CFString.h>\n");
+       printf("      #define SCSTR(s) CFSTR(s)\n");
+       printf("    #endif\n");
+       printf("  #endif\n");
+       printf("#endif\n\n\n");
+
+       printf("/* -------------------- HeaderDoc comments -------------------- */\n\n\n");
+       printf("#if\t0\n");
+       printf("/*!\n");
+       printf(" *\t@header SCSchemaDefinitions\n");
+       printf(" */\n");
+       dump_names(gen_headerdoc_e);
+       printf("\n");
+       printf("#endif\t/* 0 */\n\n\n");
+
+       printf("/* -------------------- Schema declarations -------------------- */\n\n");
+       dump_names(gen_hfile_e);
+       printf("\n");
+
        printf("#endif /* _SCSCHEMADEFINITIONS_H */\n");
     }
     else if (strcmp(type, "cfile") == 0) {
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@
  * 
  */
 
 
+#include <unistd.h>
+
 #include "configd.h"
+#include "configd_server.h"
+#include "session.h"
 
 
 __private_extern__ CFMutableDictionaryRef      sessionData             = NULL;
@@ -133,7 +137,7 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        i = CFArrayGetFirstIndexOfValue(newWatchers,
                                        CFRangeMake(0, CFArrayGetCount(newWatchers)),
                                        sessionNum);
-       if (i == -1) {
+       if (i == kCFNotFound) {
                /* if this is the first instance of this session watching this key */
                CFArrayAppendValue(newWatchers, sessionNum);
                refCnt = 1;
@@ -164,7 +168,9 @@ _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        CFDictionarySetValue(storeData, watchedKey, newDict);
        CFRelease(newDict);
 
+#ifdef DEBUG
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _addWatcher: %@, %@"), sessionNum, watchedKey);
+#endif /* DEBUG */
 
        return;
 }
@@ -190,7 +196,9 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        dict = CFDictionaryGetValue(storeData, watchedKey);
        if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) {
                /* key doesn't exist (isn't this really fatal?) */
+#ifdef DEBUG
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey);
+#endif /* DEBUG */
                return;
        }
        newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
@@ -209,8 +217,10 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        i = CFArrayGetFirstIndexOfValue(newWatchers,
                                        CFRangeMake(0, CFArrayGetCount(newWatchers)),
                                        sessionNum);
-       if (i == -1) {
+       if (i == kCFNotFound) {
+#ifdef DEBUG
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _removeWatcher: %@, %@, session not watching"), sessionNum, watchedKey);
+#endif /* DEBUG */
                CFRelease(newDict);
                CFRelease(newWatchers);
                CFRelease(newWatcherRefs);
@@ -251,7 +261,159 @@ _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
        }
        CFRelease(newDict);
 
+#ifdef DEBUG
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  _removeWatcher: %@, %@"), sessionNum, watchedKey);
+#endif /* DEBUG */
+
+       return;
+}
+
+
+__private_extern__
+void
+pushNotifications()
+{
+       const void                      **sessionsToNotify;
+       CFIndex                         notifyCnt;
+       int                             server;
+       serverSessionRef                theSession;
+       SCDynamicStorePrivateRef        storePrivate;
+
+       if (needsNotification == NULL)
+               return;         /* if no sessions need to be kicked */
+
+       notifyCnt = CFSetGetCount(needsNotification);
+       sessionsToNotify = malloc(notifyCnt * sizeof(CFNumberRef));
+       CFSetGetValues(needsNotification, sessionsToNotify);
+       while (--notifyCnt >= 0) {
+               (void) CFNumberGetValue(sessionsToNotify[notifyCnt],
+                                       kCFNumberIntType,
+                                       &server);
+               theSession = getSession(server);
+               storePrivate = (SCDynamicStorePrivateRef)theSession->store;
+
+               /*
+                * deliver notifications to client sessions
+                */
+               if ((storePrivate->notifyStatus == Using_NotifierInformViaMachPort) &&
+                   (storePrivate->notifyPort != MACH_PORT_NULL)) {
+                       mach_msg_empty_send_t   msg;
+                       mach_msg_option_t       options;
+                       kern_return_t           status;
+                       /*
+                        * Post notification as mach message
+                        */
+#ifdef DEBUG
+                       if (_configd_verbose) {
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("sending mach message notification."));
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("  port  = %d"), storePrivate->notifyPort);
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("  msgid = %d"), storePrivate->notifyPortIdentifier);
+                       }
+#endif /* DEBUG */
+                       msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
+                       msg.header.msgh_size = sizeof(msg);
+                       msg.header.msgh_remote_port = storePrivate->notifyPort;
+                       msg.header.msgh_local_port = MACH_PORT_NULL;
+                       msg.header.msgh_id = storePrivate->notifyPortIdentifier;
+                       options = MACH_SEND_TIMEOUT;
+                       status = mach_msg(&msg.header,                  /* msg */
+                                         MACH_SEND_MSG|options,        /* options */
+                                         msg.header.msgh_size,         /* send_size */
+                                         0,                            /* rcv_size */
+                                         MACH_PORT_NULL,               /* rcv_name */
+                                         0,                            /* timeout */
+                                         MACH_PORT_NULL);              /* notify */
+                       if (status == MACH_SEND_TIMED_OUT) {
+                               mach_msg_destroy(&msg.header);
+                       }
+               }
+
+               if ((storePrivate->notifyStatus == Using_NotifierInformViaFD) &&
+                   (storePrivate->notifyFile >= 0)) {
+                       ssize_t         written;
+
+#ifdef DEBUG
+                       if (_configd_verbose) {
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("sending (UNIX domain) socket notification"));
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("  fd    = %d"), storePrivate->notifyFile);
+                               SCLog(TRUE, LOG_DEBUG, CFSTR("  msgid = %d"), storePrivate->notifyFileIdentifier);
+                       }
+#endif /* DEBUG */
+
+                       written = write(storePrivate->notifyFile,
+                                       &storePrivate->notifyFileIdentifier,
+                                       sizeof(storePrivate->notifyFileIdentifier));
+                       if (written == -1) {
+                               if (errno == EWOULDBLOCK) {
+#ifdef DEBUG
+                                       SCLog(_configd_verbose, LOG_DEBUG,
+                                             CFSTR("sorry, only one outstanding notification per session."));
+#endif /* DEBUG */
+                               } else {
+#ifdef DEBUG
+                                       SCLog(_configd_verbose, LOG_DEBUG,
+                                             CFSTR("could not send notification, write() failed: %s"),
+                                             strerror(errno));
+#endif /* DEBUG */
+                                       storePrivate->notifyFile = -1;
+                               }
+                       } else if (written != sizeof(storePrivate->notifyFileIdentifier)) {
+#ifdef DEBUG
+                               SCLog(_configd_verbose, LOG_DEBUG,
+                                     CFSTR("could not send notification, incomplete write()"));
+#endif /* DEBUG */
+                               storePrivate->notifyFile = -1;
+                       }
+               }
+
+               if ((storePrivate->notifyStatus == Using_NotifierInformViaSignal) &&
+                   (storePrivate->notifySignal > 0)) {
+                       kern_return_t   status;
+                       pid_t           pid;
+                       /*
+                        * Post notification as signal
+                        */
+                       status = pid_for_task(storePrivate->notifySignalTask, &pid);
+                       if (status == KERN_SUCCESS) {
+#ifdef DEBUG
+                               if (_configd_verbose) {
+                                       SCLog(TRUE, LOG_DEBUG, CFSTR("sending signal notification"));
+                                       SCLog(TRUE, LOG_DEBUG, CFSTR("  pid    = %d"), pid);
+                                       SCLog(TRUE, LOG_DEBUG, CFSTR("  signal = %d"), storePrivate->notifySignal);
+                               }
+#endif /* DEBUG */
+                               if (kill(pid, storePrivate->notifySignal) != 0) {
+#ifdef DEBUG
+                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), strerror(errno));
+#endif /* DEBUG */
+                                       status = KERN_FAILURE;
+                               }
+                       } else {
+                               mach_port_type_t        pt;
+
+                               if ((mach_port_type(mach_task_self(), storePrivate->notifySignalTask, &pt) == KERN_SUCCESS) &&
+                                   (pt & MACH_PORT_TYPE_DEAD_NAME)) {
+                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal, process died"));
+                               } else {
+                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not send signal: %s"), mach_error_string(status));
+                               }
+                       }
+
+                       if (status != KERN_SUCCESS) {
+                               /* don't bother with any more attempts */
+                               (void) mach_port_destroy(mach_task_self(), storePrivate->notifySignalTask);
+                               storePrivate->notifySignal     = 0;
+                               storePrivate->notifySignalTask = TASK_NULL;
+                       }
+              }
+       }
+       free(sessionsToNotify);
+
+       /*
+        * this list of notifications have been posted, wait for some more.
+        */
+       CFRelease(needsNotification);
+       needsNotification = NULL;
 
        return;
 }
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@
  * 
@@ -27,7 +27,7 @@
  * 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
  */
 
@@ -119,12 +119,8 @@ __SCDynamicStoreCopyKeyList                (SCDynamicStoreRef      store,
 int
 __SCDynamicStoreAddValue               (SCDynamicStoreRef      store,
                                         CFStringRef            key,
-                                        CFDataRef              value);
-
-int
-__SCDynamicStoreAddTemporaryValue      (SCDynamicStoreRef      store,
-                                        CFStringRef            key,
-                                        CFDataRef              value);
+                                        CFDataRef              value,
+                                        Boolean                internal);
 
 int
 __SCDynamicStoreCopyValue              (SCDynamicStoreRef      store,
@@ -217,6 +213,9 @@ void
 _removeWatcher                         (CFNumberRef            sessionNum,
                                         CFStringRef            watchedKey);
 
+void
+pushNotifications                      ();
+
 __END_DECLS
 
 #endif /* !_S_SCD_H */
index 5e0d5015d3076d92e22f9ac84500e51e7b43c49b..792e57a0e0e9281cf4eecfba9e8deef2925729d5 100644 (file)
 
 __private_extern__
 int
-__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value)
+__SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef value, Boolean internal)
 {
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
        int                             sc_status       = kSCStatusOK;
        CFDataRef                       tempValue;
 
-       if (_configd_verbose) {
-               CFPropertyListRef       val;
-
-               (void) _SCUnserialize(&val, value, NULL, NULL);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), val);
-               CFRelease(val);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
 
        if (_configd_trace) {
-               SCTrace(TRUE, _configd_trace, CFSTR("add     : %5d : %@\n"), storePrivate->server, key);
+               SCTrace(TRUE, _configd_trace,
+                       CFSTR("%s%s : %5d : %@\n"),
+                       internal ? "*add " : "add  ",
+                       storePrivate->useSessionKeys ? "t " : "  ",
+                       storePrivate->server,
+                       key);
        }
 
        /*
@@ -84,7 +79,9 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
                        goto done;
 
                default :
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
+#ifdef DEBUG
+                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreAddValue __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
+#endif /* DEBUG */
                        goto done;
        }
 
@@ -96,7 +93,9 @@ __SCDynamicStoreAddValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
        /*
         * 4. Release our lock.
         */
+
     done:
+
        __SCDynamicStoreUnlock(store, TRUE);
 
        return sc_status;
@@ -114,44 +113,102 @@ _configadd(mach_port_t                   server,
           int                          *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-       CFDataRef               data;           /* data (un-serialized) */
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       CFDataRef               data            = NULL;         /* data (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
+
+       /* un-serialize the key */
+       if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
+               *sc_status = kSCStatusFailed;
+               goto done;
+       }
+
+       if (!isA_CFString(key)) {
+               *sc_status = kSCStatusInvalidArgument;
+               goto done;
+       }
+
+       /* un-serialize the data */
+       if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
+               *sc_status = kSCStatusFailed;
+               goto done;
+       }
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Add key to configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
+       if (!mySession) {
+               *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
+               goto done;
        }
 
-       *sc_status = kSCStatusOK;
+       *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+       if (*sc_status == kSCStatusOK) {
+               *newInstance = 0;
+       }
+
+    done :
+
+       if (key)        CFRelease(key);
+       if (data)       CFRelease(data);
+
+       return KERN_SUCCESS;
+}
+
+
+__private_extern__
+kern_return_t
+_configadd_s(mach_port_t               server,
+            xmlData_t                  keyRef,         /* raw XML bytes */
+            mach_msg_type_number_t     keyLen,
+            xmlData_t                  dataRef,        /* raw XML bytes */
+            mach_msg_type_number_t     dataLen,
+            int                        *newInstance,
+            int                        *sc_status
+)
+{
+       CFDataRef                       data            = NULL;         /* data (un-serialized) */
+       CFStringRef                     key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef                mySession       = getSession(server);
+       SCDynamicStorePrivateRef        storePrivate;
+       Boolean                         useSessionKeys;
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-       } else if (!isA_CFString(key)) {
+               goto done;
+       }
+
+       if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
+               goto done;
        }
 
        /* un-serialize the data */
        if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
                *sc_status = kSCStatusFailed;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
+               goto done;
        }
 
-       if (*sc_status != kSCStatusOK) {
-               if (key)        CFRelease(key);
-               if (data)       CFRelease(data);
-               return KERN_SUCCESS;
+       // force "useSessionKeys"
+       storePrivate = (SCDynamicStorePrivateRef)mySession->store;
+       useSessionKeys = storePrivate->useSessionKeys;
+       storePrivate->useSessionKeys = TRUE;
+
+       *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data, FALSE);
+       if (*sc_status == kSCStatusOK) {
+               *newInstance = 0;
        }
 
-       *sc_status = __SCDynamicStoreAddValue(mySession->store, key, data);
-       *newInstance = 0;
+       // restore "useSessionKeys"
+       storePrivate->useSessionKeys = useSessionKeys;
+
+    done :
 
-       CFRelease(key);
-       CFRelease(data);
+       if (key)        CFRelease(key);
+       if (data)       CFRelease(data);
 
        return KERN_SUCCESS;
 }
diff --git a/configd.tproj/_configadd_s.c b/configd.tproj/_configadd_s.c
deleted file mode 100644 (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)
 {
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)*store;
-       CFIndex                         keyCnt;
-       CFStringRef                     sessionKey;
        CFDictionaryRef                 dict;
        CFArrayRef                      keys;
+       CFIndex                         keyCnt;
        serverSessionRef                mySession;
-
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreClose:"));
+       CFStringRef                     sessionKey;
+       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)*store;
 
        if ((*store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
@@ -177,14 +175,12 @@ __SCDynamicStoreClose(SCDynamicStoreRef *store, Boolean internal)
        }
 
        /*
-        * Remove the run loop source on the server port (for this
-        * client).  Then, invalidate and release the port.
+        * invalidate and release our run loop source on the server
+        * port (for this client).  Then, release the port.
         */
        mySession = getSession(storePrivate->server);
        if (mySession->serverRunLoopSource) {
-               CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
-                                     mySession->serverRunLoopSource,
-                                     kCFRunLoopDefaultMode);
+               CFRunLoopSourceInvalidate(mySession->serverRunLoopSource);
                CFRelease(mySession->serverRunLoopSource);
        }
        CFMachPortInvalidate(mySession->serverPort);
@@ -204,11 +200,6 @@ _configclose(mach_port_t server, int *sc_status)
 {
        serverSessionRef        mySession = getSession(server);
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Close session."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                return KERN_SUCCESS;
@@ -219,7 +210,6 @@ _configclose(mach_port_t server, int *sc_status)
         */
        *sc_status = __SCDynamicStoreClose(&mySession->store, FALSE);
        if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreClose(): %s"), SCErrorString(*sc_status));
                return KERN_SUCCESS;
        }
 
index fa889fe3f32635faf73b9b5909e50f7f3004089b..caeae329395d1ba1ed5596adf356a457503c4e49 100644 (file)
@@ -41,11 +41,6 @@ __SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *v
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        CFDictionaryRef                 dict;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key      = %@"), key);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -67,14 +62,6 @@ __SCDynamicStoreCopyValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef *v
        /* Return the data associated with the key */
        *value = CFRetain(CFDictionaryGetValue(dict, kSCDData));
 
-       if (_configd_verbose) {
-               CFPropertyListRef       val;
-
-               (void) _SCUnserialize(&val, *value, NULL, NULL);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value    = %@"), val);
-               CFRelease(val);
-       }
-
        return kSCStatusOK;
 }
 
@@ -89,41 +76,33 @@ _configget(mach_port_t                      server,
           int                          *sc_status
 )
 {
-       CFStringRef             key;            /* key  (un-serialized) */
-       serverSessionRef        mySession = getSession(server);
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
        Boolean                 ok;
        CFDataRef               value;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Get key from configuration database."));
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        *dataRef = NULL;
        *dataLen = 0;
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreCopyValue(mySession->store, key, &value, FALSE);
-       CFRelease(key);
        if (*sc_status != kSCStatusOK) {
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /* serialize the data */
@@ -131,7 +110,7 @@ _configget(mach_port_t                      server,
        CFRelease(value);
        if (!ok) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /*
@@ -139,6 +118,9 @@ _configget(mach_port_t                      server,
         */
        *newInstance = 1;
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
 
@@ -202,12 +184,6 @@ __SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRe
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        addSpecific                     myContext;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyMultiple:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keys     = %@"), keys);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  patterns = %@"), patterns);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -243,14 +219,6 @@ __SCDynamicStoreCopyMultiple(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRe
        /* Return the keys/values associated with the key */
        *values = myContext.dict;
 
-       if (_configd_verbose) {
-               CFDictionaryRef expDict;
-
-               expDict = _SCUnserializeMultiple(*values);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  values   = %@"), expDict);
-               CFRelease(expDict);
-       }
-
        return kSCStatusOK;
 }
 
@@ -271,23 +239,19 @@ _configget_m(mach_port_t          server,
        Boolean                 ok;
        CFArrayRef              patterns        = NULL; /* patterns (un-serialized) */
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Get keys from configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        *dataRef = NULL;
        *dataLen = 0;
-       *sc_status = kSCStatusOK;
 
        if (keysRef && (keysLen > 0)) {
                /* un-serialize the keys */
                if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) {
                        *sc_status = kSCStatusFailed;
+                       goto done;
                }
 
                if (!isA_CFArray(keys)) {
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
@@ -295,34 +259,33 @@ _configget_m(mach_port_t          server,
                /* un-serialize the patterns */
                if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) {
                        *sc_status = kSCStatusFailed;
+                       goto done;
                }
 
                if (!isA_CFArray(patterns)) {
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
+               goto done;
        }
 
-       if (*sc_status != kSCStatusOK) {
-               if (keys)       CFRelease(keys);
-               if (patterns)   CFRelease(patterns);
-               return KERN_SUCCESS;
-       }
-
+       /* fetch the requested information */
        *sc_status = __SCDynamicStoreCopyMultiple(mySession->store, keys, patterns, &dict);
-       if (keys)       CFRelease(keys);
-       if (patterns)   CFRelease(patterns);
 
        /* serialize the dictionary of matching keys/patterns */
        ok = _SCSerialize(dict, NULL, (void **)dataRef, (CFIndex *)dataLen);
        CFRelease(dict);
        if (!ok) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
        }
 
+    done :
+
+       if (keys)       CFRelease(keys);
+       if (patterns)   CFRelease(patterns);
        return KERN_SUCCESS;
 }
index a43e889b6b146e93aeafda75cf073ea0b08d8973..6591a9972f5c5aa8ce4da94d87404f676d1a8282 100644 (file)
@@ -48,31 +48,22 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
        CFStringRef                     storeStr;
        CFDictionaryRef                 storeValue;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
 
-       storeCnt = CFDictionaryGetCount(storeData);
-       keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
-
        if (isRegex) {
                CFStringRef     reErrStr;
 
                if (!patternCompile(key, &preg, &reErrStr)) {
-                       CFArrayAppendValue(keyArray, reErrStr);
+                       *subKeys = CFArrayCreate(NULL, (const void **)&reErrStr, 1, &kCFTypeArrayCallBacks);
                        CFRelease(reErrStr);
-                       *subKeys = CFArrayCreateCopy(NULL, keyArray);
-                       CFRelease(keyArray);
                        return kSCStatusFailed;
                }
        }
 
+       storeCnt = CFDictionaryGetCount(storeData);
+       keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
        if (storeCnt > 0) {
                int             i;
                const void *    storeKeys_q[N_QUICK];
@@ -103,7 +94,7 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
                                if (storeKeyLen > (CFIndex)sizeof(storeKey_q))
                                        storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0);
                                if (_SC_cfstring_to_cstring(storeStr, storeKey, storeKeyLen, kCFStringEncodingASCII) == NULL) {
-                                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+                                       SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList(): could not convert store key to C string"));
                                        if (storeKey != storeKey_q) CFAllocatorDeallocate(NULL, storeKey);
                                        continue;
                                }
@@ -126,7 +117,7 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
                                                                       &preg,
                                                                       reErrBuf,
                                                                       sizeof(reErrBuf));
-                                               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+                                               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyKeyList regexec() failed: %s"), reErrBuf);
                                                break;
                                        }
                                }
@@ -153,8 +144,8 @@ __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean is
                regfree(&preg);
        }
 
-       *subKeys = keyArray;
-
+       *subKeys = CFArrayCreateCopy(NULL, keyArray);
+       CFRelease(keyArray);
        return kSCStatusOK;
 }
 
@@ -170,15 +161,10 @@ _configlist(mach_port_t                   server,
            int                         *sc_status
 )
 {
-       CFStringRef             key;            /* key  (un-serialized) */
-       serverSessionRef        mySession = getSession(server);
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
        Boolean                 ok;
-       CFArrayRef              subKeys;        /* array of CFStringRef's */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("List keys in configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFArrayRef              subKeys;                        /* array of CFStringRef's */
 
        *listRef = NULL;
        *listLen = 0;
@@ -186,25 +172,22 @@ _configlist(mach_port_t                   server,
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex != 0, &subKeys);
-       CFRelease(key);
        if (*sc_status != kSCStatusOK) {
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /* serialize the list of keys */
@@ -212,8 +195,11 @@ _configlist(mach_port_t                    server,
        CFRelease(subKeys);
        if (!ok) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
index 02ecc715d21e2005ed50db31b8382be7432b68d5..c383da6ba5f987de63121471fbce93476c402278 100644 (file)
@@ -40,10 +40,8 @@ __private_extern__
 int
 __SCDynamicStoreLock(SCDynamicStoreRef store, Boolean recursive)
 {
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        serverSessionRef                mySession;
-
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreLock:"));
+       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession;         /* you must have an open session to play */
@@ -100,11 +98,6 @@ _configlock(mach_port_t server, int *sc_status)
 {
        serverSessionRef        mySession = getSession(server);
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Lock configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                return KERN_SUCCESS;
@@ -112,7 +105,6 @@ _configlock(mach_port_t server, int *sc_status)
 
        *sc_status = __SCDynamicStoreLock(mySession->store, FALSE);
        if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  SCDynamicStoreLock(): %s"), SCErrorString(*sc_status));
                return KERN_SUCCESS;
        }
 
index 892d5426adf7cebe6c657f2fd250cbf94794a0c8..e4e0dea332ffb3f5d566ae05264a608dd17335c9 100644 (file)
@@ -41,11 +41,6 @@ __SCDynamicStoreNotifyValue(SCDynamicStoreRef store, CFStringRef key, Boolean in
        Boolean                         newValue        = FALSE;
        CFDataRef                       value;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -102,34 +97,29 @@ _confignotify(mach_port_t          server,
              int                       *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Notify key in configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreNotifyValue(mySession->store, key, FALSE);
-       CFRelease(key);
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
index 82630c9f77247217070c01e15bf02a63d84fc9cb..facaf7e27372a4ab6e9660872f168070e370c48a 100644 (file)
@@ -39,11 +39,6 @@ __private_extern__
 int
 __SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
 {
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreOpen:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  name = %@"), name);
-       }
-
        /*
         * allocate and initialize a new session
         */
@@ -85,41 +80,66 @@ kern_return_t
 _configopen(mach_port_t                        server,
            xmlData_t                   nameRef,                /* raw XML bytes */
            mach_msg_type_number_t      nameLen,
+           xmlData_t                   optionsRef,             /* raw XML bytes */
+           mach_msg_type_number_t      optionsLen,
            mach_port_t                 *newServer,
            int                         *sc_status)
 {
-       kern_return_t           status;
-       serverSessionRef        mySession, newSession;
-       CFStringRef             name;           /* name (un-serialized) */
-       mach_port_t             oldNotify;
-       CFStringRef             sessionKey;
-       CFDictionaryRef         info;
-       CFMutableDictionaryRef  newInfo;
-       CFMachPortRef           mp;
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Open new session."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFDictionaryRef                 info;
+       CFMachPortRef                   mp;
+       serverSessionRef                mySession;
+       CFStringRef                     name            = NULL; /* name (un-serialized) */
+       CFMutableDictionaryRef          newInfo;
+       serverSessionRef                newSession;
+       mach_port_t                     oldNotify;
+       CFDictionaryRef                 options         = NULL; /* options (un-serialized) */
+       CFStringRef                     sessionKey;
+       kern_return_t                   status;
+       SCDynamicStorePrivateRef        storePrivate;
+       CFBooleanRef                    useSessionKeys  = NULL;
 
        /* un-serialize the name */
        if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(name)) {
-               CFRelease(name);
                *sc_status = kSCStatusInvalidArgument;
-               return KERN_SUCCESS;
+               goto done;
+       }
+
+       if (optionsRef && (optionsLen > 0)) {
+               /* un-serialize the [session] options */
+               if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) {
+                       *sc_status = kSCStatusFailed;
+                       goto done;
+               }
+
+               if (!isA_CFDictionary(options)) {
+                       *sc_status = kSCStatusInvalidArgument;
+                       goto done;
+               }
+
+               /*
+                * [pre-]process any provided options
+                */
+               useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys);
+               if (useSessionKeys != NULL) {
+                       if (!isA_CFBoolean(useSessionKeys)) {
+                               *sc_status = kSCStatusInvalidArgument;
+                               goto done;
+                       }
+               }
        }
 
        mySession = getSession(server);
        if (mySession->store) {
-               CFRelease(name);
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  Sorry, this session is already open."));
+#ifdef DEBUG
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen(): session is already open."));
+#endif /* DEBUG */
                *sc_status = kSCStatusFailed;   /* you can't re-open an "open" session */
-               return KERN_SUCCESS;
+               goto done;
        }
 
        /* Create the server port for this session */
@@ -150,11 +170,19 @@ _configopen(mach_port_t                   server,
        }
 
        *sc_status = __SCDynamicStoreOpen(&newSession->store, name);
+       storePrivate = (SCDynamicStorePrivateRef)newSession->store;
 
        /*
         * Make the server port accessible to the framework routines.
         */
-       ((SCDynamicStorePrivateRef)newSession->store)->server = *newServer;
+       storePrivate->server = *newServer;
+
+       /*
+        * Process any provided [session] options
+        */
+       if (useSessionKeys != NULL) {
+               storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys);
+       }
 
        /* Request a notification when/if the client dies */
        status = mach_port_request_notification(mach_task_self(),
@@ -165,17 +193,18 @@ _configopen(mach_port_t                   server,
                                                MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                                &oldNotify);
        if (status != KERN_SUCCESS) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
-               CFRelease(name);
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_configopen() mach_port_request_notification() failed: %s"), mach_error_string(status));
                cleanupSession(*newServer);
                *newServer = MACH_PORT_NULL;
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
+#ifdef DEBUG
        if (oldNotify != MACH_PORT_NULL) {
-               SCLog(_configd_verbose, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
+               SCLog(TRUE, LOG_ERR, CFSTR("_configopen(): why is oldNotify != MACH_PORT_NULL?"));
        }
+#endif /* DEBUG */
 
        /*
         * Save the name of the calling application / plug-in with the session data.
@@ -191,10 +220,13 @@ _configopen(mach_port_t                   server,
                                                    &kCFTypeDictionaryValueCallBacks);
        }
        CFDictionarySetValue(newInfo, kSCDName, name);
-       CFRelease(name);
        CFDictionarySetValue(sessionData, sessionKey, newInfo);
        CFRelease(newInfo);
        CFRelease(sessionKey);
 
+    done :
+
+       if (name)       CFRelease(name);
+       if (options)    CFRelease(options);
        return KERN_SUCCESS;
 }
index 0b0ad14c585c71c369c9211b132f567ffae09be6..d3bcb0034b7065d081c19bdb999a7272325a1b6d 100644 (file)
@@ -44,11 +44,6 @@ __SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key, Boolean in
        CFMutableDictionaryRef          newDict;
        CFStringRef                     sessionKey;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key      = %@"), key);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -141,34 +136,30 @@ _configremove(mach_port_t         server,
              int                       *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Remove key from configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key, FALSE);
-       CFRelease(key);
+
+    done :
+
+       if (key)        CFRelease(key);
 
        return KERN_SUCCESS;
 }
index 08747c313418daef826671a90ad06ade3ba4ae5a..2cd2ce5acb1d3b55aa1b61909dfec84c01655419 100644 (file)
@@ -49,24 +49,15 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
        CFStringRef                     sessionKey;
        CFStringRef                     storeSessionKey;
 
-       if (_configd_verbose) {
-               CFPropertyListRef       val;
-
-               (void) _SCUnserialize(&val, value, NULL, NULL);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key          = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  value        = %@"), val);
-               CFRelease(val);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
 
        if (_configd_trace) {
                SCTrace(TRUE, _configd_trace,
-                       CFSTR("%s : %5d : %@\n"),
-                       internal ? "*set   " : "set    ",
+                       CFSTR("%s%s : %5d : %@\n"),
+                       internal ? "*set " : "set  ",
+                       storePrivate->useSessionKeys ? "t " : "  ",
                        storePrivate->server,
                        key);
        }
@@ -101,24 +92,91 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
        newEntry = !CFDictionaryContainsKey(newDict, kSCDData);
        CFDictionarySetValue(newDict, kSCDData, value);
 
-       /*
-        * 4. Since we are updating this key we need to check and, if
-        *    necessary, remove the indication that this key is on
-        *    another session's remove-on-close list.
-        */
        sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
-       if (CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) &&
-           !CFEqual(sessionKey, storeSessionKey)) {
-               CFStringRef     removedKey;
-
-               /* We are no longer a session key! */
-               CFDictionaryRemoveValue(newDict, kSCDSession);
 
-               /* add this session key to the (session) removal list */
-               removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key);
-               CFSetAddValue(removedSessionKeys, removedKey);
-               CFRelease(removedKey);
+       /*
+        * 4. Manage per-session keys.
+        */
+       if (storePrivate->useSessionKeys) {
+               if (newEntry) {
+                       CFArrayRef              keys;
+                       CFMutableDictionaryRef  newSession;
+                       CFMutableArrayRef       newKeys;
+                       CFDictionaryRef         session;
+
+                       /*
+                        * Add this key to my list of per-session keys
+                        */
+                       session = CFDictionaryGetValue(sessionData, sessionKey);
+                       keys = CFDictionaryGetValue(session, kSCDSessionKeys);
+                       if ((keys == NULL) ||
+                           (CFArrayGetFirstIndexOfValue(keys,
+                                                        CFRangeMake(0, CFArrayGetCount(keys)),
+                                                        key) == kCFNotFound)) {
+                               /*
+                                * if no session keys defined "or" keys defined but not
+                                * this one...
+                                */
+                               if (keys != NULL) {
+                                       /* this is the first session key */
+                                       newKeys = CFArrayCreateMutableCopy(NULL, 0, keys);
+                               } else {
+                                       /* this is an additional session key */
+                                       newKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+                               }
+                               CFArrayAppendValue(newKeys, key);
+
+                               /* update session dictionary */
+                               newSession = CFDictionaryCreateMutableCopy(NULL, 0, session);
+                               CFDictionarySetValue(newSession, kSCDSessionKeys, newKeys);
+                               CFRelease(newKeys);
+                               CFDictionarySetValue(sessionData, sessionKey, newSession);
+                               CFRelease(newSession);
+                       }
+
+                       /*
+                        * Mark the key as a "session" key and track the creator.
+                        */
+                       CFDictionarySetValue(newDict, kSCDSession, sessionKey);
+               } else {
+                       /*
+                        * Since we are using per-session keys and this key already
+                        * exists, check if it was created by "our" session
+                        */
+                       dict = CFDictionaryGetValue(storeData, key);
+                       if (!CFDictionaryGetValueIfPresent(dict, kSCDSession, (void *)&storeSessionKey) ||
+                           !CFEqual(sessionKey, storeSessionKey)) {
+                               /*
+                                * if the key exists and is not a session key or
+                                * if the key exists it's not "our" session.
+                                */
+                               sc_status = kSCStatusKeyExists;
+                               CFRelease(sessionKey);
+                               CFRelease(newDict);
+                               goto done;
+                       }
+               }
+       } else {
+               /*
+               * Since we are updating this key we need to check and, if
+               * necessary, remove the indication that this key is on
+               * another session's remove-on-close list.
+               */
+               if (!newEntry &&
+                   CFDictionaryGetValueIfPresent(newDict, kSCDSession, (void *)&storeSessionKey) &&
+                   !CFEqual(sessionKey, storeSessionKey)) {
+                       CFStringRef     removedKey;
+
+                       /* We are no longer a session key! */
+                       CFDictionaryRemoveValue(newDict, kSCDSession);
+
+                       /* add this session key to the (session) removal list */
+                       removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), storeSessionKey, key);
+                       CFSetAddValue(removedSessionKeys, removedKey);
+                       CFRelease(removedKey);
+               }
        }
+
        CFRelease(sessionKey);
 
        /*
@@ -152,6 +210,8 @@ __SCDynamicStoreSetValue(SCDynamicStoreRef store, CFStringRef key, CFDataRef val
         */
        CFSetAddValue(changedKeys, key);
 
+    done :
+
        /*
         * 8. Release our lock.
         */
@@ -172,45 +232,39 @@ _configset(mach_port_t                    server,
           int                          *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-       CFDataRef               data;           /* data (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Set key to configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
-       *sc_status = kSCStatusOK;
+       CFDataRef               data            = NULL; /* data (un-serialized) */
+       CFStringRef             key             = NULL; /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-       } else if (!isA_CFString(key)) {
+               goto done;
+       }
+
+       if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
+               goto done;
        }
 
        /* un-serialize the data */
        if (!_SCUnserializeData(&data, (void *)dataRef, dataLen)) {
                *sc_status = kSCStatusFailed;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-       }
-
-       if (*sc_status != kSCStatusOK) {
-               if (key)        CFRelease(key);
-               if (data)       CFRelease(data);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreSetValue(mySession->store, key, data, FALSE);
        *newInstance = 0;
 
-       CFRelease(key);
-       CFRelease(data);
+    done :
 
+       if (key)        CFRelease(key);
+       if (data)       CFRelease(data);
        return KERN_SUCCESS;
 }
 
@@ -271,17 +325,6 @@ __SCDynamicStoreSetMultiple(SCDynamicStoreRef store, CFDictionaryRef keysToSet,
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
        int                             sc_status       = kSCStatusOK;
 
-       if (_configd_verbose) {
-               CFDictionaryRef expDict;
-
-               expDict = keysToSet ? _SCUnserializeMultiple(keysToSet) : NULL;
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetMultiple:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToSet    = %@"), expDict);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToRemove = %@"), keysToRemove);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keysToNotify = %@"), keysToNotify);
-               if (expDict) CFRelease(expDict);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -349,24 +392,21 @@ _configset_m(mach_port_t          server,
             mach_msg_type_number_t     notifyLen,
             int                        *sc_status)
 {
-       serverSessionRef        mySession = getSession(server);
-       CFDictionaryRef         dict    = NULL;         /* key/value dictionary (un-serialized) */
-       CFArrayRef              remove  = NULL;         /* keys to remove (un-serialized) */
-       CFArrayRef              notify  = NULL;         /* keys to notify (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Set/remove/notify keys to configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
-       *sc_status = kSCStatusOK;
+       CFDictionaryRef         dict            = NULL;         /* key/value dictionary (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
+       CFArrayRef              notify          = NULL;         /* keys to notify (un-serialized) */
+       CFArrayRef              remove          = NULL;         /* keys to remove (un-serialized) */
 
        if (dictRef && (dictLen > 0)) {
                /* un-serialize the key/value pairs to set */
                if (!_SCUnserialize((CFPropertyListRef *)&dict, NULL, (void *)dictRef, dictLen)) {
                        *sc_status = kSCStatusFailed;
-               } else if (!isA_CFDictionary(dict)) {
+                       goto done;
+               }
+
+               if (!isA_CFDictionary(dict)) {
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
@@ -374,8 +414,12 @@ _configset_m(mach_port_t           server,
                /* un-serialize the keys to remove */
                if (!_SCUnserialize((CFPropertyListRef *)&remove, NULL, (void *)removeRef, removeLen)) {
                        *sc_status = kSCStatusFailed;
-               } else if (!isA_CFArray(remove)) {
+                       goto done;
+               }
+
+               if (!isA_CFArray(remove)) {
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
@@ -383,17 +427,18 @@ _configset_m(mach_port_t          server,
                /* un-serialize the keys to notify */
                if (!_SCUnserialize((CFPropertyListRef *)&notify, NULL, (void *)notifyRef, notifyLen)) {
                        *sc_status = kSCStatusFailed;
-               } else if (!isA_CFArray(notify)) {
+                       goto done;
+               }
+
+               if (!isA_CFArray(notify)) {
                        *sc_status = kSCStatusInvalidArgument;
+                       goto done;
                }
        }
 
        if (!mySession) {
                /* you must have an open session to play */
                *sc_status = kSCStatusNoStoreSession;
-       }
-
-       if (*sc_status != kSCStatusOK) {
                goto done;
        }
 
index 8c62cf447a663f5d94edb02a3b842a8057d1db95..d35842085189f1f1599e436ab3aab156bace4a7a 100644 (file)
@@ -42,11 +42,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
        int                             sc_status;
        CFDataRef                       value;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreTouchValue:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key = %@"), key);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -74,7 +69,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
                        /* store entry does not exist, create */
 
                        now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  new time stamp = %@"), now);
                        (void) _SCSerialize(now, &value, NULL, NULL);
                        CFRelease(now);
                        break;
@@ -85,13 +79,12 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
 
                        /* store entry exists */
 
-                       (void) _SCUnserialize((CFPropertyListRef *)&now, value, NULL, NULL);
+                       (void) _SCUnserialize((CFPropertyListRef *)&now, value, NULL, 0);
                        if (isA_CFDate(now)) {
                                /* the value is a CFDate, update the time stamp */
                                CFRelease(now);
                                CFRelease(value);
                                now = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
-                               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  new time stamp = %@"), now);
                                (void) _SCSerialize(now, &value, NULL, NULL);
                        } /* else, we'll just save the data (again) to bump the instance */
                        CFRelease(now);
@@ -99,7 +92,6 @@ __SCDynamicStoreTouchValue(SCDynamicStoreRef store, CFStringRef key)
                        break;
                }
                default :
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreCopyValue(): %s"), SCErrorString(sc_status));
                        goto done;
        }
 
@@ -125,34 +117,29 @@ _configtouch(mach_port_t          server,
             int                        *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Touch key in configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreTouchValue(mySession->store, key);
-       CFRelease(key);
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
index c00fa5d445c162ff7398c384b9bb5e8bed588221..21d08158125c61831d26a02e7227cfa9ba0f1d3e 100644 (file)
@@ -218,7 +218,7 @@ _cleanupRemovedSessionKeys(const void *value, void *context)
        i = CFArrayGetFirstIndexOfValue(sessionKeys,
                                        CFRangeMake(0, CFArrayGetCount(sessionKeys)),
                                        key);
-       if (i == -1) {
+       if (i == kCFNotFound) {
                /* if this session key has already been removed */
                goto done;
        }
@@ -252,10 +252,8 @@ __private_extern__
 int
 __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
 {
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        serverSessionRef                mySession;
-
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreUnlock:"));
+       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession;         /* you must have an open session to play */
@@ -284,13 +282,6 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
        CFSetRemoveAllValues       (deferredRemovals_s);
        CFSetRemoveAllValues       (removedSessionKeys_s);
 
-#ifdef DEBUG
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys I changed           = %@"), changedKeys);
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys flagged for removal = %@"), deferredRemovals);
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("keys I'm watching        = %@"), storePrivate->keys);
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("patterns I'm watching    = %@"), storePrivate->patterns);
-#endif /* DEBUG */
-
        /*
         * push notifications to any session watching those keys which
         * were recently changed.
@@ -308,10 +299,6 @@ __SCDynamicStoreUnlock(SCDynamicStoreRef store, Boolean recursive)
        CFSetApplyFunction(removedSessionKeys, _cleanupRemovedSessionKeys, NULL);
        CFSetRemoveAllValues(removedSessionKeys);
 
-#ifdef DEBUG
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("sessions to notify = %@"), needsNotification);
-#endif /* DEBUG */
-
        /* Remove the "locked" run loop source for this port */
        mySession = getSession(storePrivate->server);
        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mySession->serverRunLoopSource, CFSTR("locked"));
@@ -329,11 +316,6 @@ _configunlock(mach_port_t server, int *sc_status)
 {
        serverSessionRef        mySession = getSession(server);
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Unlock configuration database."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                return KERN_SUCCESS;
@@ -341,7 +323,6 @@ _configunlock(mach_port_t server, int *sc_status)
 
        *sc_status = __SCDynamicStoreUnlock(mySession->store, FALSE);
        if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreUnlock(): %s"), SCErrorString(*sc_status));
                return KERN_SUCCESS;
        }
 
index 55a6ec2b46234b0305aedb03694bcb9b9e2ff30c..27c6a88db1164ebd4e48c8a2c27540bc5ab795c0 100644 (file)
@@ -60,12 +60,6 @@ __SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean
        CFNumberRef                     sessionNum      = NULL;
        SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)store;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreAddWatchedKey:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -131,35 +125,30 @@ _notifyadd(mach_port_t                    server,
           int                          *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Add notification key for this session."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFStringRef             key             = NULL; /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex != 0, FALSE);
-       CFRelease(key);
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
 
@@ -231,12 +220,6 @@ __SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CF
        updateKeysContext               myContext;
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreSetNotificationKeys:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  keys     = %@"), keys);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  patterns = %@"), patterns);
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -292,15 +275,10 @@ _notifyset(mach_port_t                    server,
           int                          *sc_status
 )
 {
-       serverSessionRef        mySession       = getSession(server);
        CFArrayRef              keys            = NULL; /* key (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
        CFArrayRef              patterns        = NULL; /* patterns (un-serialized) */
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Add notification key for this session."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        *sc_status = kSCStatusOK;
 
        if (keysRef && (keysLen > 0)) {
index 66673a38a131b4e60be7ed198c4bc1f2495df4c4..06194ed8eebcbef7936c698db2e46338ffca8cb6 100644 (file)
@@ -43,12 +43,6 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
 {
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyCancel:"));
-
-       if (!store) {
-               return kSCStatusNoStoreSession; /* you must have an open session to play */
-       }
-
        /*
         * cleanup any mach port based notifications.
         */
@@ -61,7 +55,7 @@ __SCDynamicStoreNotifyCancel(SCDynamicStoreRef store)
         * cleanup any file based notifications.
         */
        if (storePrivate->notifyFile >= 0) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  closing (notification) fd %d"), storePrivate->notifyFile);
+               // close (notification) fd
                (void) close(storePrivate->notifyFile);
                storePrivate->notifyFile = -1;
        }
@@ -103,20 +97,11 @@ _notifycancel(mach_port_t  server,
 {
        serverSessionRef        mySession = getSession(server);
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Cancel requested notifications."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                return KERN_SUCCESS;
        }
 
        *sc_status = __SCDynamicStoreNotifyCancel(mySession->store);
-       if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreNotifyCancel(): %s"), SCErrorString(*sc_status));
-       }
-
        return KERN_SUCCESS;
 }
index 80be21354f860747ee7d750f2e5761d328720fbd..9b2c902be2b66dcbf612ea322b51f7d426bf967a 100644 (file)
@@ -43,8 +43,6 @@ __SCDynamicStoreCopyNotifiedKeys(SCDynamicStoreRef store, CFArrayRef *notifierKe
        CFDictionaryRef                 info;
        CFMutableDictionaryRef          newInfo;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreCopyNotifiedKeys:"));
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -87,11 +85,6 @@ _notifychanges(mach_port_t                   server,
        CFArrayRef              notifierKeys;   /* array of CFStringRef's */
        Boolean                 ok;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("List notification keys which have changed."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
-
        *listRef = NULL;
        *listLen = 0;
 
index 9463d395a89af5d6f2c511ca7d9d2c4c41e93b3d..adc4676200bc8fae2539d84d934a904eeac54f54 100644 (file)
@@ -44,12 +44,6 @@ __SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boole
        CFNumberRef                     sessionNum;
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveWatchedKey:"));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  key     = %@"), key);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  isRegex = %s"), isRegex ? "TRUE" : "FALSE");
-       }
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -107,38 +101,33 @@ _notifyremove(mach_port_t         server,
              int                       *sc_status
 )
 {
-       serverSessionRef        mySession = getSession(server);
-       CFStringRef             key;            /* key  (un-serialized) */
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Remove notification key for this session."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-       }
+       CFStringRef             key             = NULL;         /* key  (un-serialized) */
+       serverSessionRef        mySession       = getSession(server);
 
        /* un-serialize the key */
        if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
                *sc_status = kSCStatusFailed;
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!isA_CFString(key)) {
                *sc_status = kSCStatusInvalidArgument;
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
-               CFRelease(key);
-               return KERN_SUCCESS;
+               goto done;
        }
 
        *sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store,
                                                      key,
                                                      isRegex != 0,
                                                      FALSE);
-       CFRelease(key);
 
+    done :
+
+       if (key)        CFRelease(key);
        return KERN_SUCCESS;
 }
 
index 4f6b317899bfba2512a5dd7c7cf41a239d393754..6a11e21649784d6f20df0cc1e5e25058e7a775fb 100644 (file)
@@ -52,8 +52,6 @@ __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef        store,
        CFStringRef                     sessionKey;
        CFDictionaryRef                 info;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyFileDescriptor:"));
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -64,7 +62,7 @@ __SCDynamicStoreNotifyFileDescriptor(SCDynamicStoreRef        store,
        }
 
        if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-               SCLog(_configd_verbose, LOG_NOTICE, CFSTR("socket: %s"), strerror(errno));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("__SCDynamicStoreNotifyFileDescriptor socket() failed: %s"), strerror(errno));
                return kSCStatusFailed;
        }
 
@@ -100,31 +98,27 @@ _notifyviafd(mach_port_t           server,
             int                        *sc_status
 )
 {
-       kern_return_t           status;
-       serverSessionRef        mySession = getSession(server);
-       SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)mySession->store;
-       struct sockaddr_un      un;
-       int                     sock;
-       int                     bufSiz  = sizeof(storePrivate->notifyFileIdentifier);
-       int                     nbioYes = 1;
-
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Send message via UNIX domain socket when a notification key changes."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  path   = %s"), pathRef);
-       }
+       int                             bufSiz;
+       serverSessionRef                mySession       = getSession(server);
+       int                             nbioYes;
+       int                             sock;
+       kern_return_t                   status;
+       SCDynamicStorePrivateRef        storePrivate    = (SCDynamicStorePrivateRef)mySession->store;
+       struct sockaddr_un              un;
 
        /*
         * if socket currently open, close it!
         */
        /* validate the UNIX domain socket path */
        if (pathLen > (sizeof(un.sun_path) - 1)) {
-               SCLog(_configd_verbose, LOG_NOTICE, CFSTR("domain socket path length too long!"));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("_notifyviafd(): domain socket path length too long!"));
                status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen);
+#ifdef DEBUG
                if (status != KERN_SUCCESS) {
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd vm_deallocate() failed: %s"), mach_error_string(status));
                        /* non-fatal???, proceed */
                }
+#endif /* DEBUG */
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
@@ -134,10 +128,12 @@ _notifyviafd(mach_port_t          server,
        bcopy(pathRef, un.sun_path, pathLen);
        un.sun_path[pathLen] = '\0';
        status = vm_deallocate(mach_task_self(), (vm_address_t)pathRef, pathLen);
+#ifdef DEBUG
        if (status != KERN_SUCCESS) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd vm_deallocate() failed: %s"), mach_error_string(status));
                /* non-fatal???, proceed */
        }
+#endif /* DEBUG */
 
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
@@ -154,7 +150,7 @@ _notifyviafd(mach_port_t            server,
 
        /* establish the connection, get ready for a read() */
        if (connect(sock, (struct sockaddr *)&un, sizeof(un)) == -1) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("connect: %s"), strerror(errno));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd connect() failed: %s"), strerror(errno));
                (void) close(sock);
                storePrivate->notifyStatus = NotifierNotRegistered;
                storePrivate->notifyFile   = -1;
@@ -162,18 +158,19 @@ _notifyviafd(mach_port_t          server,
                return KERN_SUCCESS;
        }
 
-       SCLog(_configd_verbose, LOG_NOTICE, CFSTR("  fd     = %d"), sock);
        (void) unlink(un.sun_path);
 
+       bufSiz = sizeof(storePrivate->notifyFileIdentifier);
        if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufSiz, sizeof(bufSiz)) < 0) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("setsockopt: %s"), strerror(errno));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd setsockopt() failed: %s"), strerror(errno));
                (void) close(sock);
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
 
+       nbioYes = 1;
        if (ioctl(sock, FIONBIO, &nbioYes) == -1) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("ioctl(,FIONBIO,): %s"), strerror(errno));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviafd ioctl(,FIONBIO,) failed: %s"), strerror(errno));
                (void) close(sock);
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
index a0d1f7b99aaf78eb1f94fff2e5d409030ea1e3e1..4b7df81d3a0b23143296d902fb72c566a5affb9b 100644 (file)
@@ -44,8 +44,6 @@ __SCDynamicStoreNotifyMachPort(SCDynamicStoreRef      store,
        CFStringRef                     sessionKey;
        CFDictionaryRef                 info;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifyMachPort:"));
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession;         /* you must have an open session to play */
        }
@@ -92,20 +90,13 @@ _notifyviaport(mach_port_t  server,
        serverSessionRef                mySession = getSession(server);
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)mySession->store;
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Send mach message when a notification key changes."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server     = %d"), server);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  port       = %d"), port);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  message id = %d"), identifier);
-       }
-
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                return KERN_SUCCESS;
        }
 
        if (storePrivate->notifyPort != MACH_PORT_NULL) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  destroying old callback mach port %d"), storePrivate->notifyPort);
+               // destroying [old] callback mach port
                (void) mach_port_destroy(mach_task_self(), storePrivate->notifyPort);
        }
 
index 7bd555345c07e2935f820b8299e89ae8702cd4ee..28aea5a3966a627701334e413bd27ee75bb53c78 100644 (file)
@@ -31,6 +31,9 @@
  * - initial revision
  */
 
+#include <unistd.h>
+#include <sys/types.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;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreNotifySignal:"));
-
        if (!store || (storePrivate->server == MACH_PORT_NULL)) {
                return kSCStatusNoStoreSession; /* you must have an open session to play */
        }
@@ -100,13 +101,6 @@ _notifyviasignal(mach_port_t       server,
        mach_port_t                     oldNotify;
 #endif /* NOTYET */
 
-       if (_configd_verbose) {
-               SCLog(TRUE, LOG_DEBUG, CFSTR("Send signal when a notification key changes."));
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  server = %d"), server);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  task   = %d"), task);
-               SCLog(TRUE, LOG_DEBUG, CFSTR("  signal = %d"), sig);
-       }
-
        status = pid_for_task(task, &pid);
        if (status != KERN_SUCCESS) {
                *sc_status = kSCStatusFailed;           /* could not determine pid for task */
@@ -160,19 +154,21 @@ _notifyviasignal(mach_port_t      server,
                                                MACH_MSG_TYPE_MAKE_SEND_ONCE,
                                                &oldNotify);
        if (status != KERN_SUCCESS) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_request_notification(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviasignal mach_port_request_notification() failed: %s"), mach_error_string(status));
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
 
+#ifdef NOTYET_DEBUG
        if (oldNotify != MACH_PORT_NULL) {
-               SCLog(_configd_verbose, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?"));
+               SCLog(TRUE, LOG_ERR, CFSTR("_notifyviasignal(): why is oldNotify != MACH_PORT_NULL?"));
        }
+#endif /* NOTYET_DEBUG */
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Adding task notification port %d to the server's port set"), task);
+       // add task notification port to the server's port set
        status = mach_port_move_member(mach_task_self(), task, server_ports);
        if (status != KERN_SUCCESS) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("mach_port_move_member(): %s"), mach_error_string(status));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("_notifyviasignal mach_port_move_member() failed: %s"), mach_error_string(status));
                *sc_status = kSCStatusFailed;
                return KERN_SUCCESS;
        }
index 60869d57891da4f05a4f07cd179d4433fd219d64..22b23261e91b0742a73c8e5e15ed70a8a4d6c758 100644 (file)
@@ -78,7 +78,7 @@ _expandStore(CFDictionaryRef storeData)
                        if (data) {
                                CFPropertyListRef       plist;
 
-                               if (!_SCUnserialize(&plist, data, NULL, NULL)) {
+                               if (!_SCUnserialize(&plist, data, NULL, 0)) {
                                        goto done;
                                }
 
@@ -130,8 +130,6 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        SCDynamicStorePrivateRef        storePrivate = (SCDynamicStorePrivateRef)store;
        CFDataRef                       xmlData;
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreSnapshot:"));
-
        /* check credentials */
 
        mySession = getSession(storePrivate->server);
@@ -151,7 +149,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
        xmlData = CFPropertyListCreateXMLData(NULL, expandedStoreData);
        CFRelease(expandedStoreData);
        if (!xmlData) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateXMLData() failed"));
                close(fd);
                return kSCStatusFailed;
        }
@@ -169,7 +167,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
 
        xmlData = CFPropertyListCreateXMLData(NULL, patternData);
        if (!xmlData) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateXMLData() failed"));
                close(fd);
                return kSCStatusFailed;
        }
@@ -187,7 +185,7 @@ __SCDynamicStoreSnapshot(SCDynamicStoreRef store)
 
        xmlData = CFPropertyListCreateXMLData(NULL, sessionData);
        if (!xmlData) {
-               SCLog(TRUE, LOG_ERR, CFSTR("CFPropertyListCreateXMLData() failed"));
+               SCLog(TRUE, LOG_ERR, CFSTR("__SCDynamicStoreSnapshot CFPropertyListCreateXMLData() failed"));
                close(fd);
                return kSCStatusFailed;
        }
@@ -205,17 +203,11 @@ _snapshot(mach_port_t server, int *sc_status)
 {
        serverSessionRef        mySession = getSession(server);
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Snapshot configuration database."));
-
        if (!mySession) {
                *sc_status = kSCStatusNoStoreSession;   /* you must have an open session to play */
                return KERN_SUCCESS;
        }
 
        *sc_status = __SCDynamicStoreSnapshot(mySession->store);
-       if (*sc_status != kSCStatusOK) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("  __SCDynamicStoreSnapshot(): %s"), SCErrorString(*sc_status));
-       }
-
        return KERN_SUCCESS;
 }
diff --git a/configd.tproj/config.defs b/configd.tproj/config.defs
deleted file mode 100644 (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@
  * 
@@ -24,6 +24,9 @@
 /*
  * 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
  *
@@ -46,6 +49,7 @@
 #include "configd_server.h"
 #include "plugin_support.h"
 
+__private_extern__
 Boolean        _configd_verbose                = FALSE;        /* TRUE if verbose logging enabled */
 
 __private_extern__
@@ -60,7 +64,7 @@ CFMutableSetRef       _plugins_verbose        = NULL;         /* bundle identifiers to enable verbos
 static CFMachPortRef termRequested     = NULL;         /* Mach port used to notify runloop of a shutdown request */
 
 
-static struct option longopts[] = {
+static const struct option longopts[] = {
 //     { "no-bundles",         no_argument,            0,      'b' },
 //     { "exclude-plugin",     required_argument,      0,      'B' },
 //     { "no-fork",            no_argument,            0,      'd' },
@@ -75,7 +79,7 @@ static struct option longopts[] = {
 static void
 usage(const char *prog)
 {
-       SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t plugin-path]\n"), prog);
+       SCPrint(TRUE, stderr, CFSTR("%s: [-d] [-v] [-V bundleID] [-b] [-B bundleID] [-t bundle-path]\n"), prog);
        SCPrint(TRUE, stderr, CFSTR("options:\n"));
        SCPrint(TRUE, stderr, CFSTR("\t-d\tdisable daemon/run in foreground\n"));
        SCPrint(TRUE, stderr, CFSTR("\t-v\tenable verbose logging\n"));
@@ -93,7 +97,7 @@ catcher(int signum)
 {
        switch (signum) {
                case SIGTERM :
-                       if (termRequested) {
+                       if (termRequested != NULL) {
                                mach_msg_empty_send_t   msg;
                                mach_msg_option_t       options;
                                kern_return_t           status;
@@ -115,6 +119,11 @@ catcher(int signum)
                                                            MACH_PORT_NULL,             /* rcv_name */
                                                            0,                          /* timeout */
                                                            MACH_PORT_NULL);            /* notify */
+                               if (status == MACH_SEND_TIMED_OUT) {
+                                       mach_msg_destroy(&msg.header);
+                               }
+                       } else {
+                               _exit(EX_OK);
                        }
                        break;
        }
@@ -126,7 +135,17 @@ catcher(int signum)
 static void
 term(CFMachPortRef port, void *msg, CFIndex size, void *info)
 {
-       server_shutdown();
+       int     status  = EX_OK;
+       Boolean wait;
+
+       wait = plugin_term(&status);
+       if (!wait) {
+               // if we are not waiting on a plugin
+               status = server_shutdown();
+               exit (status);
+       }
+
+       return;
 }
 
 
@@ -250,12 +269,15 @@ main(int argc, char * const argv[])
 {
        Boolean                 enableRestart   = (argc <= 1);  /* only if there are no arguments */
        Boolean                 forceForeground = FALSE;
+       mach_port_limits_t      limits;
        Boolean                 loadBundles     = TRUE;
        struct sigaction        nact;
        int                     opt;
        extern int              optind;
        const char              *prog           = argv[0];
+       CFRunLoopSourceRef      rls;
        mach_port_t             service_port    = MACH_PORT_NULL;
+       kern_return_t           status;
        CFStringRef             str;
        const char              *testBundle     = NULL;
 
@@ -375,40 +397,33 @@ main(int argc, char * const argv[])
                       strerror(errno));
        }
 
-       /* add signal handler to catch a SIGTERM (if dynamic store) */
-       if (testBundle == NULL) {
-               if (enableRestart) {
-                       mach_port_limits_t      limits;
-                       CFRunLoopSourceRef      rls;
-                       kern_return_t           status;
-
-                       /* add signal handler */
-                       if (sigaction(SIGTERM, &nact, NULL) == -1) {
-                               SCLog(_configd_verbose, LOG_ERR,
-                                     CFSTR("sigaction(SIGTERM, ...) failed: %s"),
-                                     strerror(errno));
-                       }
+       /* add signal handler to catch a SIGTERM */
+       if (sigaction(SIGTERM, &nact, NULL) == -1) {
+               SCLog(_configd_verbose, LOG_ERR,
+                     CFSTR("sigaction(SIGTERM, ...) failed: %s"),
+                     strerror(errno));
+       }
 
-                       /* create the "shutdown requested" notification port */
-                       termRequested = CFMachPortCreate(NULL, term, NULL, NULL);
-
-                       // set queue limit
-                       limits.mpl_qlimit = 1;
-                       status = mach_port_set_attributes(mach_task_self(),
-                                                         CFMachPortGetPort(termRequested),
-                                                         MACH_PORT_LIMITS_INFO,
-                                                         (mach_port_info_t)&limits,
-                                                         MACH_PORT_LIMITS_INFO_COUNT);
-                       if (status != KERN_SUCCESS) {
-                               perror("mach_port_set_attributes");
-                       }
+       /* create the "shutdown requested" notification port */
+       termRequested = CFMachPortCreate(NULL, term, NULL, NULL);
+
+       // set queue limit
+       limits.mpl_qlimit = 1;
+       status = mach_port_set_attributes(mach_task_self(),
+                                         CFMachPortGetPort(termRequested),
+                                         MACH_PORT_LIMITS_INFO,
+                                         (mach_port_info_t)&limits,
+                                         MACH_PORT_LIMITS_INFO_COUNT);
+       if (status != KERN_SUCCESS) {
+               perror("mach_port_set_attributes");
+       }
 
-                       // add to our runloop
-                       rls = CFMachPortCreateRunLoopSource(NULL, termRequested, 0);
-                       CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
-                       CFRelease(rls);
-               }
+       // add to our runloop
+       rls = CFMachPortCreateRunLoopSource(NULL, termRequested, 0);
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
+       CFRelease(rls);
 
+       if (testBundle == NULL) {
                /* initialize primary (store management) thread */
                server_init(service_port, enableRestart);
 
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@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
+ * March 9, 2004               Allan Nathanson <ajn@apple.com>
+ * - add DNS configuration server
+ *
  * June 1, 2001                        Allan Nathanson <ajn@apple.com>
  * - public API conversion
  *
  * - initial revision
  */
 
-#include <servers/bootstrap.h>
 #include <sysexits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <servers/bootstrap.h>
 
 #include "configd.h"
 #include "configd_server.h"
 #include "notify_server.h"
 #include "session.h"
-#include "notify.h"
 
 /* MiG generated externals and functions */
-extern struct rpc_subsystem    _config_subsystem;
+extern struct mig_subsystem    _config_subsystem;
 extern boolean_t               config_server(mach_msg_header_t *, mach_msg_header_t *);
 
+#include "shared_dns_info_types.h"
+#include "dnsinfo_server.h"
+
+/* MiG generated externals and functions */
+extern struct mig_subsystem    _shared_dns_info_subsystem;
+extern boolean_t               shared_dns_info_server(mach_msg_header_t *, mach_msg_header_t *);
+
 /* configd server port (for new session requests) */
 static CFMachPortRef           configd_port            = NULL;
 
@@ -70,14 +81,11 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply)
                    (trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) {
                        thisSession->callerEUID = trailer->msgh_sender.val[0];
                        thisSession->callerEGID = trailer->msgh_sender.val[1];
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("caller has eUID = %d, eGID = %d"),
-                              thisSession->callerEUID,
-                              thisSession->callerEGID);
                } else {
                        static Boolean warned   = FALSE;
 
                        if (!warned) {
-                               SCLog(_configd_verbose, LOG_WARNING, CFSTR("caller's credentials not available."));
+                               SCLog(TRUE, LOG_WARNING, CFSTR("caller's credentials not available."));
                                warned = TRUE;
                        }
                        thisSession->callerEUID = 0;
@@ -86,30 +94,42 @@ config_demux(mach_msg_header_t *request, mach_msg_header_t *reply)
        }
 
        /*
-        * (attemp to) process configd requests.
+        * (attempt to) process SCDynamicStore requests.
         */
        processed = config_server(request, reply);
-
-       if (!processed) {
-               /*
-                * (attempt to) process (NO MORE SENDERS) notification messages.
-                */
-               processed = notify_server(request, reply);
+       if (processed) {
+               return TRUE;
        }
 
-       if (!processed) {
-               SCLog(TRUE, LOG_ERR, CFSTR("unknown message ID (%d) received"), request->msgh_id);
+       /*
+        * (attempt to) process DNS configuration requests.
+        */
+       processed = shared_dns_info_server(request, reply);
+       if (processed) {
+               return TRUE;
+       }
 
-               reply->msgh_bits        = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->msgh_bits), 0);
-               reply->msgh_remote_port = request->msgh_remote_port;
-               reply->msgh_size        = sizeof(mig_reply_error_t);    /* Minimal size */
-               reply->msgh_local_port  = MACH_PORT_NULL;
-               reply->msgh_id          = request->msgh_id + 100;
-               ((mig_reply_error_t *)reply)->NDR = NDR_record;
-               ((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID;
+       /*
+        * (attempt to) process (NO MORE SENDERS) notification messages.
+        */
+       processed = notify_server(request, reply);
+       if (processed) {
+               return TRUE;
        }
 
-       return processed;
+       /*
+        * unknown message ID, log and return an error.
+        */
+       SCLog(TRUE, LOG_ERR, CFSTR("config_demux(): unknown message ID (%d) received"), request->msgh_id);
+       reply->msgh_bits        = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->msgh_bits), 0);
+       reply->msgh_remote_port = request->msgh_remote_port;
+       reply->msgh_size        = sizeof(mig_reply_error_t);    /* Minimal size */
+       reply->msgh_local_port  = MACH_PORT_NULL;
+       reply->msgh_id          = request->msgh_id + 100;
+       ((mig_reply_error_t *)reply)->NDR = NDR_record;
+       ((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID;
+
+       return FALSE;
 }
 
 
@@ -123,18 +143,26 @@ configdCallback(CFMachPortRef port, void *msg, CFIndex size, void *info)
        mig_reply_error_t *     bufRequest      = msg;
        uint32_t                bufReply_q[MACH_MSG_BUFFER_SIZE/sizeof(uint32_t)];
        mig_reply_error_t *     bufReply        = (mig_reply_error_t *)bufReply_q;
+       static CFIndex          bufSize         = 0;
        mach_msg_return_t       mr;
        int                     options;
 
-       if (_config_subsystem.maxsize > sizeof(bufReply_q)) {
-               static Boolean warned = FALSE;
+       if (bufSize == 0) {
+               // get max size for MiG reply buffers
+               bufSize = _config_subsystem.maxsize;
+               if (_shared_dns_info_subsystem.maxsize > bufSize) {
+                       bufSize = _shared_dns_info_subsystem.maxsize;
+               }
 
-               if (!warned) {
-                       SCLog(_configd_verbose, LOG_NOTICE,
+               // check if our on-the-stack reply buffer will be big enough
+               if (bufSize > sizeof(bufReply_q)) {
+                       SCLog(TRUE, LOG_NOTICE,
                              CFSTR("configdCallback(): buffer size should be increased > %d"),
                              _config_subsystem.maxsize);
-                       warned = TRUE;
                }
+       }
+
+       if (bufSize > sizeof(bufReply_q)) {
                bufReply = CFAllocatorAllocate(NULL, _config_subsystem.maxsize, 0);
        }
 
@@ -206,7 +234,6 @@ __private_extern__
 boolean_t
 server_active(mach_port_t *restart_service_port)
 {
-       mach_port_t             bootstrap_port;
        char                    *service_name;
        kern_return_t           status;
 
@@ -215,14 +242,6 @@ server_active(mach_port_t *restart_service_port)
                service_name = SCD_SERVER;
        }
 
-       /* Getting bootstrap server port */
-       status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
-       if (status != KERN_SUCCESS) {
-               fprintf(stderr, "task_get_bootstrap_port(): %s\n",
-                       mach_error_string(status));
-               exit (EX_UNAVAILABLE);
-       }
-
        /* Check "configd" server status */
        status = bootstrap_check_in(bootstrap_port, service_name, restart_service_port);
        switch (status) {
@@ -253,24 +272,17 @@ __private_extern__
 void
 server_init(mach_port_t        restart_service_port, Boolean enableRestart)
 {
-       mach_port_t             bootstrap_port;
        CFRunLoopSourceRef      rls;
        char                    *service_name;
        mach_port_t             service_port    = restart_service_port;
        kern_return_t           status;
+       mach_port_t             unpriv_bootstrap_port;
 
        service_name = getenv("SCD_SERVER");
        if (!service_name) {
                service_name = SCD_SERVER;
        }
 
-       /* Getting bootstrap server port */
-       status = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
-       if (status != KERN_SUCCESS) {
-               SCLog(TRUE, LOG_ERR, CFSTR("task_get_bootstrap_port(): %s"), mach_error_string(status));
-               exit (EX_UNAVAILABLE);
-       }
-
        if (service_port == MACH_PORT_NULL) {
                mach_port_t     service_send_port;
 
@@ -294,7 +306,7 @@ server_init(mach_port_t     restart_service_port, Boolean enableRestart)
                                                                         FALSE,         /* not onDemand == restart now */
                                                                         &priv_bootstrap_port);
                                        if (status != BOOTSTRAP_SUCCESS) {
-                                               SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_create_server() failed: status=%d"), status);
+                                               SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_create_server() failed: status=%d"), status);
                                                exit (EX_UNAVAILABLE);
                                        }
                                } else {
@@ -303,13 +315,13 @@ server_init(mach_port_t   restart_service_port, Boolean enableRestart)
 
                                status = bootstrap_create_service(priv_bootstrap_port, service_name, &service_send_port);
                                if (status != BOOTSTRAP_SUCCESS) {
-                                       SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_create_service() failed: status=%d"), status);
+                                       SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_create_service() failed: status=%d"), status);
                                        exit (EX_UNAVAILABLE);
                                }
 
                                status = bootstrap_check_in(priv_bootstrap_port, service_name, &service_port);
                                if (status != BOOTSTRAP_SUCCESS) {
-                                       SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_check_in() failed: status=%d"), status);
+                                       SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_check_in() failed: status=%d"), status);
                                        exit (EX_UNAVAILABLE);
                                }
                                break;
@@ -318,22 +330,22 @@ server_init(mach_port_t   restart_service_port, Boolean enableRestart)
                                SCLog(TRUE, LOG_ERR, CFSTR("'%s' server already active"), service_name);
                                exit (EX_UNAVAILABLE);
                        default :
-                               SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_check_in() failed: status=%d"), status);
+                               SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_check_in() failed: status=%d"), status);
                                exit (EX_UNAVAILABLE);
                }
 
        }
 
        /* we don't want to pass our priviledged bootstrap port along to any spawned helpers so... */
-       status = bootstrap_unprivileged(priv_bootstrap_port, &bootstrap_port);
+       status = bootstrap_unprivileged(priv_bootstrap_port, &unpriv_bootstrap_port);
        if (status != BOOTSTRAP_SUCCESS) {
-               SCLog(TRUE, LOG_ERR, CFSTR("bootstrap_unprivileged() failed: status=%d"), status);
+               SCLog(TRUE, LOG_ERR, CFSTR("server_init bootstrap_unprivileged() failed: status=%d"), status);
                exit (EX_UNAVAILABLE);
        }
 
-       status = task_set_bootstrap_port(mach_task_self(), bootstrap_port);
+       status = task_set_bootstrap_port(mach_task_self(), unpriv_bootstrap_port);
        if (status != BOOTSTRAP_SUCCESS) {
-               SCLog(TRUE, LOG_ERR, CFSTR("task_set_bootstrap_port(): %s"),
+               SCLog(TRUE, LOG_ERR, CFSTR("server_init task_set_bootstrap_port(): %s"),
                        mach_error_string(status));
                exit (EX_UNAVAILABLE);
        }
@@ -361,7 +373,7 @@ server_init(mach_port_t     restart_service_port, Boolean enableRestart)
 
 
 __private_extern__
-void
+int
 server_shutdown()
 {
        char            *service_name;
@@ -373,7 +385,7 @@ server_shutdown()
         *       logging thread lock is held.
         */
        if ((priv_bootstrap_port == MACH_PORT_NULL) || (configd_port == NULL)) {
-               return;
+               return EX_OK;
        }
 
        service_name = getenv("SCD_SERVER");
@@ -401,10 +413,10 @@ server_shutdown()
                                fprintf(stderr,  "bootstrap_register() failed: status=%d\n", status);
                                fflush (stderr);
                        }
-                       exit (EX_UNAVAILABLE);
+                       return EX_UNAVAILABLE;
        }
 
-       exit(EX_OK);
+       return EX_OK;
 }
 
 
index af388a11764e0a3a7e21806f7fb18c4078ec5934..4784de975035c544f103ec29a2635f7b65bd188d 100644 (file)
@@ -36,9 +36,7 @@
 
 #include <sys/cdefs.h>
 #include <mach/mach.h>
-
-#include <CoreFoundation/CFRunLoop.h>
-#include <CoreFoundation/CFMachPort.h>
+#include <CoreFoundation/CoreFoundation.h>
 
 __BEGIN_DECLS
 
@@ -52,7 +50,7 @@ boolean_t     server_active   (mach_port_t            *service_port);
 void           server_init     (mach_port_t            service_port,
                                 Boolean                enableRestart);
 
-void           server_shutdown ();
+int            server_shutdown ();
 
 void           server_loop     ();
 
@@ -62,6 +60,8 @@ kern_return_t _snapshot       (mach_port_t            server,
 kern_return_t  _configopen     (mach_port_t            server,
                                 xmlData_t              nameRef,
                                 mach_msg_type_number_t nameLen,
+                                xmlData_t              optionsRef,
+                                mach_msg_type_number_t optionsLen,
                                 mach_port_t            *newServer,
                                 int                    *sc_status);
 
diff --git a/configd.tproj/h.template b/configd.tproj/h.template
deleted file mode 100644 (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@
  * 
@@ -30,7 +30,6 @@
 
 #include "configd.h"
 #include "session.h"
-#include "notify.h"
 
 __private_extern__
 boolean_t
@@ -71,8 +70,8 @@ notify_server(mach_msg_header_t *request, mach_msg_header_t *reply)
        }
 
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("HELP!, Received notification: port=%d, msgh_id=%d"),
-              Request->not_header.msgh_local_port,
-              Request->not_header.msgh_id);
+             Request->not_header.msgh_local_port,
+             Request->not_header.msgh_id);
 
        Reply->NDR     = NDR_record;
        Reply->RetCode = MIG_BAD_ID;
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) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern(): could not convert store key to C string"));
                goto done;
        }
 
@@ -108,7 +108,7 @@ identifyKeyForPattern(const void *key, void *val, void *context)
                        char    reErrBuf[256];
 
                        (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("identifyKeyForPattern regexec(): %s"), reErrBuf);
                        break;
                }
        }
@@ -173,12 +173,16 @@ patternCompile(CFStringRef pattern, regex_t *preg, CFStringRef *error)
 
                        (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
                        *error = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingASCII);
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regcomp(%s) failed: %s"), str, reErrBuf);
+#ifdef DEBUG
+                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("patternCompile regcomp(%s) failed: %s"), str, reErrBuf);
+#endif /* DEBUG */
                        ok = FALSE;
                }
        } else {
                *error = CFRetain(CFSTR("could not convert pattern to regex string"));
+#ifdef DEBUG
                SCLog(_configd_verbose, LOG_DEBUG, CFSTR("%@"), *error);
+#endif /* DEBUG */
        }
 
        if (str != str_q)       CFAllocatorDeallocate(NULL, str);
@@ -349,7 +353,7 @@ addKeyForPattern(const void *key, void *val, void *context)
        if (len > (CFIndex)sizeof(str_q))
                str = CFAllocatorAllocate(NULL, len, 0);
        if (_SC_cfstring_to_cstring(storeKey, str, len, kCFStringEncodingASCII) == NULL) {
-               SCLog(_configd_verbose, LOG_DEBUG, CFSTR("could not convert store key to C string"));
+               SCLog(TRUE, LOG_DEBUG, CFSTR("addKeyForPattern(): could not convert store key to C string"));
                goto done;
        }
 
@@ -389,7 +393,7 @@ addKeyForPattern(const void *key, void *val, void *context)
                        char    reErrBuf[256];
 
                        (void)regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
-                       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
+                       SCLog(TRUE, LOG_DEBUG, CFSTR("addKeyForPattern regexec(): %s"), reErrBuf);
                        break;
                }
        }
@@ -432,7 +436,7 @@ removeKeyFromPattern(const void *key, void *val, void *context)
        }
 
        i = CFArrayGetFirstIndexOfValue(pInfo, CFRangeMake(2, n-2), storeKey);
-       if (i == -1) {
+       if (i == kCFNotFound) {
                /* if this key wasn't matched by this pattern */
                return;
        }
index 80e5b85ad29770d8226fe92e409df3dc35565f52..266220f71be31e63388d5efb7b13ae57971309c4 100644 (file)
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
+ * October 30, 2003            Allan Nathanson <ajn@apple.com>
+ * - add plugin "stop()" function support
+ *
  * June 11, 2001               Allan Nathanson <ajn@apple.com>
  * - start using CFBundle code
  *
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <dirent.h>
+#include <sysexits.h>
 #include <unistd.h>
 #include <NSSystemDirectories.h>
 
 #include "configd.h"
+#include "configd_server.h"
 #include <SystemConfiguration/SCDPlugin.h>
 void   _SCDPluginExecInit();
 
@@ -54,128 +59,149 @@ void      _SCDPluginExecInit();
 #define        BUNDLE_DIR_EXTENSION    ".bundle"
 
 
-static CFMutableArrayRef       allBundles      = NULL;
-
-
-/* exception handling functions */
-typedef kern_return_t (*cer_func_t)            (mach_port_t            exception_port,
-                                                mach_port_t            thread,
-                                                mach_port_t            task,
-                                                exception_type_t       exception,
-                                                exception_data_t       code,
-                                                mach_msg_type_number_t codeCnt);
-
-typedef kern_return_t (*cer_state_func_t)      (mach_port_t            exception_port,
-                                                exception_type_t       exception,
-                                                exception_data_t       code,
-                                                mach_msg_type_number_t codeCnt,
-                                                int                    *flavor,
-                                                thread_state_t         old_state,
-                                                mach_msg_type_number_t old_stateCnt,
-                                                thread_state_t         new_state,
-                                                mach_msg_type_number_t *new_stateCnt);
-
-typedef kern_return_t (*cer_identity_func_t)   (mach_port_t            exception_port,
-                                                mach_port_t            thread,
-                                                mach_port_t            task,
-                                                exception_type_t       exception,
-                                                exception_data_t       code,
-                                                mach_msg_type_number_t codeCnt,
-                                                int                    *flavor,
-                                                thread_state_t         old_state,
-                                                mach_msg_type_number_t old_stateCnt,
-                                                thread_state_t         new_state,
-                                                mach_msg_type_number_t *new_stateCnt);
-
-static cer_func_t              catch_exception_raise_func          = NULL;
-static cer_state_func_t                catch_exception_raise_state_func    = NULL;
-static cer_identity_func_t     catch_exception_raise_identity_func = NULL;
-
-kern_return_t
-catch_exception_raise(mach_port_t              exception_port,
-                     mach_port_t               thread,
-                     mach_port_t               task,
-                     exception_type_t          exception,
-                     exception_data_t          code,
-                     mach_msg_type_number_t    codeCnt)
-{
-
-       if (catch_exception_raise_func == NULL) {
-               /* The user hasn't defined catch_exception_raise in their binary */
-               abort();
+typedef struct {
+       CFBundleRef                             bundle;
+       Boolean                                 loaded;
+       Boolean                                 builtin;
+       Boolean                                 verbose;
+       SCDynamicStoreBundleLoadFunction        load;
+       SCDynamicStoreBundleStartFunction       start;
+       SCDynamicStoreBundlePrimeFunction       prime;
+       SCDynamicStoreBundleStopFunction        stop;
+} *bundleInfoRef;
+
+
+// all loaded bundles
+static CFMutableArrayRef       allBundles      = NULL;
+
+// exiting bundles
+static CFMutableDictionaryRef  exiting         = NULL;
+
+// plugin CFRunLoopRef
+static CFRunLoopRef            plugin_runLoop  = NULL;
+
+
+#ifdef ppc
+//extern SCDynamicStoreBundleLoadFunction      load_ATconfig;
+//extern SCDynamicStoreBundleStopFunction      stop_ATconfig;
+#endif /* ppc */
+extern SCDynamicStoreBundleLoadFunction                load_IPMonitor;
+extern SCDynamicStoreBundlePrimeFunction       prime_IPMonitor;
+extern SCDynamicStoreBundleLoadFunction                load_InterfaceNamer;
+extern SCDynamicStoreBundleLoadFunction                load_KernelEventMonitor;
+extern SCDynamicStoreBundlePrimeFunction       prime_KernelEventMonitor;
+extern SCDynamicStoreBundleLoadFunction                load_Kicker;
+extern SCDynamicStoreBundleLoadFunction                load_LinkConfiguration;
+extern SCDynamicStoreBundleLoadFunction                load_PreferencesMonitor;
+extern SCDynamicStoreBundlePrimeFunction       prime_PreferencesMonitor;
+extern SCDynamicStoreBundleStopFunction                stop_PreferencesMonitor;
+
+
+typedef struct {
+       const CFStringRef       bundleID;
+       const void              *load;          // SCDynamicStoreBundleLoadFunction
+       const void              *start;         // SCDynamicStoreBundleStartFunction
+       const void              *prime;         // SCDynamicStoreBundlePrimeFunction
+       const void              *stop;          // SCDynamicStoreBundleStopFunction
+} builtin, *builtinRef;
+
+
+static const builtin builtin_plugins[] = {
+#ifdef ppc
+//     {
+//             CFSTR("com.apple.SystemConfiguration.ATconfig"),
+//             &load_ATconfig,
+//             NULL,
+//             NULL,
+//             &stop_ATconfig
+//     },
+#endif /* ppc */
+       {
+               CFSTR("com.apple.SystemConfiguration.IPMonitor"),
+               &load_IPMonitor,
+               NULL,
+               &prime_IPMonitor,
+               NULL
+       },
+       {
+               CFSTR("com.apple.SystemConfiguration.InterfaceNamer"),
+               &load_InterfaceNamer,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               CFSTR("com.apple.SystemConfiguration.KernelEventMonitor"),
+               &load_KernelEventMonitor,
+               NULL,
+               &prime_KernelEventMonitor,
+               NULL
+       },
+       {
+               CFSTR("com.apple.SystemConfiguration.Kicker"),
+               &load_Kicker,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               CFSTR("com.apple.SystemConfiguration.LinkConfiguration"),
+               &load_LinkConfiguration,
+               NULL,
+               NULL,
+               NULL
+       },
+       {
+               CFSTR("com.apple.SystemConfiguration.PreferencesMonitor"),
+               &load_PreferencesMonitor,
+               NULL,
+               &prime_PreferencesMonitor,
+               &stop_PreferencesMonitor
        }
-       return (*catch_exception_raise_func)(exception_port,
-                                            thread,
-                                            task,
-                                            exception,
-                                            code,
-                                            codeCnt);
-}
+};
 
 
-kern_return_t
-catch_exception_raise_state(mach_port_t                        exception_port,
-                           exception_type_t            exception,
-                           exception_data_t            code,
-                           mach_msg_type_number_t      codeCnt,
-                           int                         *flavor,
-                           thread_state_t              old_state,
-                           mach_msg_type_number_t      old_stateCnt,
-                           thread_state_t              new_state,
-                           mach_msg_type_number_t      *new_stateCnt)
+static void
+addBundle(CFBundleRef bundle)
 {
-       if (catch_exception_raise_state_func == 0) {
-               /* The user hasn't defined catch_exception_raise_state in their binary */
-               abort();
-       }
-       return (*catch_exception_raise_state_func)(exception_port,
-                                                  exception,
-                                                  code,
-                                                  codeCnt,
-                                                  flavor,
-                                                  old_state,
-                                                  old_stateCnt,
-                                                  new_state,
-                                                  new_stateCnt);
-}
+       CFDictionaryRef         bundleDict;
+       bundleInfoRef           bundleInfo;
+       
+       bundleInfo = CFAllocatorAllocate(NULL, sizeof(*bundleInfo), 0);
+       bundleInfo->bundle      = (CFBundleRef)CFRetain(bundle);
+       bundleInfo->loaded      = FALSE;
+       bundleInfo->builtin     = FALSE;
+       bundleInfo->verbose     = FALSE;
+       bundleInfo->load        = NULL;
+       bundleInfo->start       = NULL;
+       bundleInfo->prime       = NULL;
+       bundleInfo->stop        = NULL;
+       
+       bundleDict = CFBundleGetInfoDictionary(bundle);
+       if (isA_CFDictionary(bundleDict)) {
+               CFBooleanRef    bVal;
+
+               bVal = CFDictionaryGetValue(bundleDict, kSCBundleIsBuiltinKey);
+               if (isA_CFBoolean(bVal) && CFBooleanGetValue(bVal)) {
+                       bundleInfo->builtin = TRUE;
+               }
 
+               bVal = CFDictionaryGetValue(bundleDict, kSCBundleVerboseKey);
+               if (isA_CFBoolean(bVal) && CFBooleanGetValue(bVal)) {
+                       bundleInfo->verbose = TRUE;
+               }
+       }
 
-kern_return_t
-catch_exception_raise_state_identity(mach_port_t               exception_port,
-                                    mach_port_t                thread,
-                                    mach_port_t                task,
-                                    exception_type_t           exception,
-                                    exception_data_t           code,
-                                    mach_msg_type_number_t     codeCnt,
-                                    int                        *flavor,
-                                    thread_state_t             old_state,
-                                    mach_msg_type_number_t     old_stateCnt,
-                                    thread_state_t             new_state,
-                                    mach_msg_type_number_t     *new_stateCnt)
-{
-       if (catch_exception_raise_identity_func == 0) {
-               /* The user hasn't defined catch_exception_raise_identify in their binary */
-               abort();
-       }
-       return (*catch_exception_raise_identity_func)(exception_port,
-                                                     thread,
-                                                     task,
-                                                     exception,
-                                                     code,
-                                                     codeCnt,
-                                                     flavor,
-                                                     old_state,
-                                                     old_stateCnt,
-                                                     new_state,
-                                                     new_stateCnt);
+       CFArrayAppendValue(allBundles, bundleInfo);
+       return;
 }
 
 
 static CFStringRef
 shortBundleIdentifier(CFStringRef bundleID)
 {
-       CFIndex         len     = CFStringGetLength(bundleID);
-       CFRange         range;
+       CFIndex         len     = CFStringGetLength(bundleID);
+       CFRange         range;
        CFStringRef     shortID = NULL;
 
        if (CFStringFindWithOptions(bundleID,
@@ -192,137 +218,154 @@ shortBundleIdentifier(CFStringRef bundleID)
 }
 
 
-static void
-loadBundle(const void *value, void *context) {
-       CFBundleRef                             bundle          = (CFBundleRef)value;
-       CFStringRef                             bundleID        = CFBundleGetIdentifier(bundle);
-       Boolean                                 bundleExclude   = FALSE;
-       Boolean                                 bundleVerbose   = FALSE;
-       CFDictionaryRef                         dict;
-       void                                    *func;
-       SCDynamicStoreBundleLoadFunction        load;
-       Boolean                                 loaded;
-       CFIndex                                 *nLoaded        = (CFIndex *)context;
-
-       SCLog(TRUE, LOG_DEBUG, CFSTR("loading %@"), bundleID);
-
-       bundleExclude = CFSetContainsValue(_plugins_exclude, bundleID);
-       if (!bundleExclude) {
-               CFStringRef     shortID = shortBundleIdentifier(bundleID);
+static void *
+getBundleSymbol(CFBundleRef bundle, CFStringRef functionName, CFStringRef shortID)
+{
+       void    *func;
 
-               if (shortID) {
-                       bundleExclude = CFSetContainsValue(_plugins_exclude, shortID);
-                       CFRelease(shortID);
-               }
+       // search for load(), start(), prime(), stop(), ...
+       func = CFBundleGetFunctionPointerForName(bundle, functionName);
+       if (func != NULL) {
+               return func;
        }
 
-       if (bundleExclude) {
-               SCLog(TRUE,
-                     LOG_DEBUG,
-                     CFSTR("%@ load skipped"),
-                     bundleID);
-               return;
+       if (shortID != NULL) {
+               CFStringRef     altFunctionName;
+
+               // search for load_XXX(), ...
+               altFunctionName = CFStringCreateWithFormat(NULL,
+                                                   NULL,
+                                                   CFSTR("%@_%@"),
+                                                   functionName,
+                                                   shortID);
+               func = CFBundleGetFunctionPointerForName(bundle, altFunctionName);
+               CFRelease(altFunctionName);
        }
 
-       loaded = CFBundleLoadExecutable(bundle);
-       if (!loaded) {
-               SCLog(TRUE,
-                     LOG_NOTICE,
-                     CFSTR("%@ load failed"),
-                     bundleID);
-               return;
-       }
+       return func;
+}
 
-       if (!CFBundleIsExecutableLoaded(bundle)) {
-               SCLog(TRUE,
-                     LOG_NOTICE,
-                     CFSTR("%@ executable not loaded"),
-                     bundleID);
+
+static void
+loadBundle(const void *value, void *context) {
+       CFStringRef     bundleID;
+       bundleInfoRef   bundleInfo      = (bundleInfoRef)value;
+       Boolean         bundleExclude;
+       CFIndex         *nLoaded        = (CFIndex *)context;
+       CFStringRef     shortID;
+
+       bundleID = CFBundleGetIdentifier(bundleInfo->bundle);
+       if (bundleID == NULL) {
+               // sorry, no bundles without a bundle identifier
+               SCLog(TRUE, LOG_DEBUG, CFSTR("skipped %@"), bundleInfo->bundle);
                return;
        }
 
-       /* bump the count of loaded bundles */
-       *nLoaded = *nLoaded + 1;
+       shortID = shortBundleIdentifier(bundleID);
 
-       /* identify any exception handling functions */
-
-       func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise"));
-       if (func) {
-               catch_exception_raise_func = func;
+       bundleExclude = CFSetContainsValue(_plugins_exclude, bundleID);
+       if (bundleExclude) {
+               if (shortID != NULL) {
+                       bundleExclude = CFSetContainsValue(_plugins_exclude, shortID);
+               }
        }
 
-       func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise_state"));
-       if (func) {
-               catch_exception_raise_state_func = func;
+       if (bundleExclude) {
+               // sorry, this bundle has been excluded
+               SCLog(TRUE, LOG_DEBUG, CFSTR("excluded %@"), bundleID);
+               goto done;
        }
 
-       func = CFBundleGetFunctionPointerForName(bundle, CFSTR("catch_exception_raise_identity"));
-       if (func) {
-               catch_exception_raise_identity_func = func;
+       if (!bundleInfo->verbose) {
+               bundleInfo->verbose = CFSetContainsValue(_plugins_verbose, bundleID);
+               if (!bundleInfo->verbose) {
+                       if (shortID != NULL) {
+                               bundleInfo->verbose = CFSetContainsValue(_plugins_verbose, shortID);
+                       }
+               }
        }
 
-       /* if defined, call the bundles load() function */
+       if (bundleInfo->builtin) {
+               int     i;
 
-       load = CFBundleGetFunctionPointerForName(bundle, CFSTR("load"));
-       if (!load) {
-               return;
-       }
+               SCLog(TRUE, LOG_DEBUG, CFSTR("adding  %@"), bundleID);
 
-       bundleVerbose = CFSetContainsValue(_plugins_verbose, bundleID);
-       if (!bundleVerbose) {
-               CFStringRef     shortID = shortBundleIdentifier(bundleID);
+               for (i = 0; i < sizeof(builtin_plugins)/sizeof(builtin_plugins[0]); i++) {
+                       if (CFEqual(bundleID, builtin_plugins[i].bundleID)) {
+                               bundleInfo->load  = builtin_plugins[i].load;
+                               bundleInfo->start = builtin_plugins[i].start;
+                               bundleInfo->prime = builtin_plugins[i].prime;
+                               bundleInfo->stop  = builtin_plugins[i].stop;
+                               break;
+                       }
+               }
+       } else {
+               SCLog(TRUE, LOG_DEBUG, CFSTR("loading %@"), bundleID);
 
-               if (shortID) {
-                       bundleVerbose = CFSetContainsValue(_plugins_verbose, shortID);
-                       CFRelease(shortID);
+               if (!CFBundleLoadExecutable(bundleInfo->bundle)) {
+                       SCLog(TRUE, LOG_NOTICE, CFSTR("%@ load failed"), bundleID);
+                       goto done;
                }
+
+               // get bundle entry points
+               bundleInfo->load  = getBundleSymbol(bundleInfo->bundle, CFSTR("load" ), shortID);
+               bundleInfo->start = getBundleSymbol(bundleInfo->bundle, CFSTR("start"), shortID);
+               bundleInfo->prime = getBundleSymbol(bundleInfo->bundle, CFSTR("prime"), shortID);
+               bundleInfo->stop  = getBundleSymbol(bundleInfo->bundle, CFSTR("stop" ), shortID);
        }
 
-       if (!bundleVerbose) {
-               dict = CFBundleGetInfoDictionary(bundle);
-               if (isA_CFDictionary(dict)) {
-                       CFBooleanRef    bVal;
+       /* mark this bundle as having been loaded */
+       bundleInfo->loaded = TRUE;
 
-                       bVal = CFDictionaryGetValue(dict, kSCBundleVerbose);
-                       if (isA_CFBoolean(bVal) && CFBooleanGetValue(bVal)) {
-                               bundleVerbose = TRUE;
-                       }
-               }
-       }
+       /* bump the count of loaded bundles */
+       *nLoaded = *nLoaded + 1;
+
+    done :
 
-       (*load)(bundle, bundleVerbose);
+       if (shortID != NULL)    CFRelease(shortID);
        return;
 }
 
 
-static void
-startBundle(const void *value, void *context) {
-       CFBundleRef                             bundle          = (CFBundleRef)value;
-       CFURLRef                                bundleURL;
-       char                                    bundleName[MAXNAMLEN + 1];
-       char                                    bundlePath[MAXPATHLEN];
-       char                                    *cp;
-       CFDictionaryRef                         dict;
-       int                                     len;
-       Boolean                                 ok;
-       SCDynamicStoreBundleStartFunction       start;
+void
+callLoadFunction(const void *value, void *context) {
+       bundleInfoRef   bundleInfo      = (bundleInfoRef)value;
 
-       if (!CFBundleIsExecutableLoaded(bundle)) {
+       if (!bundleInfo->loaded) {
                return;
        }
 
-       start = CFBundleGetFunctionPointerForName(bundle, CFSTR("start"));
-       if (!start) {
+       if (bundleInfo->load == NULL) {
+               // if no load() function
+               return;
+       }
+
+       (*bundleInfo->load)(bundleInfo->bundle, bundleInfo->verbose);
+       return;
+}
+
+
+void
+callStartFunction(const void *value, void *context) {
+       bundleInfoRef   bundleInfo      = (bundleInfoRef)value;
+       CFURLRef        bundleURL;
+       char            bundleName[MAXNAMLEN + 1];
+       char            bundlePath[MAXPATHLEN];
+       char            *cp;
+       int             len;
+       Boolean         ok;
+
+       if (!bundleInfo->loaded) {
                return;
        }
 
-       dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle));
-       if (!dict) {
+       if (bundleInfo->start == NULL) {
+               // if no start() function
                return;
        }
 
-       bundleURL = CFBundleCopyBundleURL(bundle);
-       if (!bundleURL) {
+       bundleURL = CFBundleCopyBundleURL(bundleInfo->bundle);
+       if (bundleURL == NULL) {
                return;
        }
 
@@ -359,30 +402,209 @@ startBundle(const void *value, void *context) {
        bundleName[0] = '\0';
        (void) strncat(bundleName, cp, len);
 
-       (*start)(bundleName, bundlePath);
+       (*bundleInfo->start)(bundleName, bundlePath);
+       return;
+}
+
+
+void
+callPrimeFunction(const void *value, void *context) {
+       bundleInfoRef   bundleInfo      = (bundleInfoRef)value;
+
+       if (!bundleInfo->loaded) {
+               return;
+       }
+
+       if (bundleInfo->prime == NULL) {
+               // if no prime() function
+               return;
+       }
+
+       (*bundleInfo->prime)();
        return;
 }
 
 
 static void
-primeBundle(const void *value, void *context) {
-       CFBundleRef                             bundle          = (CFBundleRef)value;
-       SCDynamicStoreBundlePrimeFunction       prime;
+stopComplete(void *info)
+{
+       CFBundleRef             bundle          = (CFBundleRef)info;
+       CFStringRef             bundleID        = CFBundleGetIdentifier(bundle);
+       CFRunLoopSourceRef      stopRls;
+
+       SCLog(TRUE, LOG_DEBUG, CFSTR("** %@ complete (%f)"), bundleID, CFAbsoluteTimeGetCurrent());
+
+       stopRls = (CFRunLoopSourceRef)CFDictionaryGetValue(exiting, bundle);
+       CFRunLoopSourceInvalidate(stopRls);
+
+       CFDictionaryRemoveValue(exiting, bundle);
+
+       if (CFDictionaryGetCount(exiting) == 0) {
+               int     status;
+
+               // if all of the plugins are happy
+               status = server_shutdown();
+               SCLog(TRUE, LOG_DEBUG, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
+               exit (status);
+       }
 
-       if (!CFBundleIsExecutableLoaded(bundle)) {
+       return;
+}
+
+
+static void
+stopDelayed(CFRunLoopTimerRef timer, void *info)
+{
+       const void      **keys;
+       CFIndex         i;
+       CFIndex         n;
+       int             status;
+
+       SCLog(TRUE, LOG_ERR, CFSTR("server shutdown was delayed, unresponsive plugins:"));
+
+       /*
+        * we've asked our plugins to shutdown but someone
+        * isn't listening.
+        */
+       n = CFDictionaryGetCount(exiting);
+       keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0);
+       CFDictionaryGetKeysAndValues(exiting, keys, NULL);
+       for (i = 0; i < n; i++) {
+               CFBundleRef     bundle;
+               CFStringRef     bundleID;
+
+               bundle   = (CFBundleRef)keys[i];
+               bundleID = CFBundleGetIdentifier(bundle);
+               SCLog(TRUE, LOG_ERR, CFSTR("** %@"), bundleID);
+       }
+       CFAllocatorDeallocate(NULL, keys);
+
+       status = server_shutdown();
+       exit (status);
+}
+
+static void
+stopBundle(const void *value, void *context) {
+       bundleInfoRef                   bundleInfo      = (bundleInfoRef)value;
+       CFRunLoopSourceRef              stopRls;
+       CFRunLoopSourceContext          stopContext     = { 0                   // version
+                                                         , bundleInfo->bundle  // info
+                                                         , CFRetain            // retain
+                                                         , CFRelease           // release
+                                                         , CFCopyDescription   // copyDescription
+                                                         , CFEqual             // equal
+                                                         , CFHash              // hash
+                                                         , NULL                // schedule
+                                                         , NULL                // cancel
+                                                         , stopComplete        // perform
+                                                         };
+
+       if (!bundleInfo->loaded) {
                return;
        }
 
-       prime = CFBundleGetFunctionPointerForName(bundle, CFSTR("prime"));
-       if (!prime) {
+       if (bundleInfo->stop == NULL) {
+               // if no stop() function
                return;
        }
 
-       (*prime)();
+       stopRls = CFRunLoopSourceCreate(NULL, 0, &stopContext);
+       CFRunLoopAddSource(CFRunLoopGetCurrent(), stopRls, kCFRunLoopDefaultMode);
+       CFDictionaryAddValue(exiting, bundleInfo->bundle, stopRls);
+       CFRelease(stopRls);
+
+       (*bundleInfo->stop)(stopRls);
+
+       return;
+}
+
+
+static void
+stopBundles()
+{
+       /*
+        * If defined, call each bundles stop() function.  This function is
+        * called when configd has been asked to shut down (via a SIGTERM).  The
+        * function should signal the provided run loop source when it is "ready"
+        * for the shut down to proceeed.
+        */
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle stop() functions"));
+       CFArrayApplyFunction(allBundles,
+                            CFRangeMake(0, CFArrayGetCount(allBundles)),
+                            stopBundle,
+                            NULL);
+
+       if (CFDictionaryGetCount(exiting) == 0) {
+               int     status;
+
+               // if all of the plugins are happy
+               status = server_shutdown();
+               SCLog(TRUE, LOG_DEBUG, CFSTR("server shutdown complete (%f)"), CFAbsoluteTimeGetCurrent());
+               exit (status);
+       } else {
+               CFRunLoopTimerRef       timer;
+
+               /* sorry, we're not going to wait longer than 20 seconds */
+               timer = CFRunLoopTimerCreate(NULL,                              /* allocator */
+                                            CFAbsoluteTimeGetCurrent() + 20.0, /* fireDate (in 20 seconds) */
+                                            0.0,                               /* interval (== one-shot) */
+                                            0,                                 /* flags */
+                                            0,                                 /* order */
+                                            stopDelayed,                       /* callout */
+                                            NULL);                             /* context */
+               CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
+               CFRelease(timer);
+       }
+
        return;
 }
 
 
+__private_extern__
+Boolean
+plugin_term(int *status)
+{
+       CFRunLoopSourceRef      stopRls;
+       CFRunLoopSourceContext  stopContext = { 0               // version
+                                             , NULL            // info
+                                             , NULL            // retain
+                                             , NULL            // release
+                                             , NULL            // copyDescription
+                                             , NULL            // equal
+                                             , NULL            // hash
+                                             , NULL            // schedule
+                                             , NULL            // cancel
+                                             , stopBundles     // perform
+                                             };
+
+       if (plugin_runLoop == NULL) {
+               // if no plugins
+               *status = EX_OK;
+               return FALSE;   // don't delay shutdown
+       }
+
+       if (exiting != NULL) {
+               // if shutdown already active
+               return TRUE;
+       }
+
+       SCLog(TRUE, LOG_DEBUG, CFSTR("starting server shutdown (%f)"), CFAbsoluteTimeGetCurrent());
+
+       exiting = CFDictionaryCreateMutable(NULL,
+                                           0,
+                                           &kCFTypeDictionaryKeyCallBacks,
+                                           &kCFTypeDictionaryValueCallBacks);
+
+       stopRls = CFRunLoopSourceCreate(NULL, 0, &stopContext);
+       CFRunLoopAddSource(plugin_runLoop, stopRls, kCFRunLoopDefaultMode);
+       CFRunLoopSourceSignal(stopRls);
+       CFRelease(stopRls);
+       CFRunLoopWakeUp(plugin_runLoop);
+
+       return TRUE;
+}
+
+
 #ifdef DEBUG
 
 static void
@@ -400,30 +622,30 @@ timerCallback(CFRunLoopTimerRef timer, void *info)
 static void
 sortBundles(CFMutableArrayRef orig)
 {
-       CFMutableArrayRef   new;
+       CFMutableArrayRef       new;
 
-       new = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       new = CFArrayCreateMutable(NULL, 0, NULL);
        while (CFArrayGetCount(orig) > 0) {
                int     i;
                Boolean inserted        = FALSE;
                int     nOrig           = CFArrayGetCount(orig);
 
                for (i = 0; i < nOrig; i++) {
-                       CFBundleRef     bundle1   = (CFBundleRef)CFArrayGetValueAtIndex(orig, i);
-                       CFStringRef     bundleID1 = CFBundleGetIdentifier(bundle1);
+                       bundleInfoRef   bundleInfo1     = (bundleInfoRef)CFArrayGetValueAtIndex(orig, i);
+                       CFStringRef     bundleID1       = CFBundleGetIdentifier(bundleInfo1->bundle);
                        int             count;
                        CFDictionaryRef dict;
                        int             j;
                        int             nRequires;
                        CFArrayRef      requires  = NULL;
 
-                       dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundle1));
+                       dict = isA_CFDictionary(CFBundleGetInfoDictionary(bundleInfo1->bundle));
                        if (dict) {
-                               requires = CFDictionaryGetValue(dict, kSCBundleRequires);
+                               requires = CFDictionaryGetValue(dict, kSCBundleRequiresKey);
                                requires = isA_CFArray(requires);
                        }
                        if (bundleID1 == NULL || requires == NULL) {
-                               CFArrayInsertValueAtIndex(new, 0, bundle1);
+                               CFArrayInsertValueAtIndex(new, 0, bundleInfo1);
                                CFArrayRemoveValueAtIndex(orig, i);
                                inserted = TRUE;
                                break;
@@ -436,8 +658,8 @@ sortBundles(CFMutableArrayRef orig)
 
                                nNew = CFArrayGetCount(new);
                                for (k = 0; k < nNew; k++) {
-                                       CFBundleRef     bundle2   = (CFBundleRef)CFArrayGetValueAtIndex(new, k);
-                                       CFStringRef     bundleID2 = CFBundleGetIdentifier(bundle2);
+                                       bundleInfoRef   bundleInfo2     = (bundleInfoRef)CFArrayGetValueAtIndex(new, k);
+                                       CFStringRef     bundleID2       = CFBundleGetIdentifier(bundleInfo2->bundle);
 
                                        if (bundleID2 && CFEqual(bundleID2, r)) {
                                                count--;
@@ -446,7 +668,7 @@ sortBundles(CFMutableArrayRef orig)
                        }
                        if (count == 0) {
                                /* all dependencies are met, append */
-                               CFArrayAppendValue(new, bundle1);
+                               CFArrayAppendValue(new, bundleInfo1);
                                CFArrayRemoveValueAtIndex(orig, i);
                                inserted = TRUE;
                                break;
@@ -477,10 +699,10 @@ __private_extern__
 void *
 plugin_exec(void *arg)
 {
-       CFIndex                 nLoaded         = 0;
+       CFIndex         nLoaded         = 0;
 
        /* keep track of bundles */
-       allBundles = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+       allBundles = CFArrayCreateMutable(NULL, 0, NULL);
 
        /* allow plug-ins to exec child/helper processes */
        _SCDPluginExecInit();
@@ -493,7 +715,7 @@ plugin_exec(void *arg)
                 * identify and load all bundles
                 */
                state = NSStartSearchPathEnumeration(NSLibraryDirectory,
-                                                    NSLocalDomainMask|NSSystemDomainMask);
+                                                    NSSystemDomainMask);
                while ((state = NSGetNextSearchPathEnumeration(state, path))) {
                        CFArrayRef      bundles;
                        CFURLRef        url;
@@ -508,10 +730,17 @@ plugin_exec(void *arg)
                        bundles = CFBundleCreateBundlesFromDirectory(NULL, url, CFSTR(".bundle"));
                        CFRelease(url);
 
-                       if (bundles) {
-                               CFArrayAppendArray(allBundles,
-                                                  bundles,
-                                                  CFRangeMake(0, CFArrayGetCount(bundles)));
+                       if (bundles != NULL) {
+                               CFIndex i;
+                               CFIndex n;
+
+                               n = CFArrayGetCount(bundles);
+                               for (i = 0; i < n; i++) {
+                                       CFBundleRef     bundle;
+                                       
+                                       bundle = (CFBundleRef)CFArrayGetValueAtIndex(bundles, i);
+                                       addBundle(bundle);
+                               }
                                CFRelease(bundles);
                        }
                }
@@ -529,17 +758,26 @@ plugin_exec(void *arg)
                                                              strlen((char *)arg),
                                                              TRUE);
                bundle = CFBundleCreate(NULL, url);
-               if (bundle) {
-                       CFArrayAppendValue(allBundles, bundle);
+               if (bundle != NULL) {
+                       addBundle(bundle);
                        CFRelease(bundle);
                }
                CFRelease(url);
        }
 
        /*
-        * load each bundle and, if defined, call its load() function.  This
-        * function (or the start() function) should initialize any variables,
-        * open any sessions with "configd", and register any needed notifications.
+        * load each bundle.
+        */
+       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("loading bundles"));
+       CFArrayApplyFunction(allBundles,
+                            CFRangeMake(0, CFArrayGetCount(allBundles)),
+                            loadBundle,
+                            &nLoaded);
+
+       /*
+        * If defined, call each bundles load() function.  This function (or
+        * the start() function) should initialize any variables, open any
+        * sessions with "configd", and register any needed notifications.
         *
         * Note: Establishing initial information in the store should be
         *       deferred until the prime() initialization function so that
@@ -550,8 +788,8 @@ plugin_exec(void *arg)
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle load() functions"));
        CFArrayApplyFunction(allBundles,
                             CFRangeMake(0, CFArrayGetCount(allBundles)),
-                            loadBundle,
-                            &nLoaded);
+                            callLoadFunction,
+                            NULL);
 
        /*
         * If defined, call each bundles start() function.  This function is
@@ -568,7 +806,7 @@ plugin_exec(void *arg)
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle start() functions"));
        CFArrayApplyFunction(allBundles,
                             CFRangeMake(0, CFArrayGetCount(allBundles)),
-                            startBundle,
+                            callStartFunction,
                             NULL);
 
        /*
@@ -580,7 +818,7 @@ plugin_exec(void *arg)
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("calling bundle prime() functions"));
        CFArrayApplyFunction(allBundles,
                             CFRangeMake(0, CFArrayGetCount(allBundles)),
-                            primeBundle,
+                            callPrimeFunction,
                             NULL);
 
 #ifdef DEBUG
@@ -608,8 +846,11 @@ plugin_exec(void *arg)
         * private thread.
         */
        SCLog(_configd_verbose, LOG_DEBUG, CFSTR("starting plugin CFRunLoop"));
+       plugin_runLoop = CFRunLoopGetCurrent();
        CFRunLoopRun();
-       SCLog(_configd_verbose, LOG_INFO, CFSTR("what, no more work for the \"configd\" bundles?"));
+
+       SCLog(_configd_verbose, LOG_INFO, CFSTR("No more work for the \"configd\" plugins"));
+       plugin_runLoop = NULL;
        return NULL;
 }
 
index 0891ca68e426690396154bcfc6f90313062f67fa..63d515a55c2a8fa3a5c59c5b5d5981040cff64e7 100644 (file)
@@ -37,6 +37,7 @@ __BEGIN_DECLS
 
 void   plugin_init     ();
 void   plugin_exec     (void   *arg);
+Boolean        plugin_term     (int    *status);
 
 __END_DECLS
 
index 6c299bbe3670dd4e985723ff341f2b86c88cb60b..94e421345bf1adad31fc8c04eb147804006b39ec 100644 (file)
@@ -47,7 +47,7 @@ getSession(mach_port_t server)
        int     i;
 
        if (server == MACH_PORT_NULL) {
-               SCLog(_configd_verbose, LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?"));
+               SCLog(TRUE, LOG_NOTICE, CFSTR("Excuse me, why is getSession() being called with an invalid port?"));
                return NULL;
        }
 
@@ -93,11 +93,11 @@ addSession(CFMachPortRef server)
                if (n < 0) {
                        /* no empty slots, add one to the list */
                        n = nSessions++;
-                       sessions = realloc(sessions, ((nSessions) * sizeof(serverSessionRef)));
+                       sessions = reallocf(sessions, ((nSessions) * sizeof(serverSessionRef)));
                }
        }
 
-       SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Allocating new session for port %d"), CFMachPortGetPort(server));
+       // allocate a new session for this server
        sessions[n] = malloc(sizeof(serverSession));
        sessions[n]->key                 = CFMachPortGetPort(server);
        sessions[n]->serverPort          = server;
diff --git a/configd.xcode/project.pbxproj b/configd.xcode/project.pbxproj
new file mode 100644 (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>
-                               <string>/tmp/ppp.log</string>
+                               <string>/var/log/ppp.log</string>
                                <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>
 
 
-Boolean        apply   = TRUE;
+static Boolean apply   = TRUE;
 
 
-static struct option longopts[] = {
+static const struct option longopts[] = {
 //     { "debug",              no_argument,            0,      'd' },
 //     { "verbose",            no_argument,            0,      'v' },
 //     { "do-not-apply",       no_argument,            0,      'n' },
@@ -76,31 +76,31 @@ usage(const char *command)
 static Boolean
 isAdmin()
 {
-        gid_t  groups[NGROUPS_MAX];
-        int    ngroups;
-
-        if (getuid() == 0) {
-                return TRUE;   // if "root"
-        }
-
-        ngroups = getgroups(NGROUPS_MAX, groups);
-        if(ngroups > 0) {
-                struct group   *adminGroup;
-
-                adminGroup = getgrnam("admin");
-                if (adminGroup != NULL) {
-                        gid_t  adminGid = adminGroup->gr_gid;
-                        int    i;
-
-                        for (i = 0; i < ngroups; i++) {
-                                if (groups[i] == adminGid) {
-                                        return TRUE;   // if a member of group "admin"
-                                }
-                        }
-                }
-        }
-
-        return FALSE;
+       gid_t   groups[NGROUPS_MAX];
+       int     ngroups;
+
+       if (getuid() == 0) {
+               return TRUE;    // if "root"
+       }
+
+       ngroups = getgroups(NGROUPS_MAX, groups);
+       if(ngroups > 0) {
+               struct group    *adminGroup;
+
+               adminGroup = getgrnam("admin");
+               if (adminGroup != NULL) {
+                       gid_t   adminGid = adminGroup->gr_gid;
+                       int     i;
+
+                       for (i = 0; i < ngroups; i++) {
+                               if (groups[i] == adminGid) {
+                                       return TRUE;    // if a member of group "admin"
+                               }
+                       }
+               }
+       }
+
+       return FALSE;
 }
 
 
@@ -141,17 +141,17 @@ _SessionGetInfo(SecuritySessionId session, SecuritySessionId *sessionId, Session
 static Boolean
 hasLocalConsoleAccess()
 {
-        OSStatus               error;
-        SecuritySessionId      sessionID       = 0;
-        SessionAttributeBits   attributeBits   = 0;
-
-        error = SessionGetInfo(callerSecuritySession, &sessionID, &attributeBits);
-        if (error != noErr) {
-                /* Security check failed, must not permit access */
-                return FALSE;
-        }
+       OSStatus                error;
+       SecuritySessionId       sessionID       = 0;
+       SessionAttributeBits    attributeBits   = 0;
+
+       error = SessionGetInfo(callerSecuritySession, &sessionID, &attributeBits);
+       if (error != noErr) {
+               /* Security check failed, must not permit access */
+               return FALSE;
+       }
 
-        return (attributeBits & (sessionHasGraphicAccess|sessionIsRemote)) == sessionHasGraphicAccess;
+       return (attributeBits & (sessionHasGraphicAccess|sessionIsRemote)) == sessionHasGraphicAccess;
 }
 
 
@@ -166,7 +166,7 @@ main(int argc, char **argv)
        CFStringRef             newSet          = NULL; /* set key */
        CFStringRef             newSetUDN       = NULL; /* user defined name */
        CFStringRef             prefix;
-       SCPreferencesRef        session;
+       SCPreferencesRef        prefs;
        CFDictionaryRef         sets;
        CFIndex                 nSets;
        const void              **setKeys       = NULL;
@@ -200,8 +200,8 @@ main(int argc, char **argv)
                        ? CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman)
                        : CFSTR("");
 
-       session = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
-       if (!session) {
+       prefs = SCPreferencesCreate(NULL, CFSTR("Select Set Command"), NULL);
+       if (prefs == NULL) {
                SCPrint(TRUE, stderr, CFSTR("SCPreferencesCreate() failed\n"));
                exit (1);
        }
@@ -224,14 +224,14 @@ main(int argc, char **argv)
                newSet = str;
        }
 
-       sets = SCPreferencesGetValue(session, kSCPrefSets);
-       if (!sets) {
-               SCPrint(TRUE, stderr, CFSTR("SCPreferencesGetValue(...,%s,...) failed\n"));
+       sets = SCPreferencesGetValue(prefs, kSCPrefSets);
+       if (sets == NULL) {
+               SCPrint(TRUE, stderr, CFSTR("No network sets defined.\n"));
                exit (1);
        }
 
-       current = SCPreferencesGetValue(session, kSCPrefCurrentSet);
-       if (current) {
+       current = SCPreferencesGetValue(prefs, kSCPrefCurrentSet);
+       if (current != NULL) {
                if (CFStringHasPrefix(current, prefix)) {
                        CFMutableStringRef      tmp;
 
@@ -264,7 +264,7 @@ main(int argc, char **argv)
 
                if (CFEqual(newSet, key)) {
                        newSetUDN = CFDictionaryGetValue(dict, kSCPropUserDefinedName);
-                       if (newSetUDN CFRetain(newSetUDN);
+                       if (newSetUDN != NULL) CFRetain(newSetUDN);
                        current = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), prefix, newSet);
                        goto found;
                }
@@ -324,12 +324,12 @@ main(int argc, char **argv)
     found :
 
        if (!(isAdmin() || hasLocalConsoleAccess())) {
-                SCPrint(TRUE, stderr,
-                        CFSTR("Only local console users and administrators can change locations\n"));
-                exit (EX_NOPERM);
+               SCPrint(TRUE, stderr,
+                       CFSTR("Only local console users and administrators can change locations\n"));
+               exit (EX_NOPERM);
        }
-        
-       if (!SCPreferencesSetValue(session, kSCPrefCurrentSet, current)) {
+
+       if (!SCPreferencesSetValue(prefs, kSCPrefCurrentSet, current)) {
                SCPrint(TRUE, stderr,
                        CFSTR("SCPreferencesSetValue(...,%@,%@) failed\n"),
                        kSCPrefCurrentSet,
@@ -337,19 +337,19 @@ main(int argc, char **argv)
                exit (1);
        }
 
-       if (!SCPreferencesCommitChanges(session)) {
+       if (!SCPreferencesCommitChanges(prefs)) {
                SCPrint(TRUE, stderr, CFSTR("SCPreferencesCommitChanges() failed\n"));
                exit (1);
        }
 
        if (apply) {
-               if (!SCPreferencesApplyChanges(session)) {
+               if (!SCPreferencesApplyChanges(prefs)) {
                        SCPrint(TRUE, stderr, CFSTR("SCPreferencesApplyChanges() failed\n"));
                        exit (1);
                }
        }
 
-       CFRelease(session);
+       CFRelease(prefs);
 
        SCPrint(TRUE, stdout,
                CFSTR("%@ updated to %@ (%@)\n"),
diff --git a/scutil.tproj/Makefile b/scutil.tproj/Makefile
deleted file mode 100644 (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)
 {
@@ -56,7 +57,7 @@ do_list(int argc, char **argv)
 
        pattern = CFStringCreateWithCString(NULL,
                                            (argc >= 1) ? argv[0] : ".*",
-                                           kCFStringEncodingMacRoman);
+                                           kCFStringEncodingUTF8);
 
        list = SCDynamicStoreCopyKeyList(store, pattern);
        CFRelease(pattern);
@@ -94,12 +95,13 @@ do_list(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_add(int argc, char **argv)
 {
        CFStringRef     key;
 
-       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
 
        if (argc < 2) {
                if (!SCDynamicStoreAddValue(store, key, value)) {
@@ -116,13 +118,14 @@ do_add(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_get(int argc, char **argv)
 {
        CFStringRef             key;
        CFPropertyListRef       newValue;
 
-       key      = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key      = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        newValue = SCDynamicStoreCopyValue(store, key);
        CFRelease(key);
        if (!newValue) {
@@ -139,12 +142,13 @@ do_get(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_set(int argc, char **argv)
 {
        CFStringRef     key;
 
-       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        if (!SCDynamicStoreSetValue(store, key, value)) {
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
        }
@@ -153,13 +157,14 @@ do_set(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_show(int argc, char **argv)
 {
        CFStringRef             key;
        CFPropertyListRef       newValue;
 
-       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
 
        if (argc == 1) {
                newValue = SCDynamicStoreCopyValue(store, key);
@@ -183,12 +188,13 @@ do_show(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_remove(int argc, char **argv)
 {
        CFStringRef     key;
 
-       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        if (!SCDynamicStoreRemoveValue(store, key)) {
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
        }
@@ -197,12 +203,13 @@ do_remove(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_notify(int argc, char **argv)
 {
        CFStringRef     key;
 
-       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        if (!SCDynamicStoreNotifyValue(store, key)) {
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
        }
@@ -211,12 +218,13 @@ do_notify(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_touch(int argc, char **argv)
 {
        CFStringRef     key;
 
-       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key    = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        if (!SCDynamicStoreTouchValue(store, key)) {
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
        }
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@
  * 
 #include "dictionary.h"
 #include "session.h"
 #include "cache.h"
-#include "notify.h"
+#include "notifications.h"
 #include "tests.h"
+#include "net.h"
 
 #include "SCDynamicStoreInternal.h"
 
 
-const cmdInfo commands[] = {
+__private_extern__
+const cmdInfo commands_store[] = {
        /* cmd          minArgs maxArgs func                    group   ctype                   */
        /*      usage                                                                           */
 
@@ -56,6 +58,15 @@ const cmdInfo commands[] = {
        { "f.read",     1,      1,      do_readFile,            0,      0,
                " f.read file                   : process commands from file"                   },
 
+       { "quit",       0,      0,      do_quit,                0,      0,
+               " quit                          : quit"                                         },
+
+       { "q",          0,      0,      do_quit,                0,      -1,
+               NULL                                                                            },
+
+       { "exit",       0,      0,      do_quit,                0,      -1,
+               NULL                                                                            },
+
        /* local dictionary manipulation commands */
 
        { "d.init",     0,      0,      do_dictInit,            1,      0,
@@ -66,17 +77,17 @@ const cmdInfo commands[] = {
 
        { "d.add",      2,      101,    do_dictSetKey,          1,      0,
                " d.add key [*#?] val [v2 ...]  : add information to dictionary\n"
-               "       (*=array, #=number, ?=boolean)"                         },
+               "       (*=array, #=number, ?=boolean)"                                         },
 
        { "d.remove",   1,      1,      do_dictRemoveKey,       1,      0,
                " d.remove key                  : remove key from dictionary"                   },
 
        /* data store manipulation commands */
 
-       { "open",       0,      0,      do_open,                2,      0,
-               " open                          : open a session with \"configd\""              },
+       { "open",       0,      1,      do_open,                2,      1,
+               " open [\"temporary\"]            : open a session with \"configd\""            },
 
-       { "close",      0,      0,      do_close,               2,      0,
+       { "close",      0,      0,      do_close,               2,      1,
                " close                         : close current \"configd\" session"            },
 
        { "lock",       0,      0,      do_lock,                3,      1,
@@ -89,13 +100,13 @@ const cmdInfo commands[] = {
                " list [pattern]                : list keys in data store"                      },
 
        { "add",        1,      2,      do_add,                 4,      0,
-               " add key [\"temporary\"]         : add key in data store w/current dict"               },
+               " add key [\"temporary\"]         : add key in data store w/current dict"       },
 
        { "get",        1,      1,      do_get,                 4,      0,
                " get key                       : get dict from data store w/key"               },
 
        { "set",        1,      1,      do_set,                 4,      0,
-               " set key                       : set key in data store w/current dict"         },
+               " set key                         : set key in data store w/current dict"       },
 
        { "show",       1,      2,      do_show,                4,      0,
                " show key [\"pattern\"]          : show values in data store w/key"            },
@@ -113,7 +124,7 @@ const cmdInfo commands[] = {
                " n.list [\"pattern\"]            : list notification keys"                     },
 
        { "n.add",      1,      2,      do_notify_add,          5,      0,
-               " n.add key [\"pattern\"]         : add notification key"                               },
+               " n.add key [\"pattern\"]         : add notification key"                       },
 
        { "n.remove",   1,      2,      do_notify_remove,       5,      0,
                " n.remove key [\"pattern\"]      : remove notification key"                    },
@@ -139,15 +150,103 @@ const cmdInfo commands[] = {
        { "n.cancel",   0,      1,      do_notify_cancel,       5,      0,
                " n.cancel                      : cancel notification requests"                 },
 
-       { "snapshot",   0,      0,      do_snapshot,            9     2,
-               " snapshot                      : save snapshot of store and session data"      },
+       { "snapshot",   0,      0,      do_snapshot,            99,     2,
+               " snapshot                      : save snapshot of store and session data"      }
 };
+__private_extern__
+const int nCommands_store = (sizeof(commands_store)/sizeof(cmdInfo));
+
+
+__private_extern__
+const cmdInfo commands_prefs[] = {
+       /* cmd          minArgs maxArgs func                    group   ctype                   */
+       /*      usage                                                                           */
+
+       { "help",       0,      0,      do_help,                0,      0,
+               " help                          : list available commands"                      },
+
+       { "f.read",     1,      1,      do_readFile,            0,      0,
+               " f.read file                   : process commands from file"                   },
+
+       { "quit",       0,      1,      do_net_quit,            0,      0,
+               " quit [!]                      : quit"                                         },
+
+       { "q",          0,      1,      do_net_quit,            0,      -1,
+               NULL                                                                            },
+
+       { "exit",       0,      1,      do_net_quit,            0,      -1,
+               NULL                                                                            },
+
+       /* network configuration manipulation commands */
+
+       { "open",       0,      1,      do_net_open,            2,      1,
+               " open                          : open the network configuration"               },
+
+       { "commit",     0,      0,      do_net_commit,          2,      0,
+               " commit                        : commit any changes"                           },
+
+       { "apply",      0,      0,      do_net_apply,           2,      0,
+               " apply                         : apply any changes"                            },
 
-const int nCommands = (sizeof(commands)/sizeof(cmdInfo));
+       { "close",      0,      1,      do_net_close,           2,      1,
+               " close [!]                     : close the network configuration"              },
 
-Boolean enablePrivateAPI       = FALSE;
+       { "create",     1,      3,      do_net_create,          3,      0,
+               " create interface <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)
 {
@@ -169,7 +268,7 @@ do_command(int argc, char **argv)
                                SCPrint(TRUE, stdout, CFSTR("%s: too many arguments\n"), cmd);
                                return;
                        }
-                       commands[i].func(argc, argv);
+                       (*commands[i].func)(argc, argv);
                        return;
                }
        }
@@ -179,6 +278,7 @@ do_command(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_help(int argc, char **argv)
 {
@@ -187,6 +287,10 @@ do_help(int argc, char **argv)
 
        SCPrint(TRUE, stdout, CFSTR("\nAvailable commands:\n"));
        for (i = 0; i < nCommands; i++) {
+               if (commands[i].ctype < 0)  {
+                       continue;       /* if "hidden" */
+               }
+
                if ((commands[i].ctype > 0) && !enablePrivateAPI)  {
                        continue;       /* if "private" API and access has not been enabled */
                }
@@ -206,6 +310,7 @@ do_help(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_readFile(int argc, char **argv)
 {
@@ -236,3 +341,12 @@ do_readFile(int argc, char **argv)
 
        return;
 }
+
+
+__private_extern__
+void
+do_quit(int argc, char **argv)
+{
+       termRequested = TRUE;
+       return;
+}
index a0a082129a557b3e58ee8022c6b431152244640d..f1fd33299a1536d6030975b881c21f9815fcb22c 100644 (file)
@@ -42,18 +42,26 @@ typedef struct {
        int     maxArgs;
        void    (*func)();
        int     group;
-       int     ctype;  /* 0==normal, 1==limited, 2==private */
+       int     ctype;  /* -1==normal/hidden, 0==normal, 1==limited, 2==private */
        char    *usage;
 } cmdInfo;
 
-extern const cmdInfo   commands[];
-extern const int       nCommands;
+extern const cmdInfo   commands_store[];
+extern const int       nCommands_store;
+
+extern const cmdInfo   commands_prefs[];
+extern const int       nCommands_prefs;
+
+extern cmdInfo         *commands;
+extern int             nCommands;
 extern Boolean         enablePrivateAPI;
+extern Boolean         termRequested;
 
 __BEGIN_DECLS
 
 void   do_command              (int argc, char **argv);
 void   do_help                 (int argc, char **argv);
+void   do_quit                 (int argc, char **argv);
 void   do_readFile             (int argc, char **argv);
 
 __END_DECLS
index 8507ddac44ca179fb08636b53f17bb74ab3f6030..234c4e2f48dd75c3fb07a88c2b285e9c0fc7343b 100644 (file)
@@ -39,6 +39,7 @@
 //#include <limits.h>
 
 
+__private_extern__
 void
 do_dictInit(int argc, char **argv)
 {
@@ -56,6 +57,7 @@ do_dictInit(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_dictShow(int argc, char **argv)
 {
@@ -70,6 +72,7 @@ do_dictShow(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_dictSetKey(int argc, char **argv)
 {
@@ -94,7 +97,7 @@ do_dictSetKey(int argc, char **argv)
        CFRelease(value);
        value = val;
 
-       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        argv++; argc--;
 
        while (argc > 0) {
@@ -161,7 +164,7 @@ do_dictSetKey(int argc, char **argv)
                                return;
                        }
                } else {
-                       val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+                       val = (CFPropertyListRef)CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
                }
 
                if (doArray) {
@@ -183,6 +186,7 @@ do_dictSetKey(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_dictRemoveKey(int argc, char **argv)
 {
@@ -203,7 +207,7 @@ do_dictRemoveKey(int argc, char **argv)
        CFRelease(value);
        value = val;
 
-       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingMacRoman);
+       key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
        CFDictionaryRemoveValue((CFMutableDictionaryRef)value, key);
        CFRelease(key);
 
diff --git a/scutil.tproj/h.template b/scutil.tproj/h.template
deleted file mode 100644 (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@
  * 
 static SCPreferencesRef
 _open()
 {
-       SCPreferencesRef        prefs;
-
        prefs = SCPreferencesCreate(NULL, CFSTR("scutil"), NULL);
-       if (!prefs) {
+       if (prefs == NULL) {
                SCPrint(TRUE,
                        stdout,
                        CFSTR("SCPreferencesCreate() failed: %s\n"),
@@ -150,7 +148,6 @@ set_ComputerName(int argc, char **argv)
 {
        CFStringEncoding        encoding;
        CFStringRef             hostname;
-       SCPreferencesRef        prefs;
 
        if (argc == 0) {
                hostname = _copyStringFromSTDIN();
@@ -175,6 +172,67 @@ set_ComputerName(int argc, char **argv)
 }
 
 
+static void
+get_HostName(int argc, char **argv)
+{
+       CFStringRef     hostname;
+
+       prefs = _open();
+       hostname = SCPreferencesGetHostName(prefs);
+       if (hostname == NULL) {
+               int     sc_status       = SCError();
+
+               switch (sc_status) {
+                       case kSCStatusNoKey :
+                               SCPrint(TRUE,
+                                       stderr,
+                                       CFSTR("HostName: not set\n"));
+                               break;
+                       default :
+                               SCPrint(TRUE,
+                                       stderr,
+                                       CFSTR("SCPreferencesGetHostName() failed: %s\n"),
+                                       SCErrorString(SCError()));
+                               break;
+               }
+               CFRelease(prefs);
+               exit (1);
+       }
+
+       SCPrint(TRUE, stdout, CFSTR("%@\n"), hostname);
+       CFRelease(hostname);
+       exit(0);
+}
+
+
+static void
+set_HostName(int argc, char **argv)
+{
+       CFStringRef             hostname = NULL;
+
+       if (argc == 0) {
+               hostname = _copyStringFromSTDIN();
+       } else {
+               hostname = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingASCII);
+       }
+
+       prefs = _open();
+       if (!SCPreferencesSetHostName(prefs, hostname)) {
+               SCPrint(TRUE,
+                       stderr,
+                       CFSTR("SCPreferencesSetHostName() failed: %s\n"),
+                       SCErrorString(SCError()));
+               CFRelease(hostname);
+               CFRelease(prefs);
+               exit (1);
+       }
+       _save(prefs);
+       CFRelease(hostname);
+       CFRelease(prefs);
+       exit(0);
+}
+
+
 static void
 get_LocalHostName(int argc, char **argv)
 {
@@ -210,7 +268,6 @@ static void
 set_LocalHostName(int argc, char **argv)
 {
        CFStringRef             hostname = NULL;
-       SCPreferencesRef        prefs;
 
        if (argc == 0) {
                hostname = _copyStringFromSTDIN();
@@ -235,24 +292,26 @@ set_LocalHostName(int argc, char **argv)
 
 typedef void (*pref_func) (int argc, char **argv);
 
-static struct {
+static const struct {
        char            *pref;
        pref_func       get;
        pref_func       set;
-} prefs[] = {
+} pref_keys[] = {
        { "ComputerName",       get_ComputerName,       set_ComputerName        },
+       { "HostName",           get_HostName,           set_HostName            },
        { "LocalHostName",      get_LocalHostName,      set_LocalHostName       }
 };
-#define        N_PREFS (sizeof(prefs) / sizeof(prefs[0]))
+#define        N_PREF_KEYS     (sizeof(pref_keys) / sizeof(pref_keys[0]))
 
 
+__private_extern__
 int
 findPref(char *pref)
 {
        int     i;
 
-       for (i = 0; i < (int)N_PREFS; i++) {
-               if (strcmp(pref, prefs[i].pref) == 0) {
+       for (i = 0; i < (int)N_PREF_KEYS; i++) {
+               if (strcmp(pref, pref_keys[i].pref) == 0) {
                        return i;
                }
        }
@@ -261,6 +320,7 @@ findPref(char *pref)
 }
 
 
+__private_extern__
 void
 do_getPref(char *pref, int argc, char **argv)
 {
@@ -268,12 +328,13 @@ do_getPref(char *pref, int argc, char **argv)
 
        i = findPref(pref);
        if (i >= 0) {
-               (*prefs[i].get)(argc, argv);
+               (*pref_keys[i].get)(argc, argv);
        }
        return;
 }
 
 
+__private_extern__
 void
 do_setPref(char *pref, int argc, char **argv)
 {
@@ -281,7 +342,7 @@ do_setPref(char *pref, int argc, char **argv)
 
        i = findPref(pref);
        if (i >= 0) {
-               (*prefs[i].set)(argc, argv);
+               (*pref_keys[i].set)(argc, argv);
        }
        return;
 }
diff --git a/scutil.tproj/scutil.8 b/scutil.tproj/scutil.8
new file mode 100644 (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@
  * 
@@ -24,6 +24,9 @@
 /*
  * Modification History
  *
+ * August 4, 2004              Allan Nathanson <ajn@apple.com>
+ * - added network configuration (prefs) support
+ *
  * September 25, 2002          Allan Nathanson <ajn@apple.com>
  * - added command line history & editing
  *
 #include "scutil.h"
 #include "commands.h"
 #include "dictionary.h"
-#include "tests.h"
+#include "net.h"
 #include "prefs.h"
+#include "session.h"
+#include "tests.h"
 
 #include "SCDynamicStoreInternal.h"
 
 #define LINE_LENGTH 256
 
 
-int                    nesting         = 0;
-CFRunLoopRef           notifyRl        = NULL;
-CFRunLoopSourceRef     notifyRls       = NULL;
-SCDynamicStoreRef      store           = NULL;
-CFPropertyListRef      value           = NULL;
-CFMutableArrayRef      watchedKeys     = NULL;
-CFMutableArrayRef      watchedPatterns = NULL;
+__private_extern__ InputRef            currentInput    = NULL;
+__private_extern__ int                 nesting         = 0;
+__private_extern__ CFRunLoopRef                notifyRl        = NULL;
+__private_extern__ CFRunLoopSourceRef  notifyRls       = NULL;
+__private_extern__ SCPreferencesRef    prefs           = NULL;
+__private_extern__ SCDynamicStoreRef   store           = NULL;
+__private_extern__ CFPropertyListRef   value           = NULL;
+__private_extern__ CFMutableArrayRef   watchedKeys     = NULL;
+__private_extern__ CFMutableArrayRef   watchedPatterns = NULL;
 
-static struct option longopts[] = {
+static const struct option longopts[] = {
 //     { "debug",              no_argument,            NULL,   'd'     },
 //     { "verbose",            no_argument,            NULL,   'v'     },
 //     { "SPI",                no_argument,            NULL,   'p'     },
-//     { "check-reachability", required_argument,      NULL,   'r'     },
+//     { "check-reachability", required_argument,      NULL,   'r'     },
 //     { "timeout",            required_argument,      NULL,   't'     },
 //     { "wait-key",           required_argument,      NULL,   'w'     },
+       { "dns",                no_argument,            NULL,   0       },
        { "get",                required_argument,      NULL,   0       },
        { "help",               no_argument,            NULL,   '?'     },
+       { "net",                no_argument,            NULL,   0       },
+       { "proxy",              no_argument,            NULL,   0       },
        { "set",                required_argument,      NULL,   0       },
-       { NULL,                 0,                      NULL,   0       }
+       { NULL,                 0,                      NULL,   0       }
 };
 
 
@@ -127,7 +137,7 @@ getLine(char *buf, int len, InputRef src)
 }
 
 
-char *
+static char *
 getString(char **line)
 {
        char *s, *e, c, *string;
@@ -178,13 +188,18 @@ getString(char **line)
 }
 
 
+__private_extern__
 Boolean
 process_line(InputRef src)
 {
-       char    line[LINE_LENGTH], *s, *arg, **argv = NULL;
-       int     i, argc;
-
-       /* if end-of-file, exit */
+       char    *arg;
+       int     argc                    = 0;
+       char    **argv                  = NULL;
+       int     i;
+       char    line[LINE_LENGTH];
+       char    *s                      = line;
+
+       // if end-of-file, exit
        if (getLine(line, sizeof(line), src) == NULL)
                return FALSE;
 
@@ -192,39 +207,37 @@ process_line(InputRef src)
                SCPrint(TRUE, stdout, CFSTR("%d> %s\n"), nesting, line);
        }
 
-       /* if requested, exit */
-       if (strcasecmp(line, "exit") == 0) return FALSE;
-       if (strcasecmp(line, "quit") == 0) return FALSE;
-       if (strcasecmp(line, "q"   ) == 0) return FALSE;
-
-       /* break up the input line */
-       s = line;
-       argc = 0;
+       // break up the input line
        while ((arg = getString(&s)) != NULL) {
                if (argc == 0)
                        argv = (char **)malloc(2 * sizeof(char *));
                else
-                       argv = (char **)realloc(argv, ((argc + 2) * sizeof(char *)));
+                       argv = (char **)reallocf(argv, ((argc + 2) * sizeof(char *)));
                argv[argc++] = arg;
        }
 
-       /* process the command */
-       if (argc > 0) {
-               argv[argc] = NULL;      /* just in case... */
+       if (argc == 0) {
+               return TRUE;            // if no arguments
+       }
 
-               if (*argv[0] != '#')
-                       do_command(argc, argv);
+       /* process the command */
+       if (*argv[0] != '#') {
+               argv[argc] = NULL;      // just in case...
+               currentInput = src;
+               do_command(argc, argv);
+       }
 
-               for (i = 0; i < argc; i++)
-                       free(argv[i]);
-               free(argv);
+       /* free the arguments */
+       for (i = 0; i < argc; i++) {
+               free(argv[i]);
        }
+       free(argv);
 
-       return TRUE;
+       return !termRequested;
 }
 
 
-void
+static void
 usage(const char *command)
 {
        SCPrint(TRUE, stderr, CFSTR("usage: %s\n"), command);
@@ -246,6 +259,19 @@ usage(const char *command)
        SCPrint(TRUE, stderr, CFSTR("\t\t\tComputerName, LocalHostName\n"));
        SCPrint(TRUE, stderr, CFSTR("\tnewval\tNew preference value to be set.  If not specified,\n"));
        SCPrint(TRUE, stderr, CFSTR("\t\tthe new value will be read from standard input.\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --dns\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tshow DNS configuration.\n"));
+       SCPrint(TRUE, stderr, CFSTR("\n"));
+       SCPrint(TRUE, stderr, CFSTR("   or: %s --proxy\n"), command);
+       SCPrint(TRUE, stderr, CFSTR("\tshow \"proxy\" configuration.\n"));
+
+       if (getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
+               SCPrint(TRUE, stderr, CFSTR("\n"));
+               SCPrint(TRUE, stderr, CFSTR("   or: %s --net\n"), command);
+               SCPrint(TRUE, stderr, CFSTR("\tmanage network configuration.\n"));
+       }
+
        exit (EX_USAGE);
 }
 
@@ -260,11 +286,14 @@ prompt(EditLine *el)
 int
 main(int argc, char * const argv[])
 {
+       Boolean                 dns     = FALSE;
        char                    *get    = NULL;
+       Boolean                 net     = FALSE;
        extern int              optind;
        int                     opt;
        int                     opti;
        const char              *prog   = argv[0];
+       Boolean                 proxy   = FALSE;
        Boolean                 reach   = FALSE;
        char                    *set    = NULL;
        InputRef                src;
@@ -299,9 +328,18 @@ main(int argc, char * const argv[])
                        xStore++;
                        break;
                case 0:
-                       if        (strcmp(longopts[opti].name, "get") == 0) {
+                       if        (strcmp(longopts[opti].name, "dns") == 0) {
+                               dns = TRUE;
+                               xStore++;
+                       } else if (strcmp(longopts[opti].name, "get") == 0) {
                                get = optarg;
                                xStore++;
+                       } else if (strcmp(longopts[opti].name, "net") == 0) {
+                               net = TRUE;
+                               xStore++;
+                       } else if (strcmp(longopts[opti].name, "proxy") == 0) {
+                               proxy = TRUE;
+                               xStore++;
                        } else if (strcmp(longopts[opti].name, "set") == 0) {
                                set = optarg;
                                xStore++;
@@ -334,6 +372,12 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
+       /* are we looking up the DNS configuration */
+       if (dns) {
+               do_showDNSConfiguration(argc, (char **)argv);
+               /* NOT REACHED */
+       }
+
        /* are we looking up a preference value */
        if (get) {
                if (findPref(get) < 0) {
@@ -343,6 +387,12 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
+       /* are we looking up the proxy configuration */
+       if (proxy) {
+               do_showProxyConfiguration(argc, (char **)argv);
+               /* NOT REACHED */
+       }
+
        /* are we changing a preference value */
        if (set) {
                if (findPref(set) < 0) {
@@ -352,8 +402,25 @@ main(int argc, char * const argv[])
                /* NOT REACHED */
        }
 
-       /* start with an empty dictionary */
-       do_dictInit(0, NULL);
+       if (net) {
+               /* if we are going to be managing the network configuration */
+               commands  = (cmdInfo *)commands_prefs;
+               nCommands = nCommands_prefs;
+
+               if (!getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) {
+                       usage(prog);
+               }
+
+               do_net_init();          /* initialization */
+               do_net_open(0, NULL);   /* open default prefs */
+       } else {
+               /* if we are going to be managing the dynamic store */
+               commands  = (cmdInfo *)commands_store;
+               nCommands = nCommands_store;
+
+               do_dictInit(0, NULL);   /* start with an empty dictionary */
+               do_open(0, NULL);       /* open the dynamic store */
+       }
 
        /* allocate command input stream */
        src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0);
index 794530bd9f538b09ae4bba1ca5178414b4b8e4c1..cf0125670fb779fbae4aeb39a3435c4b96035b8d 100644 (file)
@@ -49,9 +49,11 @@ typedef struct {
 } Input, *InputRef;
 
 
+extern InputRef                        currentInput;
 extern int                     nesting;
 extern CFRunLoopRef            notifyRl;
 extern CFRunLoopSourceRef      notifyRls;
+extern SCPreferencesRef                prefs;
 extern SCDynamicStoreRef       store;
 extern CFPropertyListRef       value;
 extern CFMutableArrayRef       watchedKeys;
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@
  * 
@@ -33,8 +33,9 @@
 
 #include "scutil.h"
 #include "session.h"
-#include "notify.h"
+#include "notifications.h"
 
+__private_extern__
 void
 do_open(int argc, char **argv)
 {
@@ -44,8 +45,24 @@ do_open(int argc, char **argv)
                CFRelease(watchedPatterns);
        }
 
-       store = SCDynamicStoreCreate(NULL, CFSTR("scutil"), storeCallback, NULL);
-       if (!store) {
+       if (argc < 1) {
+               store = SCDynamicStoreCreate(NULL, CFSTR("scutil"), storeCallback, NULL);
+       } else {
+               CFMutableDictionaryRef  options;
+
+               options = CFDictionaryCreateMutable(NULL,
+                                                   0,
+                                                   &kCFTypeDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+               CFDictionarySetValue(options, kSCDynamicStoreUseSessionKeys, kCFBooleanTrue);
+               store = SCDynamicStoreCreateWithOptions(NULL,
+                                                       CFSTR("scutil"),
+                                                       options,
+                                                       storeCallback,
+                                                       NULL);
+               CFRelease(options);
+       }
+       if (store == NULL) {
                SCPrint(TRUE, stdout, CFSTR("  %s\n"), SCErrorString(SCError()));
                return;
        }
@@ -57,11 +74,12 @@ do_open(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_close(int argc, char **argv)
 {
        if (notifyRls) {
-               CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifyRls, kCFRunLoopDefaultMode);
+               CFRunLoopSourceInvalidate(notifyRls);
                CFRelease(notifyRls);
                notifyRls = NULL;
        }
@@ -83,6 +101,7 @@ do_close(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_lock(int argc, char **argv)
 {
@@ -93,6 +112,7 @@ do_lock(int argc, char **argv)
 }
 
 
+__private_extern__
 void
 do_unlock(int argc, char **argv)
 {
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@
  * 
@@ -44,7 +44,9 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include <dnsinfo.h>
 
+__private_extern__
 void
 do_checkReachability(int argc, char **argv)
 {
@@ -161,6 +163,90 @@ do_checkReachability(int argc, char **argv)
 }
 
 
+__private_extern__
+void
+do_showDNSConfiguration(int argc, char **argv)
+{
+       dns_config_t    *dns_config;
+
+       dns_config = dns_configuration_copy();
+       if (dns_config) {
+               int     n;
+
+               SCPrint(TRUE, stdout, CFSTR("DNS configuration\n"));
+
+               for (n = 0; n < dns_config->n_resolver; n++) {
+                       int             i;
+                       dns_resolver_t  *resolver       = dns_config->resolver[n];
+
+                       SCPrint(TRUE, stdout, CFSTR("\nresolver #%d\n"), n + 1);
+
+                       if (resolver->domain != NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("  domain : %s\n"), resolver->domain);
+                       }
+
+                       for (i = 0; i < resolver->n_search; i++) {
+                               SCPrint(TRUE, stdout, CFSTR("  search domain[%d] : %s\n"), i, resolver->search[i]);
+                       }
+
+                       for (i = 0; i < resolver->n_nameserver; i++) {
+                               char    buf[128];
+
+                               _SC_sockaddr_to_string(resolver->nameserver[i], buf, sizeof(buf));
+                               SCPrint(TRUE, stdout, CFSTR("  nameserver[%d] : %s\n"), i, buf);
+                       }
+
+                       for (i = 0; i < resolver->n_sortaddr; i++) {
+                               SCPrint(TRUE, stdout, CFSTR("  sortaddr[%d] : %s/%s\n"),
+                                       i,
+                                       inet_ntoa(resolver->sortaddr[i]->address),
+                                       inet_ntoa(resolver->sortaddr[i]->mask));
+                       }
+
+                       if (resolver->options != NULL) {
+                               SCPrint(TRUE, stdout, CFSTR("  options : %s\n"), resolver->options);
+                       }
+
+                       if (resolver->port != 0) {
+                               SCPrint(TRUE, stdout, CFSTR("  port    : %hd\n"), ntohs(resolver->port));
+                       }
+
+                       if (resolver->timeout != 0) {
+                               SCPrint(TRUE, stdout, CFSTR("  timeout : %d\n"), resolver->timeout);
+                       }
+
+                       if (resolver->search_order != 0) {
+                               SCPrint(TRUE, stdout, CFSTR("  order   : %d\n"), resolver->search_order);
+                       }
+               }
+
+               dns_configuration_free(dns_config);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("No DNS configuration available\n"));
+       }
+
+       exit(0);
+}
+
+
+__private_extern__
+void
+do_showProxyConfiguration(int argc, char **argv)
+{
+       CFDictionaryRef proxies;
+
+       proxies = SCDynamicStoreCopyProxies(NULL);
+       if (proxies != NULL) {
+               SCPrint(TRUE, stdout, CFSTR("%@\n"), proxies);
+       } else {
+               SCPrint(TRUE, stdout, CFSTR("No proxy configuration available\n"));
+       }
+
+       exit(0);
+}
+
+
+__private_extern__
 void
 do_snapshot(int argc, char **argv)
 {
@@ -185,6 +271,7 @@ waitTimeout(int sigraised)
 }
 
 
+__private_extern__
 void
 do_wait(char *waitKey, int timeout)
 {
@@ -193,14 +280,14 @@ do_wait(char *waitKey, int timeout)
        CFMutableArrayRef       keys;
 
        store = SCDynamicStoreCreate(NULL, CFSTR("scutil (wait)"), waitKeyFound, NULL);
-       if (!store) {
+       if (store == NULL) {
                SCPrint(TRUE, stderr,
                        CFSTR("SCDynamicStoreCreate() failed: %s\n"), SCErrorString(SCError()));
                exit(1);
        }
 
        keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-       key  = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingMacRoman);
+       key  = CFStringCreateWithCString(NULL, waitKey, kCFStringEncodingUTF8);
        CFArrayAppendValue(keys, key);
 
        if (!SCDynamicStoreSetNotificationKeys(store, keys, NULL)) {
@@ -225,7 +312,7 @@ do_wait(char *waitKey, int timeout)
        }
        CFRelease(key);
 
-       if (waitTimeout > 0) {
+       if (timeout > 0) {
                signal(SIGALRM, waitTimeout);
                bzero(&itv, sizeof(itv));
                itv.it_value.tv_sec = timeout;
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@
  * 
 
 __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