From d49d4c8153e0d4ad98ce995c3e488a8b52df9a8e Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 22 Jun 2009 23:47:58 +0000 Subject: [PATCH] Libinfo-324.tar.gz --- APPLE_LICENSE | 372 ++ Makefile | 80 +- Makefile.postamble | 4 - Makefile.preamble | 6 - PB.project | 40 - dns.subproj/Makefile | 65 +- dns.subproj/Makefile.dist | 112 + dns.subproj/Makefile.postamble | 7 - dns.subproj/Makefile.preamble | 29 - dns.subproj/PB.project | 41 - dns.subproj/gethnamaddr.c | 825 ----- dns.subproj/getnetbyaddr.c | 80 - dns.subproj/getnetbyname.c | 87 - dns.subproj/getnetent.c | 194 - dns.subproj/getnetnamadr.c | 335 -- dns.subproj/inet_addr.c | 206 ++ dns.subproj/nsap_addr.c | 119 + dns.subproj/res_comp.c | 5 +- dns.subproj/res_data.c | 7 +- dns.subproj/res_debug.c | 8 +- dns.subproj/res_init.c | 6 +- dns.subproj/res_mkquery.c | 6 +- dns.subproj/res_query.c | 6 +- .../lu_printer.c => dns.subproj/res_running.c | 44 +- dns.subproj/res_send.c | 21 +- dns.subproj/sethostent.c | 85 - gen.subproj/Makefile | 134 +- gen.subproj/Makefile.postamble | 158 - gen.subproj/Makefile.preamble | 41 - gen.subproj/PB.project | 64 - gen.subproj/aliasdb.c | 54 - gen.subproj/ether_addr.c | 128 +- gen.subproj/fstab.c | 337 -- gen.subproj/getgrent.c | 205 -- gen.subproj/gethostbyname.3 | 250 +- gen.subproj/getifaddrs.3 | 40 +- gen.subproj/getifaddrs.c | 11 +- gen.subproj/getipnodebyname.3 | 118 +- gen.subproj/getnetent.3 | 71 +- gen.subproj/getproto.c | 78 - gen.subproj/getprotoent.3 | 45 +- gen.subproj/getprotoent.c | 148 - gen.subproj/getprotoname.c | 85 - gen.subproj/getpwent.c | 605 ---- gen.subproj/getservbyname.c | 88 - gen.subproj/getservbyport.c | 83 - gen.subproj/getservent.3 | 45 +- gen.subproj/getservent.c | 150 - gen.subproj/if_indextoname.3 | 201 +- gen.subproj/initgroups.c | 93 - gen.subproj/ip6opt.c | 2 - gen.subproj/map_v4v6.c | 5 +- gen.subproj/printerdb.c | 279 -- lookup.subproj/DSlibinfoMIG.defs | 77 - lookup.subproj/Makefile | 121 +- lookup.subproj/Makefile.postamble | 52 - lookup.subproj/Makefile.preamble | 17 - lookup.subproj/PB.project | 61 - lookup.subproj/_lu_types.x | 247 -- lookup.subproj/cache_module.c | 552 +++ lookup.subproj/ds_module.c | 2332 ++++++++++++ lookup.subproj/file_module.c | 1758 +++++++++ lookup.subproj/gai_strerror.3 | 20 +- lookup.subproj/getaddrinfo.3 | 127 +- lookup.subproj/getaddrinfo.c | 1733 --------- lookup.subproj/getfsent.3 | 62 +- lookup.subproj/getgrent.3 | 294 +- lookup.subproj/getgrouplist.3 | 9 +- lookup.subproj/getnameinfo.3 | 96 +- lookup.subproj/getnetgrent.3 | 14 +- lookup.subproj/getpwent.3 | 331 +- lookup.subproj/ils.c | 711 ++++ lookup.subproj/{lu_bootparam.c => ils.h} | 32 +- lookup.subproj/kvbuf.c | 963 +++++ lookup.subproj/kvbuf.h | 25 +- lookup.subproj/libinfo.c | 3184 +++++++++++++++++ lookup.subproj/libinfo.h | 54 + lookup.subproj/lookup.defs | 84 - lookup.subproj/lookup_types.h | 47 - lookup.subproj/lu_alias.c | 204 -- lookup.subproj/lu_bootp.c | 51 - lookup.subproj/lu_fstab.c | 268 -- lookup.subproj/lu_group.c | 904 ----- lookup.subproj/lu_host.c | 1404 -------- lookup.subproj/lu_host.h | 52 - lookup.subproj/lu_host_async.c | 507 --- lookup.subproj/lu_netgroup.c | 277 -- lookup.subproj/lu_network.c | 252 -- lookup.subproj/lu_overrides.h | 92 - lookup.subproj/lu_protocol.c | 238 -- lookup.subproj/lu_rpc.c | 254 -- lookup.subproj/lu_service.c | 458 --- lookup.subproj/lu_user.c | 555 --- lookup.subproj/lu_utils.c | 2461 ------------- lookup.subproj/lu_utils.h | 121 - lookup.subproj/mdns_module.c | 1960 ++++++++++ lookup.subproj/netdb.h | 56 +- lookup.subproj/netdb_async.h | 1 + lookup.subproj/search_module.c | 1185 ++++++ lookup.subproj/si_data.c | 184 + ...{DSlibinfoMIGAsyncReply.defs => si_data.h} | 54 +- lookup.subproj/si_getaddrinfo.c | 1338 +++++++ lookup.subproj/si_module.c | 1138 ++++++ lookup.subproj/si_module.h | 352 ++ lookup.subproj/thread_data.c | 211 ++ .../{DSlibinfoMIG_types.h => thread_data.h} | 36 +- membership.subproj/DSmemberdMIG.defs | 1 - membership.subproj/Makefile | 61 +- membership.subproj/Makefile.postamble | 11 - membership.subproj/Makefile.preamble | 18 - membership.subproj/PB.project | 34 - membership.subproj/mbr_check_membership.3 | 6 +- membership.subproj/mbr_uid_to_uuid.3 | 11 + membership.subproj/mbr_uid_to_uuid_so.3 | 1 - membership.subproj/membership.c | 249 +- membership.subproj/membership.h | 182 +- membership.subproj/membershipPriv.h | 1 - netinfo.subproj/Makefile | 48 +- netinfo.subproj/Makefile.preamble | 5 - netinfo.subproj/PB.project | 23 - nis.subproj/Makefile | 55 +- nis.subproj/Makefile.postamble | 133 - nis.subproj/Makefile.preamble | 8 - nis.subproj/PB.project | 74 - nis.subproj/getdomainname.c | 5 +- nis.subproj/yp.8 | 18 +- nis.subproj/ypclnt.3 | 5 +- rpc.subproj/DISCLAIMER | 28 + rpc.subproj/Makefile | 96 +- rpc.subproj/Makefile.inc | 115 + rpc.subproj/Makefile.postamble | 224 -- rpc.subproj/Makefile.preamble | 15 - rpc.subproj/PB.project | 91 - rpc.subproj/README | 233 ++ rpc.subproj/bindresvport.3 | 98 +- rpc.subproj/clnt_udp.c | 9 +- rpc.subproj/getrpcent.3 | 63 +- rpc.subproj/getrpcent.c | 33 +- rpc.subproj/getrpcport.3 | 13 +- rpc.subproj/pmap_getport.c | 1 - rpc.subproj/svc.h | 7 + rpc.subproj/xdr.3 | 6 +- rpc.subproj/xdr.c | 2 +- util.subproj/Makefile | 69 +- util.subproj/Makefile.postamble | 122 - util.subproj/Makefile.preamble | 8 - util.subproj/PB.project | 21 - util.subproj/hton.c | 58 +- util.subproj/pwcache.c | 122 - util.subproj/rcmd.c | 3 +- 150 files changed, 19149 insertions(+), 17161 deletions(-) create mode 100644 APPLE_LICENSE delete mode 100644 Makefile.postamble delete mode 100644 Makefile.preamble delete mode 100644 PB.project create mode 100644 dns.subproj/Makefile.dist delete mode 100644 dns.subproj/Makefile.postamble delete mode 100644 dns.subproj/Makefile.preamble delete mode 100644 dns.subproj/PB.project delete mode 100644 dns.subproj/gethnamaddr.c delete mode 100644 dns.subproj/getnetbyaddr.c delete mode 100644 dns.subproj/getnetbyname.c delete mode 100644 dns.subproj/getnetent.c delete mode 100644 dns.subproj/getnetnamadr.c create mode 100644 dns.subproj/inet_addr.c create mode 100644 dns.subproj/nsap_addr.c rename lookup.subproj/lu_printer.c => dns.subproj/res_running.c (68%) delete mode 100644 dns.subproj/sethostent.c delete mode 100644 gen.subproj/Makefile.postamble delete mode 100644 gen.subproj/Makefile.preamble delete mode 100644 gen.subproj/PB.project delete mode 100644 gen.subproj/aliasdb.c delete mode 100644 gen.subproj/fstab.c delete mode 100644 gen.subproj/getgrent.c delete mode 100644 gen.subproj/getproto.c delete mode 100644 gen.subproj/getprotoent.c delete mode 100644 gen.subproj/getprotoname.c delete mode 100644 gen.subproj/getpwent.c delete mode 100644 gen.subproj/getservbyname.c delete mode 100644 gen.subproj/getservbyport.c delete mode 100644 gen.subproj/getservent.c delete mode 100644 gen.subproj/initgroups.c delete mode 100644 gen.subproj/printerdb.c delete mode 100644 lookup.subproj/DSlibinfoMIG.defs delete mode 100644 lookup.subproj/Makefile.postamble delete mode 100644 lookup.subproj/Makefile.preamble delete mode 100644 lookup.subproj/PB.project delete mode 100644 lookup.subproj/_lu_types.x create mode 100644 lookup.subproj/cache_module.c create mode 100644 lookup.subproj/ds_module.c create mode 100644 lookup.subproj/file_module.c delete mode 100644 lookup.subproj/getaddrinfo.c create mode 100644 lookup.subproj/ils.c rename lookup.subproj/{lu_bootparam.c => ils.h} (75%) create mode 100644 lookup.subproj/kvbuf.c create mode 100644 lookup.subproj/libinfo.c create mode 100644 lookup.subproj/libinfo.h delete mode 100644 lookup.subproj/lookup.defs delete mode 100644 lookup.subproj/lookup_types.h delete mode 100644 lookup.subproj/lu_alias.c delete mode 100644 lookup.subproj/lu_bootp.c delete mode 100644 lookup.subproj/lu_fstab.c delete mode 100644 lookup.subproj/lu_group.c delete mode 100644 lookup.subproj/lu_host.c delete mode 100644 lookup.subproj/lu_host.h delete mode 100644 lookup.subproj/lu_host_async.c delete mode 100644 lookup.subproj/lu_netgroup.c delete mode 100644 lookup.subproj/lu_network.c delete mode 100644 lookup.subproj/lu_overrides.h delete mode 100644 lookup.subproj/lu_protocol.c delete mode 100644 lookup.subproj/lu_rpc.c delete mode 100644 lookup.subproj/lu_service.c delete mode 100644 lookup.subproj/lu_user.c delete mode 100644 lookup.subproj/lu_utils.c delete mode 100644 lookup.subproj/lu_utils.h create mode 100644 lookup.subproj/mdns_module.c create mode 100644 lookup.subproj/search_module.c create mode 100644 lookup.subproj/si_data.c rename lookup.subproj/{DSlibinfoMIGAsyncReply.defs => si_data.h} (54%) create mode 100644 lookup.subproj/si_getaddrinfo.c create mode 100644 lookup.subproj/si_module.c create mode 100644 lookup.subproj/si_module.h create mode 100644 lookup.subproj/thread_data.c rename lookup.subproj/{DSlibinfoMIG_types.h => thread_data.h} (56%) delete mode 100644 membership.subproj/DSmemberdMIG.defs delete mode 100644 membership.subproj/Makefile.postamble delete mode 100644 membership.subproj/Makefile.preamble delete mode 100644 membership.subproj/PB.project delete mode 100644 membership.subproj/mbr_uid_to_uuid_so.3 delete mode 100644 netinfo.subproj/Makefile.preamble delete mode 100644 netinfo.subproj/PB.project delete mode 100644 nis.subproj/Makefile.postamble delete mode 100644 nis.subproj/Makefile.preamble delete mode 100644 nis.subproj/PB.project create mode 100644 rpc.subproj/DISCLAIMER create mode 100644 rpc.subproj/Makefile.inc delete mode 100644 rpc.subproj/Makefile.postamble delete mode 100644 rpc.subproj/Makefile.preamble delete mode 100644 rpc.subproj/PB.project create mode 100644 rpc.subproj/README delete mode 100644 util.subproj/Makefile.postamble delete mode 100644 util.subproj/Makefile.preamble delete mode 100644 util.subproj/PB.project delete mode 100644 util.subproj/pwcache.c diff --git a/APPLE_LICENSE b/APPLE_LICENSE new file mode 100644 index 0000000..84687a4 --- /dev/null +++ b/APPLE_LICENSE @@ -0,0 +1,372 @@ +APPLE PUBLIC SOURCE LICENSE +Version 1.1 - April 19,1999 + +Please read this License carefully before downloading this software. +By downloading and 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") publicly announces as +subject to this Apple Public Source License 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 1.1 (or subsequent version thereof), as it may +be revised from time to time by Apple ("License"). As used in this +License: + +1.1 "Affected Original Code" means only those specific portions of +Original Code that allegedly infringe upon any party's intellectual +property rights or are otherwise the subject of a claim of +infringement. + +1.2 "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.3 "Covered Code" means the Original Code, Modifications, the +combination of Original Code and any Modifications, and/or any +respective portions thereof. + +1.4 "Deploy" means to use, sublicense or distribute Covered Code other +than for Your internal research and development (R&D), and includes +without limitation, any and all internal use or distribution of +Covered Code within Your business or organization except for R&D use, +as well as direct or indirect sublicensing or distribution of Covered +Code by You to any third party in any form or manner. + +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 Covered Code. 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 You may use, copy, modify and distribute Original Code, with or +without Modifications, solely for Your internal research and +development, provided that You must in each instance: + +(a) 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; + +(b) include a copy of this License with every copy of Source Code of +Covered Code and documentation You distribute, 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; and + +(c) completely and accurately document all Modifications that you have +made and the date of each such Modification, designate the version of +the Original Code you used, prominently include a file carrying such +information with the Modifications, and duplicate the notice in +Exhibit A in each file of the Source Code of all such Modifications. + +2.2 You may Deploy Covered Code, provided that You must in each + instance: + +(a) satisfy all the conditions of Section 2.1 with respect to the +Source Code of the Covered Code; + +(b) make all Your Deployed Modifications publicly available in Source +Code form via electronic distribution (e.g. download from a web site) +under the terms of this License and subject to the license grants set +forth in Section 3 below, and any additional terms You may choose to +offer under Section 6. You must continue to make the Source Code of +Your Deployed Modifications available for as long as you Deploy the +Covered Code or twelve (12) months from the date of initial +Deployment, whichever is longer; + +(c) if You Deploy Covered Code containing Modifications made by You, +inform others of how to obtain those Modifications by filling out and +submitting the information found at +http://www.apple.com/publicsource/modifications.html, if available; +and + +(d) if You Deploy Covered Code in object code, executable form only, +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. + +3. Your Grants. In consideration of, and as a condition to, the +licenses granted to You under this License: + +(a) You hereby grant to Apple and all third parties a non-exclusive, +royalty-free license, under Your Applicable Patent Rights and other +intellectual property rights owned or controlled by You, to use, +reproduce, modify, distribute and Deploy Your Modifications of the +same scope and extent as Apple's licenses under Sections 2.1 and 2.2; +and + +(b) You hereby grant to Apple and its subsidiaries a non-exclusive, +worldwide, royalty-free, perpetual and irrevocable license, under Your +Applicable Patent Rights and other intellectual property rights owned +or controlled by You, to use, reproduce, execute, compile, display, +perform, modify or have modified (for Apple and/or its subsidiaries), +sublicense and distribute Your Modifications, in any form, through +multiple tiers of distribution. + +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. 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 +harmless for any liability incurred by or claims asserted against +Apple 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 Original Code may contain in whole or +in part pre-release, untested, or not fully tested works. The +Original 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 Original Code, or any portion +thereof, is at Your sole and entire risk. THE ORIGINAL CODE IS +PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND +AND APPLE AND APPLE'S LICENSOR(S) (FOR THE PURPOSES OF SECTIONS 8 AND +9, APPLE AND APPLE'S LICENSOR(S) ARE COLLECTIVELY REFERRED TO AS +"APPLE") EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +AND/OR CONDITIONS OF MERCHANTABILITY OR SATISFACTORY QUALITY AND +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY +RIGHTS. APPLE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE +ORIGINAL CODE WILL MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF +THE ORIGINAL CODE WILL BE UNINTERRUPTED OR ERROR- FREE, OR THAT +DEFECTS IN THE ORIGINAL CODE WILL BE CORRECTED. NO ORAL OR WRITTEN +INFORMATION OR ADVICE GIVEN BY APPLE OR AN APPLE AUTHORIZED +REPRESENTATIVE SHALL CREATE A WARRANTY OR IN ANY WAY INCREASE THE +SCOPE OF THIS WARRANTY. You acknowledge that the Original 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 Original Code could lead to death, +personal injury, or severe physical or environmental damage. + +9. Liability. + +9.1 Infringement. If any portion of, or functionality implemented by, +the Original Code becomes the subject of a claim of infringement, +Apple may, at its option: (a) attempt to procure the rights necessary +for Apple and You to continue using the Affected Original Code; (b) +modify the Affected Original Code so that it is no longer infringing; +or (c) suspend Your rights to use, reproduce, modify, sublicense and +distribute the Affected Original Code until a final determination of +the claim is made by a court or governmental administrative agency of +competent jurisdiction and Apple lifts the suspension as set forth +below. Such suspension of rights will be effective immediately upon +Apple's posting of a notice to such effect on the Apple web site that +is used for implementation of this License. Upon such final +determination being made, if Apple is legally able, without the +payment of a fee or royalty, to resume use, reproduction, +modification, sublicensing and distribution of the Affected Original +Code, Apple will lift the suspension of rights to the Affected +Original Code by posting a notice to such effect on the Apple web site +that is used for implementation of this License. If Apple suspends +Your rights to Affected Original Code, nothing in this License shall +be construed to restrict You, at Your option and subject to applicable +law, from replacing the Affected Original Code with non-infringing +code or independently negotiating for necessary rights from such third +party. + +9.2 LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES SHALL APPLE 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 ORIGINAL CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY +OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY +OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF +ANY REMEDY. In no event shall Apple's total liability to You for all +damages 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 OS X", "Mac +OS X Server" or any other trademarks or trade names belonging to Apple +(collectively "Apple Marks") and no Apple Marks may be used to endorse +or promote products derived from the Original Code other than as +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. 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. Apple's development, use, +reproduction, modification, sublicensing and distribution of Covered +Code will not be subject to this License. + +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. + +12.2 Effect of Termination. Upon termination, You agree to +immediately stop any further use, reproduction, modification, +sublicensing and distribution of the Covered Code and to destroy all +copies of the Covered Code that are in your possession or control. +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. Neither party will be +liable to the 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 either 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 You and Apple, 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 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 Apple Computer, Inc. All Rights +Reserved. This file contains Original Code and/or Modifications of +Original Code as defined in and that are subject to the Apple Public +Source License Version 1.1 (the "License"). You may not use this file +except in compliance with the License. Please obtain a copy of the +License at http://www.apple.com/publicsource and read it before using +this file. + +The Original Code and all software distributed under the License are +distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the +License for the specific language governing rights and limitations +under the License." diff --git a/Makefile b/Makefile index 35007d3..bd8fd83 100644 --- a/Makefile +++ b/Makefile @@ -1,56 +1,24 @@ -# -# 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 = info - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Library - -SUBPROJECTS = dns.subproj gen.subproj lookup.subproj membership.subproj\ - netinfo.subproj nis.subproj rpc.subproj util.subproj - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CURRENTLY_ACTIVE_VERSION = YES -DEPLOY_WITH_VERSION_NAME = A -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = library.make -NEXTSTEP_INSTALLDIR = /usr/local/lib/system -WINDOWS_INSTALLDIR = /Developer/Libraries -PDO_UNIX_INSTALLDIR = /lib -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - - - -NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include - -WINDOWS_PUBLIC_HEADERS_DIR = /Developer/Headers/$(NAME) - -PDO_UNIX_PUBLIC_HEADERS_DIR = /Developer/Headers/$(NAME) - -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 +Project = info +ProductType = staticlib +Install_Dir = /usr/local/lib/system +BuildDebug = YES +BuildProfile = YES + +DIRS = dns gen lookup membership netinfo nis rpc util + +SubProjects = $(foreach DIR, $(DIRS), $(DIR).subproj) + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +after_install: + $(LIBTOOL) -static -o $(SYMROOT)/libinfo.a \ + $(foreach DIR, $(DIRS), $(SYMROOT)/lib$(DIR).a) + $(LIBTOOL) -static -o $(SYMROOT)/libinfo_debug.a \ + $(foreach DIR, $(DIRS), $(SYMROOT)/lib$(DIR)_debug.a) + $(LIBTOOL) -static -o $(SYMROOT)/libinfo_profile.a \ + $(foreach DIR, $(DIRS), $(SYMROOT)/lib$(DIR)_profile.a) + $(INSTALL_DIRECTORY) $(DSTROOT)/usr/local/lib/system + $(INSTALL_LIBRARY) $(SYMROOT)/libinfo.a $(DSTROOT)/usr/local/lib/system + $(INSTALL_LIBRARY) $(SYMROOT)/libinfo_debug.a $(DSTROOT)/usr/local/lib/system + $(INSTALL_LIBRARY) $(SYMROOT)/libinfo_profile.a $(DSTROOT)/usr/local/lib/system + $(RMDIR) $(DSTROOT)/scratch diff --git a/Makefile.postamble b/Makefile.postamble deleted file mode 100644 index 0e9365d..0000000 --- a/Makefile.postamble +++ /dev/null @@ -1,4 +0,0 @@ -override DEBUG_SUFFIX = _debug -PRODUCTS += $(LIBRARY_PREFIX)$(NAME)$(DEBUG_SUFFIX)$(LIBRARY_EXT) -PRODUCTS += $(LIBRARY_PREFIX)$(NAME)$(PROFILE_SUFFIX)$(LIBRARY_EXT) -RECURSIVE_FLAGS += "LINK_SUBPROJECTS = NO" diff --git a/Makefile.preamble b/Makefile.preamble deleted file mode 100644 index 25d484e..0000000 --- a/Makefile.preamble +++ /dev/null @@ -1,6 +0,0 @@ -LIBRARY_STYLE = STATIC -STRIP_ON_INSTALL = NO -BEFORE_INSTALL += debug profile -override LINK_SUBPROJECTS = NO - -# export CCOMPILER = /usr/bin/gcc-X.X diff --git a/PB.project b/PB.project deleted file mode 100644 index 314f8be..0000000 --- a/PB.project +++ /dev/null @@ -1,40 +0,0 @@ -{ - CURRENTLY_ACTIVE_VERSION = YES; - DEPLOY_WITH_VERSION_NAME = A; - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - FRAMEWORKS = (); - H_FILES = (); - OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); - SUBPROJECTS = ( - dns.subproj, - gen.subproj, - lookup.subproj, - membership.subproj, - netinfo.subproj, - nis.subproj, - rpc.subproj, - util.subproj - ); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - NEXTSTEP_INSTALLDIR = /usr/local/lib/system; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - NEXTSTEP_PUBLICHEADERSDIR = /usr/include; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; - PDO_UNIX_INSTALLDIR = /lib; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PDO_UNIX_PUBLICHEADERSDIR = "/Developer/Headers/$(NAME)"; - PROJECTNAME = info; - PROJECTTYPE = Library; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_INSTALLDIR = /Developer/Libraries; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; - WINDOWS_PUBLICHEADERSDIR = "/Developer/Headers/$(NAME)"; -} diff --git a/dns.subproj/Makefile b/dns.subproj/Makefile index 3192331..356ebaf 100644 --- a/dns.subproj/Makefile +++ b/dns.subproj/Makefile @@ -1,55 +1,18 @@ -# -# Generated by the NeXT 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. -# +Project = dns +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES -NAME = dns +CFILES = herror.c res_comp.c res_data.c res_debug.c\ + res_init.c res_mkquery.c res_query.c res_send.c -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component +Extra_CC_Flags = -Wall -fno-common -I. \ + -I../gen.subproj -I../lookup.subproj \ + -DUSE_OPTIONS_H -D__DARWIN_NON_CANCELABLE=1 -HFILES = inet.h nameser8_compat.h options.h portability.h resolv8_compat.h +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make -CFILES = gethnamaddr.c getnetbyaddr.c getnetbyname.c getnetent.c\ - getnetnamadr.c herror.c res_comp.c res_data.c res_debug.c\ - res_init.c res_mkquery.c res_query.c res_send.c sethostent.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -NEXTSTEP_INSTALLDIR = /Local/Developer/System -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - -NEXTSTEP_PB_CFLAGS = -DUSE_OPTIONS_H -PUBLIC_HEADERS = resolv8_compat.h nameser8_compat.h - - - -NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include - -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 +after_install: + $(INSTALL_DIRECTORY) "$(DSTROOT)"/usr/include/arpa + $(INSTALL_FILE) inet.h "$(DSTROOT)"/usr/include/arpa/inet.h diff --git a/dns.subproj/Makefile.dist b/dns.subproj/Makefile.dist new file mode 100644 index 0000000..385c8a9 --- /dev/null +++ b/dns.subproj/Makefile.dist @@ -0,0 +1,112 @@ +# +# from @(#)Makefile 5.16 (Berkeley) 3/14/88 +# $Id: Makefile.dist,v 1.1 1999/04/13 23:15:30 wsanchez Exp $ +# + +## ++Copyright++ 1988, 1995 +## - +## Copyright (c) 1988, 1995 +## The Regents of the University of California. All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in the +## documentation and/or other materials provided with the distribution. +## 3. All advertising materials mentioning features or use of this software +## must display the following acknowledgement: +## This product includes software developed by the University of +## California, Berkeley and its contributors. +## 4. Neither the name of the University nor the names of its contributors +## may be used to endorse or promote products derived from this software +## without specific prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +## ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +## SUCH DAMAGE. +## - +## Portions Copyright (c) 1993 by Digital Equipment Corporation. +## +## Permission to use, copy, modify, and distribute this software for any +## purpose with or without fee is hereby granted, provided that the above +## copyright notice and this permission notice appear in all copies, and that +## the name of Digital Equipment Corporation not be used in advertising or +## publicity pertaining to distribution of the document or software without +## specific, written prior permission. +## +## THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL +## WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT +## CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +## SOFTWARE. +## - +## --Copyright-- + +DESTDIR = +DESTLIB = /usr/lib +CC= cc +SHELL= /bin/sh +CDEBUG= -O +INCL = ../include +COMPINCL = ../compat/include +AR= ar cru +RANLIB= ranlib +DEFS= +LOCDEFS= -DUSE_OPTIONS_H + +AROBJS= ${ARPREF} ${OBJS} ${ARSUFF} + +CFLAGS= ${CDEBUG} -I${INCL} -I${COMPINCL} ${DEFS} ${LOCDEFS} + +SRCS= herror.c res_debug.c \ + res_comp.c res_init.c res_mkquery.c res_query.c res_send.c \ + getnetbyaddr.c getnetbyname.c getnetent.c getnetnamadr.c \ + gethnamaddr.c sethostent.c nsap_addr.c inet_addr.c hostnamelen.c + +OBJS= herror.o res_debug.o \ + res_comp.o res_init.o res_mkquery.o res_query.o res_send.o \ + getnetbyaddr.o getnetbyname.o getnetent.o getnetnamadr.o \ + gethnamaddr.o sethostent.o nsap_addr.o inet_addr.o hostnamelen.o + +all: libresolv.a + +libresolv.a: ${OBJS} + ${AR} libresolv.a ${AROBJS} + $(RANLIB) libresolv.a + +install: ${DESTDIR}${DESTLIB}/libresolv.a + +${DESTDIR}${DESTLIB}/libresolv.a: libresolv.a + ${INSTALL} -c -o bin -g bin -m 644 libresolv.a ${DESTDIR}${DESTLIB}/ + ( cd ${DESTDIR}${DESTLIB} ; $(RANLIB) libresolv.a ) + +.c.o: + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + -${LDS} ld -x -r $*.o + ${LDS} mv a.out $*.o + +clean: FRC + rm -f errs a.out core libresolv.a tags .depend + rm -f *.o *.BAK *.CKP *~ *.orig + +depend: FRC + mkdep ${CPPFLAGS} -I${INCL} -I${COMPINCL} ${DEFS} ${SRCS} + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/dns.subproj/Makefile.postamble b/dns.subproj/Makefile.postamble deleted file mode 100644 index e0bdfec..0000000 --- a/dns.subproj/Makefile.postamble +++ /dev/null @@ -1,7 +0,0 @@ -arpa_headers: $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(ARPA_HEADER_DIR_SUFFIX) - $(RM) -f $(foreach header, $(ARPA_SYMLINKED_HEADERS), $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(ARPA_HEADER_DIR_SUFFIX)/$(header)) - $(LN) -s $(foreach header, $(ARPA_SYMLINKED_HEADERS), ../$(header)) $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(ARPA_HEADER_DIR_SUFFIX) - $(SILENT) $(FASTCP) $(ARPA_HEADERS) $(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(ARPA_HEADER_DIR_SUFFIX) - -$(DSTROOT)$(PUBLIC_HDR_INSTALLDIR)$(ARPA_HEADER_DIR_SUFFIX): - $(MKDIRS) $@ diff --git a/dns.subproj/Makefile.preamble b/dns.subproj/Makefile.preamble deleted file mode 100644 index f88e7ff..0000000 --- a/dns.subproj/Makefile.preamble +++ /dev/null @@ -1,29 +0,0 @@ -OTHER_CFLAGS = \ - -D__DARWIN_NON_CANCELABLE=1 \ - -Dsethostent=_res_sethostent \ - -Dgethostent=_res_gethostent \ - -Dendhostent=_res_endhostent \ - -Dgethostbyname=_res_gethostbyname \ - -Dgethostbyaddr=_res_gethostbyaddr \ - -Dsetnetent=_old_setnetent \ - -Dgetnetent=_old_getnetent \ - -Dendnetent=_old_endnetent \ - -Dgetnetbyname=_res_getnetbyname \ - -Dgetnetbyaddr=_res_getnetbyaddr \ - -D_sethtent=_old_sethostent \ - -D_gethtent=_old_gethostent \ - -D_endhtent=_old_endhostent \ - -D_gethtbyname=_old_gethostbyname \ - -D_gethtbyaddr=_old_gethostbyaddr \ - -D_getnetbyname=_old_getnetbyname \ - -D_getnetbyaddr=_old_getnetbyaddr - -PUBLIC_HEADER_DIR_SUFFIX = -ARPA_HEADER_DIR_SUFFIX = /arpa -ARPA_HEADERS = inet.h -ARPA_SYMLINKED_HEADERS = nameser8_compat.h -AFTER_INSTALLHDRS += arpa_headers - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/dns.subproj/PB.project b/dns.subproj/PB.project deleted file mode 100644 index 48b050e..0000000 --- a/dns.subproj/PB.project +++ /dev/null @@ -1,41 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = (inet.h, nameser8_compat.h, options.h, portability.h, resolv8_compat.h); - OTHER_LINKED = ( - gethnamaddr.c, - getnetbyaddr.c, - getnetbyname.c, - getnetent.c, - getnetnamadr.c, - herror.c, - res_comp.c, - res_data.c, - res_debug.c, - res_init.c, - res_mkquery.c, - res_query.c, - res_send.c, - sethostent.c - ); - OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); - PUBLIC_HEADERS = (resolv8_compat.h, nameser8_compat.h); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /bin/gnumake; - NEXTSTEP_COMPILEROPTIONS = "-DUSE_OPTIONS_H"; - NEXTSTEP_INSTALLDIR = /Local/Developer/System; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - NEXTSTEP_PUBLICHEADERSDIR = /usr/include; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PROJECTNAME = dns; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/dns.subproj/gethnamaddr.c b/dns.subproj/gethnamaddr.c deleted file mode 100644 index f00f3dd..0000000 --- a/dns.subproj/gethnamaddr.c +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * ++Copyright++ 1985, 1988, 1993 - * - - * Copyright (c) 1985, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - - * --Copyright-- - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: gethnamaddr.c,v 1.9 2004/10/07 17:33:33 majka Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifndef LOG_AUTH -# define LOG_AUTH 0 -#endif - -#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ - -#if defined(BSD) && (BSD >= 199103) -# include -#else -# include "portability.h" -#endif -#if defined(USE_OPTIONS_H) -# include "options.h" -#endif - -#define MAXALIASES 35 -#define MAXADDRS 35 -#define MAXHOSTBUF 8*1024 - -static const char AskedForGot[] = - "gethostby*.getanswer: asked for \"%s\", got \"%s\""; - -static char *h_addr_ptrs[MAXADDRS + 1]; -#ifdef NOTDEF -static struct hostent *gethostbyname_ipv4 __P((const char *)); -#endif -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char *hostbuf = NULL; -static struct in_addr host_addr; -static FILE *hostf = NULL; -static int stayopen = 0; - -#ifdef RESOLVSORT -static void addrsort __P((char **, int)); -#endif - -#if PACKETSZ > 1024 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 1024 -#endif - -typedef union { - HEADER hdr; - u_char buf[MAXPACKET]; -} querybuf; - -typedef union { - int32_t al; - char ac; -} align; - -extern int h_errno; - -#ifdef DEBUG -static void -dprintf(msg, num) - char *msg; - int num; -{ - if (_res.options & RES_DEBUG) { - int save = errno; - - printf(msg, num); - errno = save; - } -} -#else -# define dprintf(msg, num) /*nada*/ -#endif - -static struct hostent * -getanswer(answer, anslen, qname, qclass, qtype) - const querybuf *answer; - int anslen; - const char *qname; - int qclass, qtype; -{ - register const HEADER *hp; - register const u_char *cp; - register int n; - const u_char *eom; - char *bp, **ap, **hap; - int type, class, buflen, ancount, qdcount; - int haveanswer, had_error; - int toobig = 0; - char tbuf[MAXDNAME+1]; - const char *tname; - - if (hostbuf == NULL) { - hostbuf = malloc(MAXHOSTBUF); - if (hostbuf == NULL) - return (NULL); - } - buflen = MAXHOSTBUF; - - tname = qname; - host.h_name = NULL; - eom = answer->buf + anslen; - /* - * find first satisfactory answer - */ - hp = &answer->hdr; - ancount = ntohs(hp->ancount); - qdcount = ntohs(hp->qdcount); - bp = hostbuf; - cp = answer->buf + HFIXEDSZ; - if (qdcount != 1) { - h_errno = NO_RECOVERY; - return (NULL); - } - if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) { - h_errno = NO_RECOVERY; - return (NULL); - } - cp += n + QFIXEDSZ; - if (qtype == T_A) { - /* res_send() has already verified that the query name is the - * same as the one we sent; this just gets the expanded name - * (i.e., with the succeeding search-domain tacked on). - */ - n = strlen(bp) + 1; /* for the \0 */ - host.h_name = bp; - bp += n; - buflen -= n; - /* The qname can be abbreviated, but h_name is now absolute. */ - qname = host.h_name; - } - ap = host_aliases; - *ap = NULL; - host.h_aliases = host_aliases; - hap = h_addr_ptrs; - *hap = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ - host.h_addr_list = h_addr_ptrs; -#endif - haveanswer = 0; - had_error = 0; - while (ancount-- > 0 && cp < eom && !had_error) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) { - had_error++; - continue; - } - cp += n; /* name */ - type = _getshort(cp); - cp += INT16SZ; /* type */ - class = _getshort(cp); - cp += INT16SZ + INT32SZ; /* class, TTL */ - n = _getshort(cp); - cp += INT16SZ; /* len */ - if (class != qclass) { - /* XXX - debug? syslog? */ - cp += n; - continue; /* XXX - had_error++ ? */ - } - if (qtype == T_A && type == T_CNAME) { - if (ap >= &host_aliases[MAXALIASES-1]) - continue; - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if (n < 0) { - had_error++; - continue; - } - cp += n; - if (host.h_name && strcasecmp(host.h_name, bp) != 0) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"", - host.h_name, bp); - continue; /* XXX - had_error++ ? */ - } - /* Store alias. */ - *ap++ = bp; - n = strlen(bp) + 1; /* for the \0 */ - bp += n; - buflen -= n; - /* Get canonical name. */ - n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen) { - had_error++; - continue; - } - strcpy(bp, tbuf); - host.h_name = bp; - bp += n; - buflen -= n; - continue; - } - if (qtype == T_PTR && type == T_CNAME) { - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); - if (n < 0) { - had_error++; - continue; - } - cp += n; - /* Get canonical name. */ - n = strlen(tbuf) + 1; /* for the \0 */ - if (n > buflen) { - had_error++; - continue; - } - strcpy(bp, tbuf); - tname = bp; - bp += n; - buflen -= n; - continue; - } - if (type != qtype) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class(qclass), p_type(qtype), - p_type(type)); - cp += n; - continue; /* XXX - had_error++ ? */ - } - switch (type) { - case T_PTR: - if (strcasecmp(tname, bp) != 0) { - syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, qname, bp); - cp += n; - continue; /* XXX - had_error++ ? */ - } - n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) { - had_error++; - break; - } -#if MULTI_PTRS_ARE_ALIASES - cp += n; - if (!haveanswer) - host.h_name = bp; - else if (ap < &host_aliases[MAXALIASES-1]) - *ap++ = bp; - else - n = -1; - if (n != -1) { - n = strlen(bp) + 1; /* for the \0 */ - bp += n; - buflen -= n; - } - break; -#else - host.h_name = bp; - h_errno = NETDB_SUCCESS; - return (&host); -#endif - case T_A: - if (strcasecmp(host.h_name, bp) != 0) { - syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, host.h_name, bp); - cp += n; - continue; /* XXX - had_error++ ? */ - } - if (haveanswer) { - if (n != host.h_length) { - cp += n; - continue; - } - } else { - register int nn; - - host.h_length = n; - host.h_addrtype = (class == C_IN) - ? AF_INET - : AF_UNSPEC; - host.h_name = bp; - nn = strlen(bp) + 1; /* for the \0 */ - bp += nn; - buflen -= nn; - } - - bp += sizeof(align) - ((u_long)bp % sizeof(align)); - - if (bp + n >= &hostbuf[MAXHOSTBUF]) { - dprintf("size (%d) too big\n", n); - had_error++; - continue; - } - if (hap >= &h_addr_ptrs[MAXADDRS-1]) { - if (!toobig++) - dprintf("Too many addresses (%d)\n", - MAXADDRS); - cp += n; - continue; - } - bcopy(cp, *hap++ = bp, n); - bp += n; - cp += n; - break; - default: - dprintf("Impossible condition (type=%d)\n", type); - h_errno = NO_RECOVERY; - return (NULL); - } /*switch*/ - if (!had_error) - haveanswer++; - } /*while*/ - if (haveanswer) { - *ap = NULL; - *hap = NULL; -# if defined(RESOLVSORT) - /* - * Note: we sort even if host can take only one address - * in its return structures - should give it the "best" - * address in that case, not some random one - */ - if (_res.nsort && haveanswer > 1 && - qclass == C_IN && qtype == T_A) - addrsort(h_addr_ptrs, haveanswer); -# endif /*RESOLVSORT*/ -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ - /* nothing */ -#else - host.h_addr = h_addr_ptrs[0]; -#endif /*BSD*/ - if (!host.h_name) { - n = strlen(qname) + 1; /* for the \0 */ - strcpy(bp, qname); - host.h_name = bp; - } - h_errno = NETDB_SUCCESS; - return (&host); - } else { - h_errno = TRY_AGAIN; - return (NULL); - } -} - -struct hostent * -gethostbyname(name) - const char *name; -{ -#if defined(AF_INET6) && defined(RES_TRY_INET6) - struct hostent *hp; - - if (_res.options & RES_TRY_INET6) { - hp = gethostbyname2(name, AF_INET6); - if (hp) - return (hp); - } -#endif - return (gethostbyname2(name, AF_INET)); -} - -#ifdef NOTDEF -static struct hostent * -gethostbyname_ipv4(name) - const char *name; -{ - querybuf buf; - register const char *cp; - int n; -#if !defined(__APPLE__) - extern struct hostent *_gethtbyname(); -#endif /* !NeXT */ - - if (hostbuf == NULL) - { - hostbuf = malloc(MAXHOSTBUF); - if (hostbuf == NULL) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - } - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - - /* - * if there aren't any dots, it could be a user-level alias. - * this is also done in res_query() since we are not the only - * function that looks up host names. - */ - if (!strchr(name, '.') && (cp = __hostalias(name))) - name = cp; - - /* - * disallow names consisting only of digits/dots, unless - * they end in a dot. - */ - if (isdigit(name[0])) - for (cp = name;; ++cp) { - if (!*cp) { - if (*--cp == '.') - break; - /* - * All-numeric, no dot at the end. - * Fake up a hostent as if we'd actually - * done a lookup. - */ - if (!inet_aton(name, &host_addr)) { - h_errno = HOST_NOT_FOUND; - return (NULL); - } - strncpy(hostbuf, name, MAXDNAME); - hostbuf[MAXDNAME] = '\0'; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - host.h_addrtype = AF_INET; - host.h_length = INT32SZ; - h_addr_ptrs[0] = (char *)&host_addr; - h_addr_ptrs[1] = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ - host.h_addr_list = h_addr_ptrs; -#else - host.h_addr = h_addr_ptrs[0]; -#endif - h_errno = NETDB_SUCCESS; - return (&host); - } - if (!isdigit(*cp) && *cp != '.') - break; - } - - if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { - dprintf("res_search failed (%d)\n", n); -#if !defined(__APPLE__) - if (errno == ECONNREFUSED) - return (_gethtbyname(name)); -#endif - return (NULL); - } - return (getanswer(&buf, n, name, C_IN, T_A)); -} -#endif - -struct hostent * -gethostbyaddr(vaddr, len, type) - const void *vaddr; - socklen_t len; - int type; -{ - int n; - querybuf buf; - register struct hostent *hp; - const char* addr = (const char *)vaddr; - char qbuf[MAXDNAME+1]; -#ifdef SUNSECURITY - register struct hostent *rhp; - char **haddr; - u_long old_options; - char hname2[MAXDNAME+1]; -#endif /*SUNSECURITY*/ -#if !defined(__APPLE__) - extern struct hostent *_gethtbyaddr(); -#endif /* !NeXT */ - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - if (type != AF_INET) { - errno = EAFNOSUPPORT; - h_errno = NETDB_INTERNAL; - return (NULL); - } - (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", - ((unsigned)addr[3] & 0xff), - ((unsigned)addr[2] & 0xff), - ((unsigned)addr[1] & 0xff), - ((unsigned)addr[0] & 0xff)); - n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); - if (n < 0) { - dprintf("res_query failed (%d)\n", n); -#if !defined(__APPLE__) - if (errno == ECONNREFUSED) - return (_gethtbyaddr(addr, len, type)); -#endif - return (NULL); - } - if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR))) - return (NULL); /* h_errno was set by getanswer() */ -#ifdef SUNSECURITY - /* - * turn off search as the name should be absolute, - * 'localhost' should be matched by defnames - */ - strncpy(hname2, hp->h_name, MAXDNAME); - hname2[MAXDNAME] = '\0'; - old_options = _res.options; - _res.options &= ~RES_DNSRCH; - _res.options |= RES_DEFNAMES; - if (!(rhp = gethostbyname(hname2))) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostbyaddr: No A record for %s (verifying [%s])", - hname2, inet_ntoa(*((struct in_addr *)addr))); - _res.options = old_options; - h_errno = HOST_NOT_FOUND; - return (NULL); - } - _res.options = old_options; - for (haddr = rhp->h_addr_list; *haddr; haddr++) - if (!memcmp(*haddr, addr, INADDRSZ)) - break; - if (!*haddr) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostbyaddr: A record of %s != PTR record [%s]", - hname2, inet_ntoa(*((struct in_addr *)addr))); - h_errno = HOST_NOT_FOUND; - return (NULL); - } -#endif /*SUNSECURITY*/ - hp->h_addrtype = type; - hp->h_length = len; - h_addr_ptrs[0] = (char *)&host_addr; - h_addr_ptrs[1] = NULL; - host_addr = *(struct in_addr *)addr; - h_errno = NETDB_SUCCESS; - return (hp); -} - -void -_sethtent(f) - int f; -{ - if (!hostf) - hostf = fopen(_PATH_HOSTS, "r" ); - else - rewind(hostf); - stayopen = f; -} - -void -_endhtent() -{ - if (hostf && !stayopen) { - (void) fclose(hostf); - hostf = NULL; - } -} - -struct hostent * -_gethtent() -{ - char *p; - register char *cp, **q; - - if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - if (hostbuf == NULL) { - hostbuf = malloc(MAXHOSTBUF); - if (hostbuf == NULL) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - } -again: - if (!(p = fgets(hostbuf, MAXHOSTBUF, hostf))) { - h_errno = HOST_NOT_FOUND; - return (NULL); - } - if (*p == '#') - goto again; - if (!(cp = strpbrk(p, "#\n"))) - goto again; - *cp = '\0'; - if (!(cp = strpbrk(p, " \t"))) - goto again; - *cp++ = '\0'; - /* THIS STUFF IS INTERNET SPECIFIC */ - if (!inet_aton(p, &host_addr)) - goto again; - h_addr_ptrs[0] = (char *)&host_addr; - h_addr_ptrs[1] = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ - host.h_addr_list = h_addr_ptrs; -#else - host.h_addr = h_addr_ptrs[0]; -#endif - host.h_length = INT32SZ; - host.h_addrtype = AF_INET; - while (*cp == ' ' || *cp == '\t') - cp++; - host.h_name = cp; - q = host.h_aliases = host_aliases; - if ((cp = strpbrk(cp, " \t"))) - *cp++ = '\0'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &host_aliases[MAXALIASES - 1]) - *q++ = cp; - if ((cp = strpbrk(cp, " \t"))) - *cp++ = '\0'; - } - *q = NULL; - h_errno = NETDB_SUCCESS; - return (&host); -} - -struct hostent * -_gethtbyname(name) - char *name; -{ - register struct hostent *p; - register char **cp; - - _sethtent(0); - while ((p = _gethtent())) { - if (strcasecmp(p->h_name, name) == 0) - break; - for (cp = p->h_aliases; *cp != 0; cp++) - if (strcasecmp(*cp, name) == 0) - goto found; - } -found: - _endhtent(); - return (p); -} - -struct hostent * -_gethtbyaddr(addr, len, type) - const char *addr; - int len, type; -{ - register struct hostent *p; - - _sethtent(0); - while ((p = _gethtent())) - if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) - break; - _endhtent(); - return (p); -} - -#ifdef RESOLVSORT -static void -addrsort(ap, num) - char **ap; - int num; -{ - int i, j; - char **p; - short aval[MAXADDRS]; - int needsort = 0; - - p = ap; - for (i = 0; i < num; i++, p++) { - for (j = 0 ; (unsigned)j < _res.nsort; j++) - if (_res.sort_list[j].addr.s_addr == - (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) - break; - aval[i] = j; - if (needsort == 0 && i > 0 && j < aval[i-1]) - needsort = i; - } - if (!needsort) - return; - - while (needsort < num) { - for (j = needsort - 1; j >= 0; j--) { - if (aval[j] > aval[j+1]) { - char *hp; - - i = aval[j]; - aval[j] = aval[j+1]; - aval[j+1] = i; - - hp = ap[j]; - ap[j] = ap[j+1]; - ap[j+1] = hp; - - } else - break; - } - needsort++; - } -} -#endif - -#if defined(BSD43_BSD43_NFS) || defined(sun) -/* some libc's out there are bound internally to these names (UMIPS) */ -void -ht_sethostent(stayopen) - int stayopen; -{ - _sethtent(stayopen); -} - -void -ht_endhostent() -{ - _endhtent(); -} - -struct hostent * -ht_gethostbyname(name) - char *name; -{ - return (_gethtbyname(name)); -} - -struct hostent * -ht_gethostbyaddr(addr, len, type) - const char *addr; - int len, type; -{ - return (_gethtbyaddr(addr, len, type)); -} - -struct hostent * -gethostent() -{ - return (_gethtent()); -} - -void -dns_service() -{ - return; -} - -#undef dn_skipname -dn_skipname(comp_dn, eom) - const u_char *comp_dn, *eom; -{ - return (__dn_skipname(comp_dn, eom)); -} -#endif /*old-style libc with yp junk in it*/ diff --git a/dns.subproj/getnetbyaddr.c b/dns.subproj/getnetbyaddr.c deleted file mode 100644 index 9406809..0000000 --- a/dns.subproj/getnetbyaddr.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetbyaddr.c 1.1 (Coimbra) 93/06/02"; -static char rcsid[] = "$Id: getnetbyaddr.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include - -extern int _net_stayopen; - -struct netent * -_getnetbyaddr(net, type) - register long net; - register int type; -{ - register struct netent *p; - - setnetent(_net_stayopen); - while ((p = getnetent())) - if (p->n_addrtype == type && p->n_net == net) - break; - if (!_net_stayopen) - endnetent(); - return (p); -} diff --git a/dns.subproj/getnetbyname.c b/dns.subproj/getnetbyname.c deleted file mode 100644 index 24cf4a6..0000000 --- a/dns.subproj/getnetbyname.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetbyname.c 8.1 (Berkeley) 6/4/93"; -static char sccsid_[] = "from getnetbyname.c 1.1 (Coimbra) 93/06/02"; -static char rcsid[] = "$Id: getnetbyname.c,v 1.3 2002/02/19 20:36:12 epeyton Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -extern int _net_stayopen; - -struct netent * -_getnetbyname(name) - register const char *name; -{ - register struct netent *p; - register char **cp; - - setnetent(_net_stayopen); - while ((p = getnetent())) { - if (strcasecmp(p->n_name, name) == 0) - break; - for (cp = p->n_aliases; *cp != 0; cp++) - if (strcasecmp(*cp, name) == 0) - goto found; - } -found: - if (!_net_stayopen) - endnetent(); - return (p); -} diff --git a/dns.subproj/getnetent.c b/dns.subproj/getnetent.c deleted file mode 100644 index ff90cee..0000000 --- a/dns.subproj/getnetent.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro - * Dep. Matematica Universidade de Coimbra, Portugal, Europe - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * from getnetent.c 1.1 (Coimbra) 93/06/02 - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: getnetent.c,v 1.4 2003/02/18 17:29:23 majka Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifndef _PATH_NETWORKS -#define _PATH_NETWORKS "/etc/networks" -#endif - -#define MAXALIASES 35 - -static FILE *netf; -static struct netent net; -static char *net_aliases[MAXALIASES]; -#if defined(__APPLE__) -extern -#endif -int _net_stayopen; - -void _setnetent __P((int)); -void _endnetent __P((void)); - -void -setnetent(stayopen) - int stayopen; -{ - - sethostent(stayopen); - _setnetent(stayopen); -} - -void -endnetent() -{ - - endhostent(); - _endnetent(); -} - -void -_setnetent(f) - int f; -{ - - if (netf == NULL) - netf = fopen(_PATH_NETWORKS, "r" ); - else - rewind(netf); - _net_stayopen |= f; -} - -void -_endnetent() -{ - - if (netf) { - fclose(netf); - netf = NULL; - } - _net_stayopen = 0; -} - -struct netent * -getnetent() -{ - char *p; - static char *line = NULL; - register char *cp, **q; - - if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL) - return (NULL); - - if (line == NULL) { - line = malloc(BUFSIZ+1); - if (line == NULL) - return (NULL); - } -again: - p = fgets(line, BUFSIZ, netf); - if (p == NULL) - return (NULL); - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - net.n_name = p; - cp = strpbrk(p, " \t"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - while (*cp == ' ' || *cp == '\t') - cp++; - p = strpbrk(cp, " \t"); - if (p != NULL) - *p++ = '\0'; - net.n_net = inet_network(cp); - net.n_addrtype = AF_INET; - q = net.n_aliases = net_aliases; - if (p != NULL) - cp = p; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &net_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - return (&net); -} diff --git a/dns.subproj/getnetnamadr.c b/dns.subproj/getnetnamadr.c deleted file mode 100644 index bd62e06..0000000 --- a/dns.subproj/getnetnamadr.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro - * Dep. Matematica Universidade de Coimbra, Portugal, Europe - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93"; -static char sccsid_[] = "from getnetnamadr.c 1.4 (Coimbra) 93/06/03"; -static char rcsid[] = "$Id: getnetnamadr.c,v 1.5 2004/10/07 17:33:33 majka Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -extern int h_errno; - -#if defined(mips) && defined(SYSTYPE_BSD43) -extern int errno; -#endif - -struct netent *_getnetbyaddr __P((long net, int type)); -struct netent *_getnetbyname __P((const char *name)); - -#define BYADDR 0 -#define BYNAME 1 -#define MAXALIASES 35 - -#if PACKETSZ > 1024 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 1024 -#endif - -typedef union { - HEADER hdr; - u_char buf[MAXPACKET]; -} querybuf; - -typedef union { - long al; - char ac; -} align; - -static struct netent * -getnetanswer(answer, anslen, net_i) - querybuf *answer; - int anslen; - int net_i; -{ - - register HEADER *hp; - register u_char *cp; - register int n; - u_char *eom; - int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; - char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap, - *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; -static struct netent net_entry; -static char *net_aliases[MAXALIASES], *netbuf = NULL; - - if (netbuf == NULL) { - netbuf = malloc(BUFSIZ+1); - if (netbuf == NULL) - return (NULL); - } - buflen = BUFSIZ+1; - - /* - * find first satisfactory answer - * - * answer --> +------------+ ( MESSAGE ) - * | Header | - * +------------+ - * | Question | the question for the name server - * +------------+ - * | Answer | RRs answering the question - * +------------+ - * | Authority | RRs pointing toward an authority - * | Additional | RRs holding additional information - * +------------+ - */ - eom = answer->buf + anslen; - hp = &answer->hdr; - ancount = ntohs(hp->ancount); /* #/records in the answer section */ - qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ - bp = netbuf; - cp = answer->buf + HFIXEDSZ; - if (!qdcount) { - if (hp->aa) - h_errno = HOST_NOT_FOUND; - else - h_errno = TRY_AGAIN; - return (NULL); - } - while (qdcount-- > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - ap = net_aliases; - *ap = NULL; - net_entry.n_aliases = net_aliases; - haveanswer = 0; - while (--ancount >= 0 && cp < eom) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) - break; - cp += n; - ans[0] = '\0'; - (void)strcpy(&ans[0], bp); - GETSHORT(type, cp); - GETSHORT(class, cp); - cp += INT32SZ; /* TTL */ - GETSHORT(n, cp); - if (class == C_IN && type == T_PTR) { - n = dn_expand(answer->buf, eom, cp, bp, buflen); - if (n < 0) { - cp += n; - return (NULL); - } - cp += n; - *ap++ = bp; - bp += strlen(bp) + 1; - net_entry.n_addrtype = - (class == C_IN) ? AF_INET : AF_UNSPEC; - haveanswer++; - } - } - if (haveanswer) { - *ap = NULL; - switch (net_i) { - case BYADDR: - net_entry.n_name = *net_entry.n_aliases; - net_entry.n_net = 0L; - break; - case BYNAME: - in = *net_entry.n_aliases; - net_entry.n_name = &ans[0]; - aux2[0] = '\0'; - for (i = 0; i < 4; i++) { - for (st = in, nchar = 0; - *st != '.'; - st++, nchar++) - ; - if (nchar != 1 || *in != '0' || flag) { - flag = 1; - (void)strncpy(paux1, - (i==0) ? in : in-1, - (i==0) ?nchar : nchar+1); - paux1[(i==0) ? nchar : nchar+1] = '\0'; - pauxt = paux2; - paux2 = strcat(paux1, paux2); - paux1 = pauxt; - } - in = ++st; - } - net_entry.n_net = inet_network(paux2); - break; - } - net_entry.n_aliases++; - return (&net_entry); - } - h_errno = TRY_AGAIN; - return (NULL); -} - -struct netent * -getnetbyaddr(net, net_type) - register uint32_t net; - register int net_type; -{ - unsigned int netbr[4]; - int nn, anslen; - querybuf buf; - char qbuf[MAXDNAME]; - unsigned long net2; - struct netent *net_entry; - - if (net_type != AF_INET) -#if defined(__APPLE__) - return NULL; -#else - return (_getnetbyaddr(net, net_type)); -#endif /* !NeXT */ - - for (nn = 4, net2 = net; net2; net2 >>= 8) - netbr[--nn] = net2 & 0xff; - switch (nn) { - case 3: /* Class A */ - sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); - break; - case 2: /* Class B */ - sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); - break; - case 1: /* Class C */ - sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], - netbr[1]); - break; - case 0: /* Class D - E */ - sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], - netbr[1], netbr[0]); - break; - } - anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); - if (anslen < 0) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("res_query failed\n"); -#endif -#if !defined(__APPLE__) - if (errno == ECONNREFUSED) - return (_getnetbyaddr(net, net_type)); -#endif /* !NeXT */ - return (NULL); - } - net_entry = getnetanswer(&buf, anslen, BYADDR); - if (net_entry) { - unsigned u_net = net; /* maybe net should be unsigned ? */ - - /* Strip trailing zeros */ - while ((u_net & 0xff) == 0 && u_net != 0) - u_net >>= 8; - net_entry->n_net = u_net; - return (net_entry); - } -#if defined(__APPLE__) - return NULL; -#else - return (_getnetbyaddr(net, net_type)); -#endif /* !NeXT */ -} - -struct netent * -getnetbyname(net) - register const char *net; -{ - int anslen; - querybuf buf; - char qbuf[MAXDNAME]; - struct netent *net_entry; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (NULL); - } - strcpy(&qbuf[0], net); - anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); - if (anslen < 0) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("res_query failed\n"); -#endif -#if defined(__APPLE__) - return NULL; -#else - if (errno == ECONNREFUSED) - return (_getnetbyname(net)); - return (_getnetbyname(net)); -#endif /* !NeXT */ - } - net_entry = getnetanswer(&buf, anslen, BYNAME); - if (net_entry) - return (net_entry); -#if defined(__APPLE__) - return NULL; -#else - return (_getnetbyname(net)); -#endif /* !NeXT */ -} diff --git a/dns.subproj/inet_addr.c b/dns.subproj/inet_addr.c new file mode 100644 index 0000000..58e7736 --- /dev/null +++ b/dns.subproj/inet_addr.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * ++Copyright++ 1983, 1990, 1993 + * - + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; +static char rcsid[] = "$Id: inet_addr.c,v 1.2 1999/10/14 21:56:45 wsanchez Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include "portability.h" + +/* these are compatibility routines, not needed on recent BSD releases */ + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +u_long +inet_addr(cp) + register const char *cp; +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(cp, addr) + register const char *cp; + struct in_addr *addr; +{ + register u_long val; + register int base, n; + register char c; + u_int parts[4]; + register u_int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (isascii(c) && isdigit(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && isascii(c) && isxdigit(c)) { + val = (val << 4) | + (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} diff --git a/dns.subproj/nsap_addr.c b/dns.subproj/nsap_addr.c new file mode 100644 index 0000000..651fea1 --- /dev/null +++ b/dns.subproj/nsap_addr.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: nsap_addr.c,v 1.3 2003/02/18 17:29:24 majka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include + +#include "nameser8_compat.h" +#include "resolv8_compat.h" +#include "portability.h" + +#if !defined(isxdigit) /* XXX - could be a function */ +static int +isxdigit(c) + register int c; +{ + return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F')); +} +#endif + +static char +xtob(c) + register int c; +{ + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(ascii, binary, maxlen) + const char *ascii; + u_char *binary; + int maxlen; +{ + register u_char c, nib; + u_int len = 0; + + while ((c = *ascii++) != '\0' && len < maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + if (c = *ascii++) { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(binlen, binary, ascii) + int binlen; + register const u_char *binary; + register char *ascii; +{ + register int nib; + int i; + static char tmpbuf[255*3]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/dns.subproj/res_comp.c b/dns.subproj/res_comp.c index 2bb154b..1539cc7 100644 --- a/dns.subproj/res_comp.c +++ b/dns.subproj/res_comp.c @@ -83,12 +83,13 @@ static char rcsid[] = "$Id: res_comp.c,v 1.4 2003/02/18 17:29:24 majka Exp $"; #include #include -#include #include -#include #include +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #if defined(BSD) && (BSD >= 199103) # include # include diff --git a/dns.subproj/res_data.c b/dns.subproj/res_data.c index 4f19602..d193e99 100644 --- a/dns.subproj/res_data.c +++ b/dns.subproj/res_data.c @@ -29,14 +29,19 @@ #if defined(__APPLE__) /* - * _res is declared to be the same siae as struct __res_9_state + * _res is declared to be the same size as struct __res_9_state * This allows both the BIND-8 library in libSystem (this one) * and the new BIND-9 library in libresolv to share the same * structure. We ues the __res_9_state's _pad variable to store * a version number when _res have been initialized by the BIND-9 * library, and take precautions to make them work together. */ +#ifdef __LP64__ +#define RES_9_STATE_SIZE 552 +#else #define RES_9_STATE_SIZE 512 +#endif + char _res[RES_9_STATE_SIZE] = {0}; int _net_stayopen = 0; #endif diff --git a/dns.subproj/res_debug.c b/dns.subproj/res_debug.c index bf83730..eb075c9 100644 --- a/dns.subproj/res_debug.c +++ b/dns.subproj/res_debug.c @@ -84,11 +84,13 @@ static char rcsid[] = "$Id: res_debug.c,v 1.5 2004/06/11 23:16:00 majka Exp $"; #include #include #include -#include #include #include -#include + +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #if defined(BSD) && (BSD >= 199103) # include #else @@ -236,7 +238,7 @@ do_rrset(msg, len, cp, cnt, pflag, file, hs) if ((n = ntohs(cnt))) { if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) - fprintf(file, hs); + fprintf(file, "%s", hs); while (--n >= 0) { if ((!_res.pfcode) || sflag) { cp = p_rr(cp, msg, file); diff --git a/dns.subproj/res_init.c b/dns.subproj/res_init.c index 7336289..e1778c7 100644 --- a/dns.subproj/res_init.c +++ b/dns.subproj/res_init.c @@ -86,11 +86,13 @@ static char rcsid[] = "$Id: res_init.c,v 1.8 2003/02/18 17:29:24 majka Exp $"; #include #include #include -#include #include #include -#include + +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #if defined(BSD) && (BSD >= 199103) # include # include diff --git a/dns.subproj/res_mkquery.c b/dns.subproj/res_mkquery.c index 06d2429..244a205 100644 --- a/dns.subproj/res_mkquery.c +++ b/dns.subproj/res_mkquery.c @@ -83,11 +83,13 @@ static char rcsid[] = "$Id: res_mkquery.c,v 1.3 2003/02/18 17:29:24 majka Exp $" #include #include -#include #include #include -#include + +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #if defined(BSD) && (BSD >= 199103) # include #else diff --git a/dns.subproj/res_query.c b/dns.subproj/res_query.c index 69575d0..86ce21f 100644 --- a/dns.subproj/res_query.c +++ b/dns.subproj/res_query.c @@ -84,13 +84,15 @@ static char rcsid[] = "$Id: res_query.c,v 1.3 2003/02/18 17:29:24 majka Exp $"; #include #include #include -#include #include #include -#include #include #include + +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #if defined(BSD) && (BSD >= 199306) # include # include diff --git a/lookup.subproj/lu_printer.c b/dns.subproj/res_running.c similarity index 68% rename from lookup.subproj/lu_printer.c rename to dns.subproj/res_running.c index 0b7d195..0c672df 100644 --- a/lookup.subproj/lu_printer.c +++ b/dns.subproj/res_running.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,36 +21,22 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * Printer lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include "printerdb.h" -#include "lu_utils.h" +/** + ** res_running.c + ** + ** A little shortie to tell us if the resolver has been initialized or not. + ** + ** Copyright (c) 1995, NeXT Computer, Inc. All Rights Reserved. + **/ -const prdb_ent * -prdb_getbyname(const char *name) -{ - return NULL; -} +#include +#include -const prdb_ent * -prdb_get(void) -{ - return NULL; -} - -void -prdb_set(const char *name) -{ -} +#include "nameser8_compat.h" +#include "resolv8_compat.h" -void -prdb_end(void) +int +_res_running() { + return (_res.options & RES_INIT); } diff --git a/dns.subproj/res_send.c b/dns.subproj/res_send.c index d6cf0f5..5d2931a 100644 --- a/dns.subproj/res_send.c +++ b/dns.subproj/res_send.c @@ -97,7 +97,6 @@ static char rcsid[] = "$Id: res_send.c,v 1.6 2003/02/18 17:29:25 majka Exp $"; #include #include #include -#include #include #include #include @@ -105,7 +104,10 @@ static char rcsid[] = "$Id: res_send.c,v 1.6 2003/02/18 17:29:25 majka Exp $"; #include #include #include -#include + +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #if defined(BSD) && (BSD >= 199306) # include # include @@ -319,7 +321,7 @@ static int dns_is_local_name(const u_int8_t *name) const u_int8_t *d2 = NULL; // etc. const u_int8_t *d3 = NULL; - if (name == NULL) return 0; + if (name == NULL || *name == 0) return 0; while (*name) { @@ -355,21 +357,12 @@ static int dns_is_local_name(const u_int8_t *name) #define DNS_LOCAL_DOMAIN_SERVICE_PORT 5353 #define DNS_HEADER_SIZE 12 -#if BYTE_ORDER == BIG_ENDIAN -#define my_htons(x) (x) -#define my_htonl(x) (x) -#else -#define my_htons(x) ((((u_int16_t)x) >> 8) | (((u_int16_t)x) << 8)) -#define my_htonl(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 16) | \ - (((x) & 0x0000FF00) << 16) | ((x) << 24)) -#endif - static const struct sockaddr_in mDNS_addr = { sizeof(mDNS_addr), AF_INET, - my_htons(DNS_LOCAL_DOMAIN_SERVICE_PORT), - {my_htonl(0xE00000FB)} /* 224.0.0.251 */ + htons(DNS_LOCAL_DOMAIN_SERVICE_PORT), + {htonl(0xE00000FB)} /* 224.0.0.251 */ }; int diff --git a/dns.subproj/sethostent.c b/dns.subproj/sethostent.c deleted file mode 100644 index 68ea8e1..0000000 --- a/dns.subproj/sethostent.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: sethostent.c,v 1.3 2003/02/18 17:29:25 majka Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include - -void _res_close __P((void)); - -void -sethostent(stayopen) - int stayopen; -{ - if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return; - if (stayopen) - _res.options |= RES_STAYOPEN | RES_USEVC; -} - -void -endhostent() -{ - _res.options &= ~(RES_STAYOPEN | RES_USEVC); - _res_close(); -} diff --git a/gen.subproj/Makefile b/gen.subproj/Makefile index ae7b3ee..f8484cc 100644 --- a/gen.subproj/Makefile +++ b/gen.subproj/Makefile @@ -1,63 +1,71 @@ -# -# 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 = gen - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component - -HFILES = ifaddrs.h - -CFILES = aliasdb.c ether_addr.c fstab.c getgrent.c\ - getifaddrs.c getproto.c getprotoent.c\ - getprotoname.c getpwent.c getservbyname.c getservbyport.c\ - getservent.c if_indextoname.c if_nameindex.c if_nametoindex.c\ - inet_ntop.c inet_pton.c initgroups.c printerdb.c\ - map_v4v6.c ip6opt.c rthdr.c vars.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ - getifaddrs.3 if_indextoname.3 inet6_rthdr_space.3\ - gethostbyname.3 inet6_option_space.3\ - getprotoent.3 gethostbyname.3 getipnodebyname.3\ - getnetent.3 getservent.3 inet6_option_space.3 - -OTHERLINKEDOFILES = _version.o - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -NEXTSTEP_INSTALLDIR = /usr/local/lib/system -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - -PUBLIC_HEADERS = ifaddrs.h - - - -NEXTSTEP_PUBLIC_HEADERS_DIR = /usr/include - -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 +Project = gen +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES + +CFILES = ether_addr.c getifaddrs.c \ + if_indextoname.c if_nameindex.c if_nametoindex.c \ + inet_ntop.c inet_pton.c map_v4v6.c ip6opt.c rthdr.c vars.c \ + $(OBJROOT)/_version.c + +MANPAGES = getifaddrs.3 if_indextoname.3 inet6_rthdr_space.3 \ + gethostbyname.3 inet6_option_space.3 \ + getprotoent.3 gethostbyname.3 getipnodebyname.3 \ + getnetent.3 getservent.3 inet6_option_space.3 + +Install_Headers = ifaddrs.h + +Extra_CC_Flags = -Wall -fno-common -I. \ + -I../dns.subproj -I../lookup.subproj \ + -D__DARWIN_NON_CANCELABLE=1 -DINET6=1 + + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +$(OBJROOT)/_version.c: + /Developer/Makefiles/bin/version.pl Libinfo > $@ + +after_install: + @for LINK in endhostent.3 gethostbyaddr.3 gethostbyname2.3 \ + gethostent.3 herror.3 hstrerror.3 sethostent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getifaddrs.3" \ + "$(DSTROOT)/usr/share/man/man3/freeifaddrs.3" + @for LINK in freehostent.3 getipnodebyaddr.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getipnodebyname.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in endnetent.3 getnetbyaddr.3 getnetbyname.3 \ + setnetent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in endprotoent.3 getprotobyname.3 getprotobynumber.3 \ + setprotoent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in endservent.3 getservbyname.3 getservbyport.3 \ + setservent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in if_freenameindex.3 if_nameindex.3 if_nametoindex.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in inet6_option_alloc.3 inet6_option_append.3 \ + inet6_option_find.3 inet6_option_init.3 inet6_option_next.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in inet6_rthdr_add.3 inet6_rthdr_getaddr.3 \ + inet6_rthdr_getflags.3 inet6_rthdr_init.3 \ + inet6_rthdr_lasthop.3 inet6_rthdr_reverse.3 \ + inet6_rthdr_segments.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done diff --git a/gen.subproj/Makefile.postamble b/gen.subproj/Makefile.postamble deleted file mode 100644 index 3cc4f8e..0000000 --- a/gen.subproj/Makefile.postamble +++ /dev/null @@ -1,158 +0,0 @@ -############################################################################### -# NeXT Makefile.postamble Template -# Copyright 1993, NeXT Computer, Inc. -# -# This Makefile is used for configuring the standard app makefiles associated -# with ProjectBuilder. -# -# Use this template to set attributes for a project, sub-project, bundle, or -# palette. Each node in the project's tree of sub-projects and bundles -# should have it's own Makefile.preamble and Makefile.postamble. Additional -# rules (e.g., after_install) that are defined by the developer should be -# defined in this file. -# -############################################################################### -# -# Here are the variables exported by the common "app" makefiles that can be -# used in any customizations you make to the template below: -# -# PRODUCT_ROOT - Name of the directory to which resources are copied. -# OFILE_DIR - Directory into which .o object files are generated. -# (Note that this name is calculated based on the target -# architectures specified in Project Builder). -# DERIVED_SRC_DIR - Directory used for all other derived files -# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations -# -# NAME - name of application, bundle, subproject, palette, etc. -# LANGUAGE - langage in which the project is written (default "English") -# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" -# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" -# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project -# GLOBAL_RESOURCES - non-localized resources of project -# PROJECTVERSION - version of ProjectBuilder that output Makefile -# APPICON - application icon file -# DOCICONS - dock icon files -# ICONSECTIONS - Specifies icon sections when linking executable -# -# CLASSES - Class implementation files in project. -# HFILES - Header files in project. -# MFILES - Other Objective-C source files in project. -# CFILES - Other C source files in project. -# PSWFILES - .psw files in the project -# PSWMFILES - .pswm files in the project -# SUBPROJECTS - Subprojects of this project -# BUNDLES - Bundle subprojects of this project -# OTHERSRCS - Other miscellaneous sources of this project -# OTHERLINKED - Source files not matching a standard source extention -# -# LIBS - Libraries to link with when making app target -# DEBUG_LIBS - Libraries to link with when making debug target -# PROF_LIBS - Libraries to link with when making profile target -# OTHERLINKEDOFILES - Other relocatable files to (always) link in. -# -# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles -# MAKEFILEDIR - Directory in which to find $(MAKEFILE) -# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) -# INSTALLDIR - Directory app will be installed into by 'install' target -# -############################################################################### - - -# Change defaults assumed by the standard makefiles here. Edit the -# following default values as appropriate. (Note that if no Makefile.postamble -# exists, these values will have defaults set in common.make). - -# Versioning of frameworks, libraries, bundles, and palettes: -#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary -#DEPLOY_WITH_VERSION_NAME = A -#COMPATIBILITY_PROJECT_VERSION = 1 - -# Some compiler flags can be easily overridden here, but onlytake effect at -# the top-level: -#OPTIMIZATION_CFLAG = -O -#DEBUG_SYMBOLS_CFLAG = -g -#WARNING_CFLAGS = -Wall -#DEBUG_BUILD_CFLAGS = -DDEBUG -#PROFILE_BUILD_CFLAGS = -pg -DPROFILE - -# Flags passed to yacc -#YFLAGS = -d - -# Library and Framework projects only: -# 1. If you want something other than the default .dylib name, override it here -#DYLIB_INSTALL_NAME = lib$(NAME).dylib - -# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. -#DYLIB_INSTALL_DIR = $(INSTALLDIR) - -# 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 for various project types. Note: -S strips debugging symbols -# (executables can be stripped down further with -x or, if they load no bundles, with no -# options at all). -#APP_STRIP_OPTS = -S -#TOOL_STRIP_OPTS = -S -#LIBRARY_STRIP_OPTS = -S # for .a archives -#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries - -######################################################################### -# Put rules to extend the behavior of the standard Makefiles here. "Official" -# user-defined rules are: -# * before_install -# * after_install -# * after_installhdrs -# 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. -# -install-man-page: - mkdir -p "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 gethostbyname.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/endhostent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/gethostbyaddr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/gethostbyname2.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/gethostent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/herror.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/hstrerror.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/gethostbyname.3" "$(DSTROOT)/usr/share/man/man3/sethostent.3" - install -c -m 644 getifaddrs.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getifaddrs.3" "$(DSTROOT)/usr/share/man/man3/freeifaddrs.3" - install -c -m 644 getipnodebyname.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getipnodebyname.3" "$(DSTROOT)/usr/share/man/man3/freehostent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getipnodebyname.3" "$(DSTROOT)/usr/share/man/man3/getipnodebyaddr.3" - install -c -m 644 getnetent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/endnetent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/getnetbyaddr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/getnetbyname.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetent.3" "$(DSTROOT)/usr/share/man/man3/setnetent.3" - install -c -m 644 getprotoent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/endprotoent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/getprotobyname.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/getprotobynumber.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getprotoent.3" "$(DSTROOT)/usr/share/man/man3/setprotoent.3" - install -c -m 644 getservent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/endservent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/getservbyname.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/getservbyport.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getservent.3" "$(DSTROOT)/usr/share/man/man3/setservent.3" - install -c -m 644 if_indextoname.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" "$(DSTROOT)/usr/share/man/man3/if_freenameindex.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" "$(DSTROOT)/usr/share/man/man3/if_nameindex.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/if_indextoname.3" "$(DSTROOT)/usr/share/man/man3/if_nametoindex.3" - install -c -m 644 inet6_option_space.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_alloc.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_append.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_find.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_init.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_option_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_option_next.3" - install -c -m 644 inet6_rthdr_space.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_add.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_getaddr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_getflags.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_init.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_lasthop.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_reverse.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_space.3" "$(DSTROOT)/usr/share/man/man3/inet6_rthdr_segments.3" diff --git a/gen.subproj/Makefile.preamble b/gen.subproj/Makefile.preamble deleted file mode 100644 index 7f9c621..0000000 --- a/gen.subproj/Makefile.preamble +++ /dev/null @@ -1,41 +0,0 @@ -AFTER_POSTINSTALL += install-man-page -OTHER_CFLAGS = \ - -D__DARWIN_NON_CANCELABLE=1 \ - -DINET6=1 \ - -Dsetservent=_old_setservent \ - -Dgetservent=_old_getservent \ - -Dendservent=_old_endservent \ - -Dgetservbyname=_old_getservbyname \ - -Dgetservbyport=_old_getservbyport \ - -Dsetprotoent=_old_setprotoent \ - -Dgetprotoent=_old_getprotoent \ - -Dendprotoent=_old_endprotoent \ - -Dgetprotobyname=_old_getprotobyname \ - -Dgetprotobynumber=_old_getprotobynumber \ - -Dsetnetgrent=_old_setnetgrent \ - -Dgetnetgrent=_old_getnetgrent \ - -Dendnetgrent=_old_endnetgrent \ - -Dsetpwent=_old_setpwent \ - -Dgetpwent=_old_getpwent \ - -Dendpwent=_old_endpwent \ - -Dgetpwnam=_old_getpwnam \ - -Dgetpwuid=_old_getpwuid \ - -Dsetgrent=_old_setgrent \ - -Dgetgrent=_old_getgrent \ - -Dendgrent=_old_endgrent \ - -Dgetgrnam=_old_getgrnam \ - -Dgetgrgid=_old_getgrgid \ - -Dsetfsent=_old_setfsent \ - -Dendfsent=_old_endfsent \ - -Dgetfsent=_old_getfsent \ - -Dgetfsfile=_old_getfsfile \ - -Dgetfsspec=_old_getfsspec \ - -Dinitgroups=_old_initgroups \ - -I../lookup.subproj - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) - -$(OFILE_DIR)/_version.c: - /Developer/Makefiles/bin/version.pl Libinfo > $@ diff --git a/gen.subproj/PB.project b/gen.subproj/PB.project deleted file mode 100644 index 7dbd744..0000000 --- a/gen.subproj/PB.project +++ /dev/null @@ -1,64 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = (ifaddrs.h); - OTHER_LINKED = ( - aliasdb.c, - ether_addr.c, - fstab.c, - getgrent.c, - getifaddrs.c, - getproto.c, - getprotoent.c, - getprotoname.c, - getpwent.c, - getservbyname.c, - getservbyport.c, - getservent.c, - if_indextoname.c, - if_nameindex.c, - if_nametoindex.c, - inet_ntop.c, - inet_pton.c, - initgroups.c, - printerdb.c, - map_v4v6.c, - ip6opt.c, - rthdr.c, - vars.c - ); - OTHER_SOURCES = ( - Makefile.preamble, - Makefile, - Makefile.postamble, - getifaddrs.3, - if_indextoname.3, - inet6_rthdr_space.3, - gethostbyname.3, - inet6_option_space.3, - getprotoent.3, - gethostbyname.3, - getipnodebyname.3, - getnetent.3, - getservent.3, - inet6_option_space.3 - ); - PUBLIC_HEADERS = (ifaddrs.h); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; - NEXTSTEP_INSTALLDIR = /usr/local/lib/system; - NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; - NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; - NEXTSTEP_PUBLICHEADERSDIR = /usr/include; - PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; - PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; - PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; - PROJECTNAME = gen; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/gen.subproj/aliasdb.c b/gen.subproj/aliasdb.c deleted file mode 100644 index ad0bd4f..0000000 --- a/gen.subproj/aliasdb.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Unimplemented backward-compatible alias lookup routines. - * These are only called if NetInfo is not running or if YP - * has been turned on, in which case NetInfo will be tried first. - * This is the standard NeXT policy for all lookup routines. - */ - -#include -#include - -void -_old_alias_setent(void) -{ -} - -struct aliasent * -_old_alias_getent(void) -{ - return (NULL); -} - -void -_old_alias_endent(void) -{ -} - -struct aliasent * -_old_alias_getbyname(char *name) -{ - return (NULL); -} diff --git a/gen.subproj/ether_addr.c b/gen.subproj/ether_addr.c index b6b726c..f49e258 100644 --- a/gen.subproj/ether_addr.c +++ b/gen.subproj/ether_addr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2008 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -53,134 +53,58 @@ static const char ethers[] = "/etc/ethers"; * the corresponding hosts name. * Returns zero if successful, non-zero otherwise. */ -int ether_line(s, e, hostname) - const char *s; /* the string to be parsed */ - struct ether_addr *e; /* ethernet address struct to be filled in */ - char *hostname; /* hosts name to be set */ +int +ether_line(const char *s, struct ether_addr *e, char *hostname) { - register int i; + int i; unsigned int t[6]; - i = sscanf(s, " %x:%x:%x:%x:%x:%x %s", - &t[0], &t[1], &t[2], &t[3], &t[4], &t[5], hostname); - if (i != 7) { - return (7 - i); - } - for (i = 0; i < 6; i++) - e->ether_addr_octet[i] = t[i]; - return (0); + i = sscanf(s, " %x:%x:%x:%x:%x:%x %s", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5], hostname); + if (i != 7) return (7 - i); + + for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i]; + return 0; } /* * Converts a 48 bit ethernet number to its string representation. */ -#define EI(i) (unsigned int)(e->ether_addr_octet[(i)]) +#define EI(i) (unsigned int)(e->ether_addr_octet[(i)]) char * -ether_ntoa(e) - const struct ether_addr *e; +ether_ntoa(const struct ether_addr *e) { static char *s; - if (s == 0) { + if (s == 0) + { s = (char *)malloc(18); - if (s == 0) - return (0); + if (s == 0) return NULL; } + s[0] = 0; - sprintf(s, "%x:%x:%x:%x:%x:%x", - EI(0), EI(1), EI(2), EI(3), EI(4), EI(5)); - return (s); + sprintf(s, "%x:%x:%x:%x:%x:%x", EI(0), EI(1), EI(2), EI(3), EI(4), EI(5)); + return s; } /* * Converts a ethernet address representation back into its 48 bits. */ struct ether_addr * -ether_aton(s) - const char *s; +ether_aton(const char *s) { static struct ether_addr *ep; - register int i; + int i; unsigned int t[6]; - if (ep == 0) { - ep = (struct ether_addr *)calloc(1, sizeof (struct ether_addr)); - if (ep == 0) - return (0); - } - i = sscanf(s, " %x:%x:%x:%x:%x:%x", - &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]); - if (i != 6) - return ((struct ether_addr *)NULL); - for (i = 0; i < 6; i++) - ep->ether_addr_octet[i] = t[i]; - return (ep); -} - -/* - * Given a host's name, this routine returns its 48 bit ethernet address. - * Returns zero if successful, non-zero otherwise. - */ -int _old_ether_hostton(host, e) - const char *host; /* function input */ - struct ether_addr *e; /* function output */ -{ - char currenthost[256]; - char buf[512]; - char *val = buf; - register int reason; - FILE *f; - - if ((f = fopen(ethers, "r")) == NULL) + if (ep == 0) { - return (-1); - } - - reason = -1; - while (fscanf(f, "%[^\n] ", val) == 1) - { - if ((ether_line(val, e, currenthost) == 0) && - (strcmp(currenthost, host) == 0)) - { - reason = 0; - break; - } - } - - fclose(f); - return (reason); -} - -/* - * Given a 48 bit ethernet address, this routine return its host name. - * Returns zero if successful, non-zero otherwise. - */ -int _old_ether_ntohost(host, e) - char *host; /* function output */ - const struct ether_addr *e; /* function input */ -{ - struct ether_addr currente; - char buf[512]; - char *val = buf; - register int reason; - FILE *f; - - if ((f = fopen(ethers, "r")) == NULL) - { - return (-1); + ep = (struct ether_addr *)calloc(1, sizeof (struct ether_addr)); + if (ep == 0) return NULL; } - reason = -1; - while (fscanf(f, "%[^\n] ", val) == 1) - { - if ((ether_line(val, ¤te, host) == 0) && - (bcmp(e, ¤te, sizeof(currente)) == 0)) - { - reason = 0; - break; - } - } + i = sscanf(s, " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]); + if (i != 6) return NULL; - fclose(f); - return (reason); + for (i = 0; i < 6; i++) ep->ether_addr_octet[i] = t[i]; + return ep; } diff --git a/gen.subproj/fstab.c b/gen.subproj/fstab.c deleted file mode 100644 index 8ed5824..0000000 --- a/gen.subproj/fstab.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved - * - * Copyright (c) 1980, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * @(#)fstab.c 8.1 (Berkeley) 6/4/93 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static FILE *_fs_fp = NULL; -static struct fstab _fs_fstab; -static struct fstab _root_fstab; -static char _root_fstype[MFSNAMELEN]; -static int firstTime = 1; -static int returnedRoot = 0; -static void error __P((int)); -static int fstabscan __P((void)); -static const char *slash = "/"; -static const char *remountedroot = "/root"; - -/* We don't want to depend on fstab for the root filesystem entry, -** since that can change when disks are added or removed from the system. -** So, we stat "/" and find the _PATH_DEV entry that matches. The devname() -** function can be used as a shortcut if _PATH_DEVDB exists. This returns a -** string like "sd1a", so we need to prepend _PATH_DEV to it. -*/ - -static char *getDevPath(dev_t target_dev) { - static char *dev = NULL; - char *name; - - if (dev == NULL) { - dev = malloc(MAXPATHLEN); - if (dev == NULL) - return NULL; - } - - strcpy(dev, _PATH_DEV); - - /* The root device in fstab should always be a block special device */ - name = devname(target_dev, S_IFBLK); - if (name == NULL) { - /* No _PATH_DEVDB. We have to search for it the slow way */ - DIR *dirp; - struct dirent *ent; - dirp = opendir(_PATH_DEV); - if (dirp == NULL) { - perror("opendir"); - return NULL; - } - while ((ent = readdir(dirp)) != NULL) { - /* Look for a block special device */ - if (ent->d_type == DT_BLK) { - struct stat devst; - strcat(dev, ent->d_name); - if (stat(dev, &devst) >= 0) { - if (devst.st_rdev == target_dev) { - return dev; - } - } - } - /* set dev to _PATH_DEV and try again */ - dev[sizeof(_PATH_DEV) - 1] = '\0'; - } - } else { - /* We found the _PATH_DEVDB entry */ - strcat(dev, name); - return dev; - } - return NULL; -} - -static int initrootentry(struct fstab *rootentry) -{ - char *rootpath = (char *)slash; - struct stat rootstat; - struct statfs rootfsinfo; - - if (stat(rootpath, &rootstat) < 0) { - perror("stat"); - return -1; - }; - if (statfs(rootpath, &rootfsinfo) < 0) { - perror("statfs"); - return -1; - }; - - /* Check to make sure we're not looking at a synthetic root: */ - if (strcmp(rootfsinfo.f_fstypename, "synthfs") == 0) { - rootpath = (char *)remountedroot; - if (stat(rootpath, &rootstat) < 0) { - perror("stat"); - return -1; - }; - if (statfs(rootpath, &rootfsinfo) < 0) { - perror("statfs"); - return -1; - }; - }; - - /* Copy the type name before returning a pointer a pointer to it */ - strncpy(_root_fstype, rootfsinfo.f_fstypename, MFSNAMELEN); - - rootentry->fs_spec = getDevPath(rootstat.st_dev); - rootentry->fs_file = rootpath; - rootentry->fs_vfstype = _root_fstype; - rootentry->fs_mntops = FSTAB_RW; - rootentry->fs_type = FSTAB_RW; - rootentry->fs_freq = 0; - rootentry->fs_passno = 1; - - return 0; -} - -static int fstabscan() -{ - register char *cp; -#define MAXLINELENGTH 1024 - static char *line = NULL; - char subline[MAXLINELENGTH]; - int typexx; - - if (!returnedRoot) { - returnedRoot = 1; - if (firstTime) { - firstTime = 0; - if (initrootentry(&_root_fstab) != 0) { - return 0; - }; - } - _fs_fstab = _root_fstab; - return 1; - } - if (!_fs_fp) { - return(0); - } - - if (line == NULL) { - line = malloc(MAXLINELENGTH); - if (line == NULL) - return 0; - } - - for (;;) { - if (!(cp = fgets(line, MAXLINELENGTH, _fs_fp))) - return(0); -/* OLD_STYLE_FSTAB */ - if (!strpbrk(cp, " \t")) { - _fs_fstab.fs_spec = strtok(cp, ":\n"); -#if defined(__APPLE__) - if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#') - continue; -#endif - _fs_fstab.fs_file = strtok((char *)NULL, ":\n"); - /* Only list the root filesystem once */ - if (!_fs_fstab.fs_file || !(strcmp(_fs_fstab.fs_file, "/"))) { - continue; - } - _fs_fstab.fs_type = strtok((char *)NULL, ":\n"); - if (_fs_fstab.fs_type) { - if (!strcmp(_fs_fstab.fs_type, FSTAB_XX)) - continue; - _fs_fstab.fs_mntops = _fs_fstab.fs_type; - _fs_fstab.fs_vfstype = - strcmp(_fs_fstab.fs_type, FSTAB_SW) ? - "ufs" : "swap"; - if ((cp = strtok((char *)NULL, ":\n"))) { - _fs_fstab.fs_freq = atoi(cp); - if ((cp = strtok((char *)NULL, ":\n"))) { - _fs_fstab.fs_passno = atoi(cp); - return(1); - } - } - } - goto bad; - } -/* OLD_STYLE_FSTAB */ - _fs_fstab.fs_spec = strtok(cp, " \t\n"); - if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#') - continue; - _fs_fstab.fs_file = strtok((char *)NULL, " \t\n"); - /* Only list the root filesystem once */ - if (!(strcmp(_fs_fstab.fs_file, "/"))) { - continue; - } - _fs_fstab.fs_vfstype = strtok((char *)NULL, " \t\n"); - _fs_fstab.fs_mntops = strtok((char *)NULL, " \t\n"); - if (_fs_fstab.fs_mntops == NULL) - goto bad; - _fs_fstab.fs_freq = 0; - _fs_fstab.fs_passno = 0; - if ((cp = strtok((char *)NULL, " \t\n")) != NULL) { - _fs_fstab.fs_freq = atoi(cp); - if ((cp = strtok((char *)NULL, " \t\n")) != NULL) - _fs_fstab.fs_passno = atoi(cp); - } - strcpy(subline, _fs_fstab.fs_mntops); - for (typexx = 0, cp = strtok(subline, ","); cp; - cp = strtok((char *)NULL, ",")) { - if (strlen(cp) != 2) - continue; - if (!strcmp(cp, FSTAB_RW)) { - _fs_fstab.fs_type = FSTAB_RW; - break; - } - if (!strcmp(cp, FSTAB_RQ)) { - _fs_fstab.fs_type = FSTAB_RQ; - break; - } - if (!strcmp(cp, FSTAB_RO)) { - _fs_fstab.fs_type = FSTAB_RO; - break; - } - if (!strcmp(cp, FSTAB_SW)) { - _fs_fstab.fs_type = FSTAB_SW; - break; - } - if (!strcmp(cp, FSTAB_XX)) { - _fs_fstab.fs_type = FSTAB_XX; - typexx++; - break; - } - } - if (typexx) - continue; - if (cp != NULL) - return(1); - -bad: /* no way to distinguish between EOF and syntax error */ - error(EFTYPE); - } - /* NOTREACHED */ -} - -struct fstab * -getfsent() -{ - if (!returnedRoot) { - setfsent(); - } - if (!fstabscan()) { - return((struct fstab *)NULL); - } - return(&_fs_fstab); -} - -struct fstab * -getfsspec(name) - register const char *name; -{ - if (setfsent()) - while (fstabscan()) - if (!strcmp(_fs_fstab.fs_spec, name)) - return(&_fs_fstab); - return((struct fstab *)NULL); -} - -struct fstab * -getfsfile(name) - register const char *name; -{ - if (setfsent()) - while (fstabscan()) - if (!strcmp(_fs_fstab.fs_file, name)) - return(&_fs_fstab); - return((struct fstab *)NULL); -} - -int -setfsent() -{ - returnedRoot = 0; - if (_fs_fp) { - rewind(_fs_fp); - } else { - _fs_fp = fopen(_PATH_FSTAB, "r"); - } - return(1); -} - -void -endfsent() -{ - returnedRoot = 0; - if (_fs_fp) { - (void)fclose(_fs_fp); - _fs_fp = NULL; - } -} - -static void error(err) - int err; -{ - char *p; - - (void)write(STDERR_FILENO, "fstab: ", 7); - (void)write(STDERR_FILENO, _PATH_FSTAB, sizeof(_PATH_FSTAB) - 1); - (void)write(STDERR_FILENO, ": ", 1); - p = strerror(err); - (void)write(STDERR_FILENO, p, strlen(p)); - (void)write(STDERR_FILENO, "\n", 1); -} diff --git a/gen.subproj/getgrent.c b/gen.subproj/getgrent.c deleted file mode 100644 index b867892..0000000 --- a/gen.subproj/getgrent.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include - -static FILE *_gr_fp; -static struct group _gr_group; -static int _gr_stayopen; -static int grscan(), start_gr(); - -#define MAXGRP 200 -static char *members[MAXGRP]; -#define MAXLINELENGTH 1024 -static char line[MAXLINELENGTH]; - -struct group * -getgrent() -{ - if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL)) - return(NULL); - return(&_gr_group); -} - -struct group * -getgrnam(name) - const char *name; -{ - int rval; - - if (!start_gr()) - return(NULL); - rval = grscan(1, 0, name); - if (!_gr_stayopen) - endgrent(); - return(rval ? &_gr_group : NULL); -} - -struct group * -#ifdef __STDC__ -getgrgid(gid_t gid) -#else -getgrgid(gid) - gid_t gid; -#endif -{ - int rval; - - if (!start_gr()) - return(NULL); - rval = grscan(1, gid, NULL); - if (!_gr_stayopen) - endgrent(); - return(rval ? &_gr_group : NULL); -} - -static int -start_gr() -{ - if (_gr_fp) { - rewind(_gr_fp); - return(1); - } - return((_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0); -} - -void -setgrent() -{ - setgroupent(0); -} - -int -setgroupent(stayopen) - int stayopen; -{ - if (!start_gr()) - return(0); - _gr_stayopen = stayopen; - return(1); -} - -void -endgrent() -{ - if (_gr_fp) { - (void)fclose(_gr_fp); - _gr_fp = NULL; - } -} - -static int -grscan(search, gid, name) - register int search, gid; - register char *name; -{ - register char *cp, **m; - char *bp; - char *fgets(), *strsep(), *index(); - - for (;;) { - if (!fgets(line, sizeof(line), _gr_fp)) - return(0); - bp = line; - /* skip lines that are too big */ - if (!index(line, '\n')) { - int ch; - - while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) - ; - continue; - } - _gr_group.gr_name = strsep(&bp, ":\n"); - if (search && name && strcmp(_gr_group.gr_name, name)) - continue; - _gr_group.gr_passwd = strsep(&bp, ":\n"); - if (!(cp = strsep(&bp, ":\n"))) - continue; - _gr_group.gr_gid = atoi(cp); - if (search && name == NULL && _gr_group.gr_gid != gid) - continue; - cp = NULL; - for (m = _gr_group.gr_mem = members;; bp++) { - if (m == &members[MAXGRP - 1]) - break; - if (*bp == ',') { - if (cp) { - *bp = '\0'; - *m++ = cp; - cp = NULL; - } - } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { - if (cp) { - *bp = '\0'; - *m++ = cp; - } - break; - } else if (cp == NULL) - cp = bp; - } - *m = NULL; - return(1); - } - /* NOTREACHED */ -} diff --git a/gen.subproj/gethostbyname.3 b/gen.subproj/gethostbyname.3 index 1789cb5..8737a10 100644 --- a/gen.subproj/gethostbyname.3 +++ b/gen.subproj/gethostbyname.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,62 +26,56 @@ .\" SUCH DAMAGE. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 -.\" $FreeBSD: src/lib/libc/net/gethostbyname.3,v 1.12.2.6 2001/08/17 15:42:38 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/gethostbyname.3,v 1.38 2007/01/09 00:28:02 imp Exp $ .\" -.Dd May 25, 1995 +.Dd May 12, 2006 .Dt GETHOSTBYNAME 3 .Os .Sh NAME -.Nm endhostent , -.Nm gethostbyaddr , .Nm gethostbyname , .Nm gethostbyname2 , +.Nm gethostbyaddr , .Nm gethostent , +.Nm sethostent , +.Nm endhostent , .Nm herror , -.Nm hstrerror , -.Nm sethostent +.Nm hstrerror .Nd get network host entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS -.Fd #include -.Vt extern int h_errno ; -.Ft void -.Fo endhostent -.Fa void -.Fc +.In netdb.h +.Vt int h_errno ; .Ft struct hostent * -.Fo gethostbyaddr -.Fa "const void *addr" -.Fa "socklen_t len" -.Fa "int type" -.Fc +.Fn gethostbyname "const char *name" .Ft struct hostent * -.Fo gethostbyname -.Fa "const char *name" -.Fc +.Fn gethostbyname2 "const char *name" "int af" .Ft struct hostent * -.Fo gethostbyname2 -.Fa "const char *name" -.Fa "int af" -.Fc +.Fn gethostbyaddr "const void *addr" "socklen_t len" "int type" .Ft struct hostent * -.Fo gethostent -.Fa void -.Fc +.Fn gethostent void .Ft void -.Fo herror -.Fa "const char *string" -.Fc -.Ft const char * -.Fo hstrerror -.Fa "int err" -.Fc +.Fn sethostent "int stayopen" .Ft void -.Fo sethostent -.Fa "int stayopen" -.Fc +.Fn endhostent void +.Ft void +.Fn herror "const char *string" +.Ft const char * +.Fn hstrerror "int err" .Sh DESCRIPTION +.Bf -symbolic +The +.Xr getaddrinfo 3 +and +.Xr getnameinfo 3 +functions are preferred over the +.Fn gethostbyname , +.Fn gethostbyname2 , +and +.Fn gethostbyaddr +functions. +.Ef +.Pp The .Fn gethostbyname , .Fn gethostbyname2 @@ -95,12 +85,50 @@ functions each return a pointer to an object with the following structure describing an internet host referenced by name or by address, respectively. -This structure contains either the information obtained from the name server, -.Xr named 8 , -or broken-out fields from a line in -.Pa /etc/hosts . -If the local name server is not running these routines do a lookup in +.Pp +The +.Fa name +argument passed to +.Fn gethostbyname +or +.Fn gethostbyname2 +should point to a +.Dv NUL Ns -terminated +hostname. +The +.Fa addr +argument passed to +.Fn gethostbyaddr +should point to an address which is +.Fa len +bytes long, +in binary form +(i.e., not an IP address in human readable +.Tn ASCII +form). +The +.Fa type +argument specifies the address family +(e.g.\& +.Dv AF_INET , AF_INET6 , +etc.) of this address. +.Pp +The structure returned contains information obtained from +.Xr DirectoryService 8 , +including records in .Pa /etc/hosts . +.\"The structure returned contains either the information obtained from the name +.\"server, +.\".Xr named 8 , +.\"broken-out fields from a line in +.\".Pa /etc/hosts , +.\"or database entries supplied by the +.\".Xr yp 8 +.\"system. +.\"The order of the lookups is controlled by the +.\".Sq hosts +.\"entry in +.\".Xr nsswitch.conf 5 . .Bd -literal struct hostent { char *h_name; /* official name of host */ @@ -142,13 +170,13 @@ and .Fn gethostbyname2 will search for the named host in the current domain and its parents unless the name ends in a dot. -If the name contains no dot, and if the environment variable -.Dq Ev HOSTALIASES -contains the name of an alias file, the alias file will first be searched -for an alias matching the input name. -See -.Xr hostname 7 -for the domain search procedure and the alias file format. +.\"If the name contains no dot, and if the environment variable +.\".Dq Ev HOSTALIASES +.\"contains the name of an alias file, the alias file will first be searched +.\"for an alias matching the input name. +.\"See +.\".Xr hostname 7 +.\"for the domain search procedure and the alias file format. .Pp The .Fn gethostbyname2 @@ -158,40 +186,39 @@ which is intended to allow lookups in address families other than .Dv AF_INET , for example .Dv AF_INET6 . -Both of these address families are supported in the Mac OS X implemention. -.Pp -The -.Fn sethostent -function -may be used to request the use of a connected -.Tn TCP -socket for queries. -If the -.Fa stayopen -flag is non-zero, -this sets the option to send all queries to the name server using -.Tn TCP -and to retain the connection after each call to -.Fn gethostbyname , -.Fn gethostbyname2 -or -.Fn gethostbyaddr . -Otherwise, queries are performed using -.Tn UDP -datagrams. -.Pp -The -.Fn endhostent -function -closes the -.Tn TCP -connection. .Pp +.\"The +.\".Fn sethostent +.\"function +.\"may be used to request the use of a connected +.\".Tn TCP +.\"socket for queries. +.\"If the +.\".Fa stayopen +.\"flag is non-zero, +.\"this sets the option to send all queries to the name server using +.\".Tn TCP +.\"and to retain the connection after each call to +.\".Fn gethostbyname , +.\".Fn gethostbyname2 +.\"or +.\".Fn gethostbyaddr . +.\"Otherwise, queries are performed using +.\".Tn UDP +.\"datagrams. +.\".Pp +.\"The +.\".Fn endhostent +.\"function +.\"closes the +.\".Tn TCP +.\"connection. +.\".Pp The .Fn herror function writes a message to the diagnostic output consisting of the -string parameter -.Fa s , +string argument +.Fa string , the constant string .Qq Li ":\ " , and a message corresponding to the value of @@ -202,13 +229,29 @@ The function returns a string which is the message text corresponding to the value of the .Fa err -parameter. +argument. .Sh FILES -.Bl -tag -width /etc/resolv.conf -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts -.It Pa /etc/host.conf +.\".It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El +.Sh EXAMPLES +Print out the hostname associated with a specific IP address: +.Bd -literal -offset indent +const char *ipstr = "127.0.0.1"; +struct in_addr ip; +struct hostent *hp; + +if (!inet_aton(ipstr, &ip)) + errx(1, "can't parse IP address %s", ipstr); + +if ((hp = gethostbyaddr((const void *)&ip, + sizeof ip, AF_INET)) == NULL) + errx(1, "no name associated with %s", ipstr); + +printf("name associated with %s is %s\en", ipstr, hp->h_name); +.Ed .Sh DIAGNOSTICS Error return status from .Fn gethostbyname , @@ -218,7 +261,7 @@ and is indicated by return of a .Dv NULL pointer. -The external integer +The integer .Va h_errno may then be checked to see whether this is a temporary failure or an invalid or unknown host. @@ -255,28 +298,15 @@ Another type of request to the name server using this domain name will result in an answer; for example, a mail-forwarder may be registered for this domain. .El -.Sh LEGACY SYNOPSIS -.Fd #include -.Pp -.Vt extern int h_errno ; -.Pp -.Ft struct hostent * -.br -.Fo gethostbyaddr -.Fa "const void *addr" -.Fa "socklen_t len" -.Fa "int type" -.Fc ; -.Pp -The type of -.Fa addr -has changed slightly. .Sh SEE ALSO .Xr getaddrinfo 3 , +.Xr getnameinfo 3 , +.Xr inet_aton 3 , .Xr resolver 3 , .Xr hosts 5 , .Xr hostname 7 , -.Xr named 8 +.Xr DirectoryService 8 +.\".Xr named 8 .Sh CAVEAT The .Fn gethostent @@ -286,7 +316,9 @@ is defined, and and .Fn endhostent are redefined, -when libc is built to use only the routines to lookup in +when +.Lb libc +is built to use only the routines to lookup in .Pa /etc/hosts and not the name server. .Pp @@ -335,8 +367,14 @@ function first appeared in .Tn BIND version 4.9.4. .Sh BUGS -These functions use static data storage; +These functions use a thread-specific data storage; if the data is needed for future use, it should be copied before any subsequent calls overwrite it. +.Pp +Though these functions are thread-safe, +still it is recommended to use the +.Xr getaddrinfo 3 +family of functions, instead. +.Pp Only the Internet address format is currently understood. diff --git a/gen.subproj/getifaddrs.3 b/gen.subproj/getifaddrs.3 index 6709032..201db10 100644 --- a/gen.subproj/getifaddrs.3 +++ b/gen.subproj/getifaddrs.3 @@ -1,4 +1,3 @@ -.\" $FreeBSD: src/lib/libc/net/getifaddrs.3,v 1.1.2.4 2001/08/31 10:15:14 ru Exp $ .\" $KAME: getifaddrs.3,v 1.4 2000/05/17 14:13:14 itojun Exp $ .\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp .\" @@ -22,6 +21,9 @@ .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. +.\" +.\" $FreeBSD: src/lib/libc/net/getifaddrs.3,v 1.10 2005/02/09 18:03:13 ru Exp $ +.\" .Dd October 12, 1995 .Dt GETIFADDRS 3 .Os @@ -29,9 +31,9 @@ .Nm getifaddrs .Nd get interface addresses .Sh SYNOPSIS -.Fd #include -.Fd #include -.Fd #include +.In sys/types.h +.In sys/socket.h +.In ifaddrs.h .Ft int .Fn getifaddrs "struct ifaddrs **ifap" .Ft void @@ -45,7 +47,7 @@ on the local machine in the memory referenced by The list consists of .Nm ifaddrs structures, as defined in the include file -.Aq Pa ifaddrs.h . +.In ifaddrs.h . The .Nm ifaddrs structure contains at least the following entries: @@ -55,6 +57,7 @@ structure contains at least the following entries: u_int ifa_flags; /* Interface flags */ struct sockaddr *ifa_addr; /* Interface address */ struct sockaddr *ifa_netmask; /* Interface netmask */ +.\" struct sockaddr *ifa_broadaddr; /* Interface broadcast address */ struct sockaddr *ifa_dstaddr; /* P2P interface destination */ void *ifa_data; /* Address specific data */ .Ed @@ -108,17 +111,18 @@ directive to be the same as .Pp The .Li ifa_data -field references address family specific data. For +field references address family specific data. +For .Dv AF_LINK addresses it contains a pointer to the .Fa struct if_data (as defined in include file -.Aq Pa net/if.h ) +.In net/if.h ) which contains various interface attributes and statistics. For all other address families, it contains a pointer to the .Fa struct ifa_data (as defined in include file -.Aq Pa net/if.h ) +.In net/if.h ) which contains per-address interface statistics. .Pp The data returned by @@ -139,16 +143,6 @@ for any of the errors specified for the library routines .Xr malloc 3 or .Xr sysctl 3 . -.Sh BUGS -If both -.Aq Pa net/if.h -and -.Aq Pa ifaddrs.h -are being included, -.Aq Pa net/if.h -.Em must -be included before -.Aq Pa ifaddrs.h . .Sh SEE ALSO .Xr ioctl 2 , .Xr socket 2 , @@ -160,3 +154,13 @@ The .Nm implementation first appeared in BSDi .Bsx . +.Sh BUGS +If both +.In net/if.h +and +.In ifaddrs.h +are being included, +.In net/if.h +.Em must +be included before +.In ifaddrs.h . diff --git a/gen.subproj/getifaddrs.c b/gen.subproj/getifaddrs.c index 63c4bfc..4de879e 100644 --- a/gen.subproj/getifaddrs.c +++ b/gen.subproj/getifaddrs.c @@ -84,7 +84,7 @@ #endif #define MEMORY_MIN 2048 -#define MEMORY_MAX 4194304 +#define MEMORY_MAX 16777216 int getifaddrs(struct ifaddrs **pif) @@ -131,6 +131,9 @@ getifaddrs(struct ifaddrs **pif) if (needed < MEMORY_MIN) needed = MEMORY_MIN; needed *= 2; + if (needed > MEMORY_MAX) needed = MEMORY_MAX; + + buf = NULL; while (needed <= MEMORY_MAX) { @@ -145,6 +148,12 @@ getifaddrs(struct ifaddrs **pif) needed *= 2; } + if (buf == NULL) + { + errno = ENOBUFS; + return (-1); + } + for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; if (rtm->rtm_version != RTM_VERSION) diff --git a/gen.subproj/getipnodebyname.3 b/gen.subproj/getipnodebyname.3 index 0e15009..a4cbb1e 100644 --- a/gen.subproj/getipnodebyname.3 +++ b/gen.subproj/getipnodebyname.3 @@ -1,4 +1,3 @@ -.\" $FreeBSD: src/lib/libc/net/getipnodebyname.3,v 1.2.2.3 2001/08/17 15:42:38 ru Exp $ .\" $KAME: getipnodebyname.3,v 1.6 2000/08/09 21:16:17 itojun Exp $ .\" .\" Copyright (c) 1983, 1987, 1991, 1993 @@ -12,10 +11,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -33,8 +28,9 @@ .\" SUCH DAMAGE. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 +.\" $FreeBSD: src/lib/libc/net/getipnodebyname.3,v 1.18 2007/01/09 00:28:02 imp Exp $ .\" -.Dd May 25, 1995 +.Dd August 6, 2004 .Dt GETIPNODEBYNAME 3 .Os .\" @@ -47,9 +43,9 @@ .Sh LIBRARY .Lb libc .Sh SYNOPSIS -.Fd #include -.Fd #include -.Fd #include +.In sys/types.h +.In sys/socket.h +.In netdb.h .Ft "struct hostent *" .Fn getipnodebyname "const char *name" "int af" "int flags" "int *error_num" .Ft "struct hostent *" @@ -58,6 +54,7 @@ .Fn freehostent "struct hostent *ptr" .\" .Sh DESCRIPTION +The .Fn getipnodebyname and .Fn getipnodebyaddr @@ -69,9 +66,9 @@ and The functions cover all the functionalities provided by the older ones, and provide better interface to programmers. The functions require additional arguments, -.Ar af , +.Fa af , and -.Ar flags , +.Fa flags , for specifying address family and operation mode. The additional arguments allow programmer to get address for a nodename, for specific address family @@ -80,7 +77,7 @@ for specific address family or .Dv AF_INET6 ) . The functions also require an additional pointer argument, -.Ar error_num +.Fa error_num to return the appropriate error code, to support thread safe error code returns. .Pp @@ -92,18 +89,18 @@ is described in For .Fn getipnodebyname , the -.Ar name +.Fa name argument can be either a node name or a numeric address string (i.e., a dotted-decimal IPv4 address or an IPv6 hex address). The -.Ar af +.Fa af argument specifies the address family, either .Dv AF_INET or .Dv AF_INET6 . The -.Ar flags +.Fa flags argument specifies the types of addresses that are searched for, and the types of addresses that are returned. We note that a special flags value of @@ -122,22 +119,22 @@ with .Pp Applications desiring finer control over the types of addresses searched for and returned, can specify other combinations of the -.Ar flags +.Fa flags argument. .Pp A -.Ar flags +.Fa flags of .Li 0 implies a strict interpretation of the -.Ar af +.Fa af argument: .Bl -bullet .It If -.Ar flags +.Fa flags is 0 and -.Ar af +.Fa af is .Dv AF_INET , then the caller wants only IPv4 addresses. @@ -153,9 +150,9 @@ structure will be 4, else the function returns a pointer. .It If -.Ar flags +.Fa flags is 0 and if -.Ar af +.Fa af is .Li AF_INET6 , then the caller wants only IPv6 addresses. @@ -172,14 +169,14 @@ pointer. .El .Pp Other constants can be logically-ORed into the -.Ar flags +.Fa flags argument, to modify the behavior of the function. .Bl -bullet .It If the .Dv AI_V4MAPPED flag is specified along with an -.Ar af +.Fa af of .Dv AF_INET6 , then the caller will accept IPv4-mapped IPv6 addresses. @@ -193,7 +190,7 @@ will be 16). The .Dv AI_V4MAPPED flag is ignored unless -.Ar af +.Fa af equals .Dv AF_INET6 . .It @@ -216,15 +213,19 @@ flag then the caller wants all addresses: IPv6 and IPv4-mapped IPv6. A query is first made for .Li AAAA records and if successful, the -IPv6 addresses are returned. Another query is then made for +IPv6 addresses are returned. +Another query is then made for .Li A records and any found are returned as IPv4-mapped IPv6 addresses. .Li h_length -will be 16. Only if both queries fail does the function +will be 16. +Only if both queries fail does the function return a .Dv NULL -pointer. This flag is ignored unless af equals -AF_INET6. If both +pointer. +This flag is ignored unless af equals +AF_INET6. +If both .Dv AI_ALL and .Dv AI_V4MAPPED @@ -245,7 +246,7 @@ configured. .Pp For example, if the node has no IPv6 source addresses configured, and -.Ar af +.Fa af equals AF_INET6, and the node name being looked up has both .Li AAAA and @@ -276,40 +277,40 @@ is defined as We noted that the .Fn getipnodebyname function must allow the -.Ar name +.Fa name argument to be either a node name or a literal address string (i.e., a dotted-decimal IPv4 address or an IPv6 hex address). This saves applications from having to call .Xr inet_pton 3 to handle literal address strings. When the -.Ar name +.Fa name argument is a literal address string, the -.Ar flags +.Fa flags argument is always ignored. .Pp There are four scenarios based on the type of literal address string and the value of the -.Ar af +.Fa af argument. The two simple cases are when -.Ar name +.Fa name is a dotted-decimal IPv4 address and -.Ar af +.Fa af equals .Dv AF_INET , or when -.Ar name +.Fa name is an IPv6 hex address and -.Ar af +.Fa af equals .Dv AF_INET6 . The members of the returned hostent structure are: .Li h_name points to a copy of the -.Ar name +.Fa name argument, .Li h_aliases is a @@ -317,7 +318,7 @@ is a pointer, .Li h_addrtype is a copy of the -.Ar af +.Fa af argument, .Li h_length is either 4 @@ -335,9 +336,9 @@ is a pointer. .Pp When -.Ar name +.Fa name is a dotted-decimal IPv4 address and -.Ar af +.Fa af equals .Dv AF_INET6 , and @@ -363,60 +364,71 @@ is a pointer. .Pp It is an error when -.Ar name +.Fa name is an IPv6 hex address and -.Ar af +.Fa af equals .Dv AF_INET . The function's return value is a .Dv NULL pointer and the value pointed to by -.Ar error_num +.Fa error_num equals .Dv HOST_NOT_FOUND . .Pp +The .Fn getipnodebyaddr +function takes almost the same argument as .Xr gethostbyaddr 3 , but adds a pointer to return an error number. Additionally it takes care of IPv4-mapped IPv6 addresses, and IPv4-compatible IPv6 addresses. .Pp +The .Fn getipnodebyname and .Fn getipnodebyaddr +functions dynamically allocate the structure to be returned to the caller. +The .Fn freehostent +function reclaims memory region allocated and returned by .Fn getipnodebyname or .Fn getipnodebyaddr . .\" .Sh FILES -.Bl -tag -width /etc/resolv.conf -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts -.It Pa /etc/host.conf +.\".It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El .\" .Sh DIAGNOSTICS +The .Fn getipnodebyname and .Fn getipnodebyaddr +functions returns .Dv NULL on errors. The integer values pointed to by -.Ar error_num +.Fa error_num may then be checked to see whether this is a temporary failure or an invalid or unknown host. The meanings of each error code are described in .Xr gethostbyname 3 . .\" .Sh SEE ALSO +.Xr getaddrinfo 3 , .Xr gethostbyaddr 3 , .Xr gethostbyname 3 , +.Xr getnameinfo 3 , .Xr hosts 5 , +.Xr nsswitch.conf 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 @@ -431,21 +443,25 @@ The meanings of each error code are described in .%D March 1999 .Re .\" -.Sh HISTORY -The implementation first appeared in KAME advanced networking kit. -.\" .Sh STANDARDS +The .Fn getipnodebyname and .Fn getipnodebyaddr +functions are documented in .Dq Basic Socket Interface Extensions for IPv6 (RFC2553). .\" +.Sh HISTORY +The implementation first appeared in KAME advanced networking kit. +.\" .Sh BUGS +The .Fn getipnodebyname and .Fn getipnodebyaddr +functions do not handle scoped IPv6 address properly. If you use these functions, your program will not be able to handle scoped IPv6 addresses. diff --git a/gen.subproj/getnetent.3 b/gen.subproj/getnetent.3 index 7786ce0..5e34499 100644 --- a/gen.subproj/getnetent.3 +++ b/gen.subproj/getnetent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,43 +26,32 @@ .\" SUCH DAMAGE. .\" .\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/net/getnetent.3,v 1.11.2.3 2001/08/17 15:42:38 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/getnetent.3,v 1.23 2007/01/09 00:28:02 imp Exp $ .\" .Dd June 4, 1993 .Dt GETNETENT 3 .Os .Sh NAME -.Nm endnetent , +.Nm getnetent , .Nm getnetbyaddr , .Nm getnetbyname , -.Nm getnetent , -.Nm setnetent +.Nm setnetent , +.Nm endnetent .Nd get network entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS -.Fd #include -.Ft void -.Fo endnetent -.Fa void -.Fc +.In netdb.h .Ft struct netent * -.Fo getnetbyaddr -.Fa "uint32_t net" -.Fa "int type" -.Fc +.Fn getnetent void .Ft struct netent * -.Fo getnetbyname -.Fa "const char *name" -.Fc +.Fn getnetbyname "const char *name" .Ft struct netent * -.Fo getnetent -.Fa void -.Fc +.Fn getnetbyaddr "uint32_t net" "int type" .Ft void -.Fo setnetent -.Fa "int stayopen" -.Fc +.Fn setnetent "int stayopen" +.Ft void +.Fn endnetent void .Sh DESCRIPTION The .Fn getnetent , @@ -75,16 +60,29 @@ and .Fn getnetbyaddr functions each return a pointer to an object with the -following structure -containing the broken-out -fields of a line in the network data base, +following structure describing an internet network. +.\"This structure contains either the information obtained +.\"from the nameserver, +.\".Xr named 8 , +.\"broken-out fields of a line in the network data base +.\".Pa /etc/networks , +.\"or entries supplied by the +.\".Xr yp 8 +.\"system. +.\"The order of the lookups is controlled by the +.\"`networks' entry in +.\".Xr nsswitch.conf 5 . +This structure contains information obtained from +.Xr DirectoryService 8 , +including records in .Pa /etc/networks . +.Pp .Bd -literal -offset indent struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net number type */ - unsigned long n_net; /* net number */ + uint32_t n_net; /* net number */ }; .Ed .Pp @@ -97,7 +95,8 @@ A zero terminated list of alternate names for the network. .It Fa n_addrtype The type of the network number returned; currently only AF_INET. .It Fa n_net -The network number. Network numbers are returned in machine byte +The network number. +Network numbers are returned in machine byte order. .El .Pp @@ -109,7 +108,8 @@ reads the next line of the file, opening the file if necessary. The .Fn setnetent function -opens and rewinds the file. If the +opens and rewinds the file. +If the .Fa stayopen flag is non-zero, the net data base will not be closed after each call to @@ -136,12 +136,15 @@ or until is encountered. The .Fa type +argument must be .Dv AF_INET . Network numbers are supplied in host order. .Sh FILES -.Bl -tag -width /etc/networks -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/networks +.\".It Pa /etc/nsswitch.conf +.It Pa /etc/resolv.conf .El .Sh DIAGNOSTICS Null pointer @@ -164,7 +167,7 @@ functions appeared in .Bx 4.2 . .Sh BUGS The data space used by -these functions is static; if future use requires the data, it should be +these functions is thread-specific; if future use requires the data, it should be copied before any subsequent calls to these functions overwrite it. Only Internet network numbers are currently understood. diff --git a/gen.subproj/getproto.c b/gen.subproj/getproto.c deleted file mode 100644 index 1f09b7c..0000000 --- a/gen.subproj/getproto.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include - -extern int _proto_stayopen; - -struct protoent * -getprotobynumber(proto) - register int proto; -{ - register struct protoent *p; - - setprotoent(_proto_stayopen); - while ((p = getprotoent())) - if (p->p_proto == proto) - break; - if (!_proto_stayopen) - endprotoent(); - return (p); -} diff --git a/gen.subproj/getprotoent.3 b/gen.subproj/getprotoent.3 index 5a22328..71d6659 100644 --- a/gen.subproj/getprotoent.3 +++ b/gen.subproj/getprotoent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,42 +26,32 @@ .\" SUCH DAMAGE. .\" .\" @(#)getprotoent.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/net/getprotoent.3,v 1.4.2.3 2001/08/17 15:42:38 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/getprotoent.3,v 1.12 2007/01/09 00:28:02 imp Exp $ .\" .Dd June 4, 1993 .Dt GETPROTOENT 3 .Os .Sh NAME -.Nm endprotoent , -.Nm getprotobyname , -.Nm getprotobynumber , .Nm getprotoent , -.Nm setprotoent +.Nm getprotobynumber , +.Nm getprotobyname , +.Nm setprotoent , +.Nm endprotoent .Nd get protocol entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS -.Fd #include -.Ft void -.Fo endprotoent -.Fa void -.Fc +.In netdb.h .Ft struct protoent * -.Fo getprotobyname -.Fa "const char *name" -.Fc +.Fn getprotoent void .Ft struct protoent * -.Fo getprotobynumber -.Fa "int proto" -.Fc +.Fn getprotobyname "const char *name" .Ft struct protoent * -.Fo getprotoent -.Fa void -.Fc +.Fn getprotobynumber "int proto" +.Ft void +.Fn setprotoent "int stayopen" .Ft void -.Fo setprotoent -.Fa "int stayopen" -.Fc +.Fn endprotoent void .Sh DESCRIPTION The .Fn getprotoent , @@ -78,8 +64,8 @@ following structure containing the broken-out fields of a line in the network protocol data base, .Pa /etc/protocols . -.Bd -literal -offset indent .Pp +.Bd -literal -offset indent struct protoent { char *p_name; /* official name of protocol */ char **p_aliases; /* alias list */ @@ -105,7 +91,8 @@ reads the next line of the file, opening the file if necessary. The .Fn setprotoent function -opens and rewinds the file. If the +opens and rewinds the file. +If the .Fa stayopen flag is non-zero, the net data base will not be closed after each call to @@ -152,7 +139,7 @@ and functions appeared in .Bx 4.2 . .Sh BUGS -These functions use a static data space; +These functions use a thread-specific data space; if the data is needed for future use, it should be copied before any subsequent calls overwrite it. Only the Internet diff --git a/gen.subproj/getprotoent.c b/gen.subproj/getprotoent.c deleted file mode 100644 index ed158c9..0000000 --- a/gen.subproj/getprotoent.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include -#include - -#define MAXALIASES 35 - -static FILE *protof = NULL; -static struct protoent proto; -static char *proto_aliases[MAXALIASES]; -int _proto_stayopen; - -void -setprotoent(f) - int f; -{ - if (protof == NULL) - protof = fopen(_PATH_PROTOCOLS, "r" ); - else - rewind(protof); - _proto_stayopen |= f; -} - -void -endprotoent() -{ - if (protof) { - fclose(protof); - protof = NULL; - } - _proto_stayopen = 0; -} - -struct protoent * -getprotoent() -{ - char *p; - static char *line = NULL; - register char *cp, **q; - - if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) - return (NULL); - - if (line == NULL) { - line = malloc(BUFSIZ+1); - if (line == NULL) - return (NULL); - } -again: - if ((p = fgets(line, BUFSIZ, protof)) == NULL) - return (NULL); - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - proto.p_name = p; - cp = strpbrk(p, " \t"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - while (*cp == ' ' || *cp == '\t') - cp++; - p = strpbrk(cp, " \t"); - if (p != NULL) - *p++ = '\0'; - proto.p_proto = atoi(cp); - q = proto.p_aliases = proto_aliases; - if (p != NULL) { - cp = p; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &proto_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - } - *q = NULL; - return (&proto); -} diff --git a/gen.subproj/getprotoname.c b/gen.subproj/getprotoname.c deleted file mode 100644 index 0e4b7f3..0000000 --- a/gen.subproj/getprotoname.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -extern int _proto_stayopen; - -struct protoent * -getprotobyname(name) - register const char *name; -{ - register struct protoent *p; - register char **cp; - - setprotoent(_proto_stayopen); - while ((p = getprotoent())) { - if (strcmp(p->p_name, name) == 0) - break; - for (cp = p->p_aliases; *cp != 0; cp++) - if (strcmp(*cp, name) == 0) - goto found; - } -found: - if (!_proto_stayopen) - endprotoent(); - return (p); -} diff --git a/gen.subproj/getpwent.c b/gen.subproj/getpwent.c deleted file mode 100644 index 01a9eee..0000000 --- a/gen.subproj/getpwent.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (c) 2007 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright 1997 Apple Computer, Inc. (unpublished) - * - * /etc/passwd file access routines. - * Just read from the /etc/passwd file and skip the dbm database, since - * Directory Service does all flat file lookups when the system is multi-user. - * These routines are only used in single-user mode. - * - * 17 Apr 1997 file created - Marc Majka - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define forever for (;;) - -#define _PWENT_ 0 -#define _PWNAM_ 1 -#define _PWUID_ 2 - -static struct passwd _pw = { 0 }; -static FILE *_pfp = NULL; -static int _pwFileFormat = 1; - -#define _HENT_ 0 -#define _HNAM_ 1 -#define _HADDR_ 2 - -static struct hostent _h = { 0 }; -static FILE *_hfp = NULL; - -/* Forward */ -__private_extern__ void LI_files_setpwent(); -__private_extern__ void LI_files_endhostent(); - -static void -freeList(char **l) -{ - int i; - - if (l == NULL) return; - for (i = 0; l[i] != NULL; i++) - { - if (l[i] != NULL) free(l[i]); - l[i] = NULL; - } - if (l != NULL) free(l); -} - -static unsigned int -listLength(char **l) -{ - int i; - - if (l == NULL) return 0; - for (i = 0; l[i] != NULL; i++); - return i; -} - -static char * -copyString(char *s) -{ - int len; - char *t; - - if (s == NULL) return NULL; - - len = strlen(s) + 1; - t = malloc(len); - bcopy(s, t, len); - return t; -} - - -static char ** -insertString(char *s, char **l, unsigned int x) -{ - int i, len; - - if (s == NULL) return l; - if (l == NULL) - { - l = (char **)malloc(2 * sizeof(char *)); - l[0] = copyString(s); - l[1] = NULL; - return l; - } - - for (i = 0; l[i] != NULL; i++); - len = i + 1; /* count the NULL on the end of the list too! */ - - l = (char **)realloc(l, (len + 1) * sizeof(char *)); - - if ((x >= (len - 1)) || (x == (unsigned int)-1)) - { - l[len - 1] = copyString(s); - l[len] = NULL; - return l; - } - - for (i = len; i > x; i--) l[i] = l[i - 1]; - l[x] = copyString(s); - return l; -} - -static char ** -appendString(char *s, char **l) -{ - return insertString(s, l, (unsigned int)-1); -} - -static char ** -tokenize(const char *data, const char *sep) -{ - char **tokens = NULL; - const char *p; - int i, j, len; - char buf[4096]; - int scanning; - - if (data == NULL) return NULL; - if (sep == NULL) - { - tokens = appendString((char *)data, tokens); - return tokens; - } - - len = strlen(sep); - - p = data; - - while (p[0] != '\0') - { - /* skip leading white space */ - while ((p[0] == ' ') || (p[0] == '\t') || (p[0] == '\n')) p++; - - /* check for end of line */ - if (p[0] == '\0') break; - - /* copy data */ - i = 0; - scanning = 1; - for (j = 0; (j < len) && (scanning == 1); j++) - { - if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0; - } - - while (scanning == 1) - { - buf[i++] = p[0]; - p++; - for (j = 0; (j < len) && (scanning == 1); j++) - { - if (p[0] == sep[j] || (p[0] == '\0')) scanning = 0; - } - } - - /* back over trailing whitespace */ - i--; - if (i > -1) { /* did we actually copy anything? */ - while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\n')) i--; - } - buf[++i] = '\0'; - - tokens = appendString(buf, tokens); - - /* check for end of line */ - if (p[0] == '\0') break; - - /* skip separator */ - scanning = 1; - for (j = 0; (j < len) && (scanning == 1); j++) - { - if (p[0] == sep[j]) - { - p++; - scanning = 0; - } - } - - if ((scanning == 0) && p[0] == '\0') - { - /* line ended at a separator - add a null member */ - tokens = appendString("", tokens); - return tokens; - } - } - - return tokens; -} - -static char * -getLine(FILE *fp) -{ - char s[1024]; - char *out; - - s[0] = '\0'; - - fgets(s, 1024, fp); - if ((s == NULL) || (s[0] == '\0')) return NULL; - - if (s[0] != '#') s[strlen(s) - 1] = '\0'; - - out = copyString(s); - return out; -} - -/* USERS */ - -static void -LI_files_free_user() -{ - if (_pw.pw_name != NULL) free(_pw.pw_name); - if (_pw.pw_passwd != NULL) free(_pw.pw_passwd); - if (_pw.pw_class != NULL) free(_pw.pw_class); - if (_pw.pw_gecos != NULL) free(_pw.pw_gecos); - if (_pw.pw_dir != NULL) free(_pw.pw_dir); - if (_pw.pw_shell != NULL) free(_pw.pw_shell); - - _pw.pw_name = NULL; - _pw.pw_passwd = NULL; - _pw.pw_class = NULL; - _pw.pw_gecos = NULL; - _pw.pw_dir = NULL; - _pw.pw_shell = NULL; -} - -static struct passwd * -LI_files_parse_user(char *data) -{ - char **tokens; - int ntokens; - - if (data == NULL) return NULL; - - tokens = tokenize(data, ":"); - ntokens = listLength(tokens); - if (( _pwFileFormat && (ntokens != 10)) || - (!_pwFileFormat && (ntokens != 7))) - { - freeList(tokens); - return NULL; - } - - LI_files_free_user(); - - _pw.pw_name = tokens[0]; - _pw.pw_passwd = tokens[1]; - _pw.pw_uid = atoi(tokens[2]); - free(tokens[2]); - _pw.pw_gid = atoi(tokens[3]); - free(tokens[3]); - - if (_pwFileFormat) - { - _pw.pw_class = tokens[4]; - _pw.pw_change = atoi(tokens[5]); - free(tokens[5]); - _pw.pw_expire = atoi(tokens[6]); - free(tokens[6]); - _pw.pw_gecos = tokens[7]; - _pw.pw_dir = tokens[8]; - _pw.pw_shell = tokens[9]; - } - else - { - _pw.pw_class = copyString(""); - _pw.pw_change = 0; - _pw.pw_expire = 0; - _pw.pw_gecos = tokens[4]; - _pw.pw_dir = tokens[5]; - _pw.pw_shell = tokens[6]; - } - - free(tokens); - - return &_pw; -} - -static struct passwd * -LI_files_getpw(const char *name, uid_t uid, int which) -{ - char *line; - struct passwd *pw; - - if (_pfp == NULL) LI_files_setpwent(); - if (_pfp == NULL) return NULL; - - if (which != _PWENT_) rewind(_pfp); - - forever - { - line = getLine(_pfp); - if (line == NULL) break; - - if (line[0] == '#') - { - free(line); - line = NULL; - continue; - } - - pw = LI_files_parse_user(line); - free(line); - line = NULL; - - if (pw == NULL) continue; - - if (which == _PWENT_) return pw; - - if (((which == _PWNAM_) && (!strcmp(name, pw->pw_name))) || ((which == _PWUID_) && (uid == pw->pw_uid))) - { - fclose(_pfp); - _pfp = NULL; - return pw; - } - } - - fclose(_pfp); - _pfp = NULL; - - return NULL; -} - -/* "Public" */ - -__private_extern__ struct passwd * -LI_files_getpwent() -{ - return LI_files_getpw(NULL, 0, _PWENT_); -} - -__private_extern__ struct passwd * -LI_files_getpwnam(const char *name) -{ - return LI_files_getpw(name, 0, _PWNAM_); -} - -__private_extern__ struct passwd * -LI_files_getpwuid(uid_t uid) -{ - return LI_files_getpw(NULL, uid, _PWUID_); -} - -int -setpassent(int stayopen) -{ - return 1; -} - -__private_extern__ void -LI_files_setpwent() -{ - if (_pfp == NULL) - { - char *pwFile; - if (geteuid() == 0) - { - pwFile = _PATH_MASTERPASSWD; - } - else - { - pwFile = _PATH_PASSWD; - _pwFileFormat = 0; - } - - _pfp = fopen(pwFile, "r"); - } - else rewind(_pfp); -} - -__private_extern__ void -LI_files_endpwent() -{ - if (_pfp != NULL) - { - fclose(_pfp); - _pfp = NULL; - } -} - -/* HOSTS */ - -static void -LI_files_free_host() -{ - int i; - - if (_h.h_name != NULL) free(_h.h_name); - - if (_h.h_aliases != NULL) - { - for (i = 0; _h.h_aliases[i] != NULL; i++) free(_h.h_aliases[i]); - free(_h.h_aliases); - } - - if (_h.h_addr_list != NULL) - { - for (i = 0; _h.h_addr_list[i] != NULL; i++) free(_h.h_addr_list[i]); - free(_h.h_addr_list); - } - - _h.h_name = NULL; - _h.h_aliases = NULL; - _h.h_addrtype = 0; - _h.h_length = 0; - _h.h_addr_list = NULL; -} - -static struct hostent * -LI_files_parse_host(char *data) -{ - char **tokens, *addrstr; - int i, ntokens, af; - struct in_addr a4; - struct in6_addr a6; - - if (data == NULL) return NULL; - - tokens = tokenize(data, " "); - ntokens = listLength(tokens); - if (ntokens < 2) - { - freeList(tokens); - return NULL; - } - - LI_files_free_host(); - - af = AF_UNSPEC; - if (inet_pton(AF_INET, tokens[0], &a4) == 1) af = AF_INET; - else if (inet_pton(AF_INET6, tokens[0], &a6) == 1) af = AF_INET6; - - if (af == AF_UNSPEC) - { - freeList(tokens); - return NULL; - } - - addrstr = tokens[0]; - - _h.h_addrtype = af; - if (af == AF_INET) - { - _h.h_length = sizeof(struct in_addr); - _h.h_addr_list = (char **)calloc(2, sizeof(char *)); - _h.h_addr_list[0] = (char *)calloc(1, _h.h_length); - memcpy(_h.h_addr_list[0], &a4, _h.h_length); - } - else - { - _h.h_length = sizeof(struct in6_addr); - _h.h_addr_list = (char **)calloc(2, sizeof(char *)); - _h.h_addr_list[0] = (char *)calloc(1, _h.h_length); - memcpy(_h.h_addr_list[0], &a6, _h.h_length); - } - - _h.h_name = tokens[1]; - - _h.h_aliases = (char **)calloc(ntokens - 1, sizeof(char *)); - for (i = 2; i < ntokens; i++) _h.h_aliases[i-2] = tokens[i]; - - free(addrstr); - free(tokens); - - return &_h; -} - -static struct hostent * -LI_files_get_host(const char *name, const void *addr, int af, int which) -{ - char *line; - struct hostent *h; - int i, got_host; - - if ((which == _HADDR_) && (addr == NULL)) return NULL; - - if (_hfp == NULL) _hfp = fopen(_PATH_HOSTS, "r"); - if (_hfp == NULL) return NULL; - - if (which != _HENT_) rewind(_hfp); - - forever - { - line = getLine(_hfp); - if (line == NULL) break; - - if (line[0] == '#') - { - free(line); - line = NULL; - continue; - } - - h = LI_files_parse_host(line); - free(line); - line = NULL; - - if (h == NULL) continue; - - if (which == _HENT_) return h; - - got_host = 0; - - if ((which == _HNAM_) && (af == h->h_addrtype)) - { - if (!strcmp(name, h->h_name)) got_host = 1; - else if (h->h_aliases != NULL) - { - for (i = 0; (h->h_aliases[i] != NULL) && (got_host == 0); i++) - if (!strcmp(name, h->h_aliases[i])) got_host = 1; - } - } - - if ((which == _HADDR_) && (h->h_addrtype == af)) - { - for (i = 0; (h->h_addr_list[i] != NULL) && (got_host == 0); i++) - if (memcmp(addr, h->h_addr_list[i], h->h_length) == 0) got_host = 1; - } - - if (got_host == 1) - { - fclose(_hfp); - _hfp = NULL; - return h; - } - } - - fclose(_hfp); - _hfp = NULL; - - return NULL; -} - -/* "Public" */ - -__private_extern__ struct hostent * -LI_files_gethostbyname(const char *name) -{ - return LI_files_get_host(name, NULL, AF_INET, _HNAM_); -} - -__private_extern__ struct hostent * -LI_files_gethostbyname2(const char *name, int af) -{ - return LI_files_get_host(name, NULL, af, _HNAM_); -} - -__private_extern__ struct hostent * -LI_files_gethostbyaddr(const void *addr, socklen_t len, int type) -{ - if ((type == AF_INET) || (type == AF_INET6)) return LI_files_get_host(NULL, addr, type, _HADDR_); - return NULL; -} - -__private_extern__ struct hostent * -LI_files_gethostent() -{ - return LI_files_get_host(NULL, NULL, AF_UNSPEC, _HENT_); -} - -__private_extern__ void -LI_files_sethostent(int stayopen) -{ -} - -__private_extern__ void -LI_files_endhostent() -{ - if (_hfp != NULL) - { - fclose(_hfp); - _hfp = NULL; - } -} diff --git a/gen.subproj/getservbyname.c b/gen.subproj/getservbyname.c deleted file mode 100644 index 6139e9e..0000000 --- a/gen.subproj/getservbyname.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -extern int _serv_stayopen; - -struct servent * -getservbyname(name, proto) - const char *name, *proto; -{ - register struct servent *p; - register char **cp; - - setservent(_serv_stayopen); - while ((p = getservent())) { - if (strcmp(name, p->s_name) == 0) - goto gotname; - for (cp = p->s_aliases; *cp; cp++) - if (strcmp(name, *cp) == 0) - goto gotname; - continue; -gotname: - if (proto == 0 || strcmp(p->s_proto, proto) == 0) - break; - } - if (!_serv_stayopen) - endservent(); - return (p); -} diff --git a/gen.subproj/getservbyport.c b/gen.subproj/getservbyport.c deleted file mode 100644 index 4af1e10..0000000 --- a/gen.subproj/getservbyport.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -extern int _serv_stayopen; - -struct servent * -getservbyport(port, proto) - int port; - const char *proto; -{ - register struct servent *p; - - setservent(_serv_stayopen); - while ((p = getservent())) { - if (p->s_port != port) - continue; - if (proto == 0 || strcmp(p->s_proto, proto) == 0) - break; - } - if (!_serv_stayopen) - endservent(); - return (p); -} diff --git a/gen.subproj/getservent.3 b/gen.subproj/getservent.3 index 79953ff..20838be 100644 --- a/gen.subproj/getservent.3 +++ b/gen.subproj/getservent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,44 +26,32 @@ .\" SUCH DAMAGE. .\" .\" From: @(#)getservent.3 8.3 (Berkeley) 1/12/94 -.\" $FreeBSD: src/lib/libc/net/getservent.3,v 1.7.2.4 2001/08/17 15:42:38 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/getservent.3,v 1.15 2007/01/09 00:28:02 imp Exp $ .\" .Dd July 9, 1995 .Dt GETSERVENT 3 .Os .Sh NAME -.Nm endservent , -.Nm getservbyname , -.Nm getservbyport , .Nm getservent , -.Nm setservent +.Nm getservbyport , +.Nm getservbyname , +.Nm setservent , +.Nm endservent .Nd get service entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS -.Fd #include -.Ft void -.Fo endservent -.Fa void -.Fc +.In netdb.h .Ft struct servent * -.Fo getservbyname -.Fa "const char *name" -.Fa "const char *proto" -.Fc +.Fn getservent .Ft struct servent * -.Fo getservbyport -.Fa "int port" -.Fa "const char *proto" -.Fc +.Fn getservbyname "const char *name" "const char *proto" .Ft struct servent * -.Fo getservent -.Fa void -.Fc +.Fn getservbyport "int port" "const char *proto" +.Ft void +.Fn setservent "int stayopen" .Ft void -.Fo setservent -.Fa "int stayopen" -.Fc +.Fn endservent void .Sh DESCRIPTION The .Fn getservent , @@ -111,7 +95,8 @@ reads the next line of the file, opening the file if necessary. The .Fn setservent function -opens and rewinds the file. If the +opens and rewinds the file. +If the .Fa stayopen flag is non-zero, the net data base will not be closed after each call to @@ -163,7 +148,7 @@ and functions appeared in .Bx 4.2 . .Sh BUGS -These functions use static data storage; +These functions use a thread-specific data storage; if the data is needed for future use, it should be copied before any subsequent calls overwrite it. Expecting port numbers to fit in a 32 bit diff --git a/gen.subproj/getservent.c b/gen.subproj/getservent.c deleted file mode 100644 index 134fb71..0000000 --- a/gen.subproj/getservent.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include -#include -#include - -#define MAXALIASES 35 - -static FILE *servf = NULL; -static struct servent serv; -static char *serv_aliases[MAXALIASES]; -int _serv_stayopen; - -void -setservent(f) - int f; -{ - if (servf == NULL) - servf = fopen(_PATH_SERVICES, "r" ); - else - rewind(servf); - _serv_stayopen |= f; -} - -void -endservent() -{ - if (servf) { - fclose(servf); - servf = NULL; - } - _serv_stayopen = 0; -} - -struct servent * -getservent() -{ - char *p; - static char *line = NULL; - register char *cp, **q; - - if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) - return (NULL); - - if (line == NULL) { - line = malloc(BUFSIZ+1); - if (line == NULL) - return (NULL); - } -again: - if ((p = fgets(line, BUFSIZ, servf)) == NULL) - return (NULL); - if (*p == '#') - goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) - goto again; - *cp = '\0'; - serv.s_name = p; - p = strpbrk(p, " \t"); - if (p == NULL) - goto again; - *p++ = '\0'; - while (*p == ' ' || *p == '\t') - p++; - cp = strpbrk(p, ",/"); - if (cp == NULL) - goto again; - *cp++ = '\0'; - serv.s_port = htons((u_short)atoi(p)); - serv.s_proto = cp; - q = serv.s_aliases = serv_aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - while (cp && *cp) { - if (*cp == ' ' || *cp == '\t') { - cp++; - continue; - } - if (q < &serv_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *q = NULL; - return (&serv); -} diff --git a/gen.subproj/if_indextoname.3 b/gen.subproj/if_indextoname.3 index 5d550f3..25b805f 100644 --- a/gen.subproj/if_indextoname.3 +++ b/gen.subproj/if_indextoname.3 @@ -1,26 +1,19 @@ -.\" Copyright (c) 1983, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. +.\" $KAME: if_indextoname.3,v 1.10 2000/11/24 08:13:51 itojun Exp $ +.\" BSDI Id: if_indextoname.3,v 2.2 2000/04/17 22:38:05 dab Exp +.\" +.\" Copyright (c) 1997, 2000 +.\" Berkeley Software Design, Inc. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. .\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -29,123 +22,131 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/net/if_indextoname.3,v 1.2.2.4 2001/08/17 15:42:38 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/if_indextoname.3,v 1.11 2005/11/23 10:49:07 ru Exp $ .\" -.Dd May 21, 1998 +.Dd November 23, 2005 .Dt IF_NAMETOINDEX 3 .Os .Sh NAME -.Nm if_freenameindex , +.Nm if_nametoindex , .Nm if_indextoname , .Nm if_nameindex , -.Nm if_nametoindex -.Nd convert interface index to name, and vice versa -.Sh LIBRARY -.Lb libc +.Nm if_freenameindex +.Nd provide mappings between interface names and indexes .Sh SYNOPSIS -.Fd #include -.Fd #include -.Fd #include -.Ft void -.Fo if_freenameindex -.Fa "struct if_nameindex *ptr" -.Fc +.In sys/types.h +.In sys/socket.h +.In net/if.h +.Ft "unsigned int" +.Fn if_nametoindex "const char *ifname" .Ft "char *" -.Fo if_indextoname -.Fa "unsigned ifindex" -.Fa "char *ifname" -.Fc +.Fn if_indextoname "unsigned int ifindex" "char *ifname" .Ft "struct if_nameindex *" -.Fo if_nameindex -.Fa void -.Fc -.Ft "unsigned int" -.Fo if_nametoindex -.Fa "const char *ifname" -.Fc +.Fn if_nameindex "void" +.Ft void +.Fn if_freenameindex "struct if_nameindex *ptr" .Sh DESCRIPTION -The functions map interface index to readable interface name -(such as -.Dq Li lo0 ) , -and vice versa. -.Pp +The .Fn if_nametoindex -converts readable interface name to interface index -.Pp positive integer value . -If the specified interface does not exist, 0 will be returned. +function maps the interface name specified in +.Fa ifname +to its corresponding index. +If the specified interface does not exist, it returns 0. .Pp -.Fn if_indextoname -converts interface index to readable interface name. The -.Fa ifname -argument must point to a buffer of at least -.Dv IF_NAMESIZE -bytes into which the interface name corresponding to the specified index is -returned. -.Dv ( IF_NAMESIZE -is also defined in -.Aq Pa net/if.h -and its value includes a terminating null byte at the end of the -interface name.) +.Fn if_indextoname +function maps the interface index specified in +.Fa ifindex +to it corresponding name, which is copied into the +buffer pointed to by +.Fa ifname , +which must be of at least +.Dv IFNAMSIZ +bytes. This pointer is also the return value of the function. -If there is no interface corresponding to the specified index, +If there is no interface corresponding to the specified +index, .Dv NULL is returned. .Pp +The .Fn if_nameindex -returns an array of -.Fa if_nameindex -structures. -.Fa if_nametoindex -is also defined in -.Aq Pa net/if.h , -and is as follows: -.Bd -literal -offset -struct if_nameindex { +function returns an array of +.Vt if_nameindex +structures, one structure per interface, as +defined in the include file +.In net/if.h . +The +.Vt if_nameindex +structure contains at least the following entries: +.Bd -literal unsigned int if_index; /* 1, 2, ... */ char *if_name; /* null terminated name: "le0", ... */ -}; .Ed .Pp -The end of the array of structures is indicated by a structure with -an -.Fa if_index +The end of the array of structures is indicated by a structure with an +.Va if_index of 0 and an -.Fa if_name +.Va if_name of .Dv NULL . -The function returns a +A .Dv NULL -pointer upon an error. -The memory used for this array of structures along with the interface -names pointed to by the -.Fa if_name -members is obtained dynamically. -This memory is freed by the -.Fn if_freenameindex -function. +pointer is returned upon an error. .Pp +The .Fn if_freenameindex -takes a pointer that was returned by -.Fn if_nameindex -as argument -.Pq Fa ptr , -and it reclaims the region allocated. -.Sh DIAGNOSTICS +function frees the dynamic memory that was +allocated by +.Fn if_nameindex . +.Sh RETURN VALUES +Upon successful completion, .Fn if_nametoindex -returns 0 on error, positive integer on success. +returns the index number of the interface. +If the interface is not found, a value of 0 is returned and +.Va errno +is set to +.Er ENXIO . +A value of 0 is also returned if an error +occurs while retrieving the list of interfaces via +.Xr getifaddrs 3 . +.Pp +Upon successful completion, .Fn if_indextoname -and +returns +.Fa ifname . +If the interface is not found, a +.Dv NULL +pointer is returned and +.Va errno +is set to +.Er ENXIO . +A +.Dv NULL +pointer is also returned if an error +occurs while retrieving the list of interfaces via +.Xr getifaddrs 3 . +.Pp +The .Fn if_nameindex -return +returns a .Dv NULL -on errors. +pointer if an error +occurs while retrieving the list of interfaces via +.Xr getifaddrs 3 , +or if sufficient memory cannot be allocated. .Sh SEE ALSO -R. Gilligan, S. Thomson, J. Bound, and W. Stevens, -``Basic Socket Interface Extensions for IPv6,'' RFC2553, March 1999. -.Sh HISTORY -The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit. +.Xr getifaddrs 3 , +.Xr networking 4 .Sh STANDARDS -These functions are defined in ``Basic Socket Interface Extensions for IPv6'' -(RFC2533). +The +.Fn if_nametoindex , +.Fn if_indextoname , +.Fn if_nameindex , +and +.Fn if_freenameindex +functions conform to +.%T "RFC 2553" . +.Sh HISTORY +The implementation first appeared in BSDi +.Bsx . diff --git a/gen.subproj/initgroups.c b/gen.subproj/initgroups.c deleted file mode 100644 index 2cce689..0000000 --- a/gen.subproj/initgroups.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)initgroups.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include - -#include -#include -#include -#include - -__private_extern__ struct passwd *LI_files_getpwnam(const char *name); - -/* this is _old_initgroups */ -int -initgroups(uname, agroup) - const char *uname; - int agroup; -{ - int groups[NGROUPS], ngroups; - struct passwd *pw; - - /* get the UID for this user */ - if ((pw = LI_files_getpwnam(uname)) == NULL) - return(-1); - - /* fetch the initial (advisory) group list */ - ngroups = NGROUPS; - getgrouplist(uname, agroup, groups, &ngroups); - if (ngroups == 0) - return(-1); - - if (syscall(SYS_initgroups, ngroups, groups, pw->pw_uid) < 0) - return (-1); - return (0); -} diff --git a/gen.subproj/ip6opt.c b/gen.subproj/ip6opt.c index c8805d1..0dd5264 100644 --- a/gen.subproj/ip6opt.c +++ b/gen.subproj/ip6opt.c @@ -110,8 +110,6 @@ inet6_option_append(cmsg, typep, multx, plusy) return(-1); if (plusy < 0 || plusy > 7) return(-1); - if (typep[0] > 255) - return(-1); /* * If this is the first option, allocate space for the diff --git a/gen.subproj/map_v4v6.c b/gen.subproj/map_v4v6.c index 66a1afc..d6123f3 100644 --- a/gen.subproj/map_v4v6.c +++ b/gen.subproj/map_v4v6.c @@ -63,15 +63,16 @@ static char rcsid[] = "$FreeBSD: src/lib/libc/net/map_v4v6.c,v 1.5.2.1 2001/03/0 #include #include #include -#include #include #include #include -#include #include #include +#include "nameser8_compat.h" +#include "resolv8_compat.h" + #define IN6ADDRSZ 16 typedef union { int32_t al; diff --git a/gen.subproj/printerdb.c b/gen.subproj/printerdb.c deleted file mode 100644 index 26bde62..0000000 --- a/gen.subproj/printerdb.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * /etc/printcap reader (in case NetInfo is not running) - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include - -static FILE *pf; -static char *getline(FILE *); -static int emptyfield(char *); - -static void -_prdb_free_ent( - prdb_ent *ent - ) -{ - int i; - - for (i = 0; ent->pe_name[i]; i++) { - free(ent->pe_name[i]); - } - free(ent->pe_name); - ent->pe_name = NULL; - for (i = 0; i < ent->pe_nprops; i++) { - free(ent->pe_prop[i].pp_key); - free(ent->pe_prop[i].pp_value); - } - free(ent->pe_prop); - ent->pe_prop = NULL; -} - -void -_old_prdb_end( - void - ) -{ - if (pf != NULL) { - fclose(pf); - pf = NULL; - } -} - -void -_old_prdb_set( - void - ) -{ - if (pf == NULL) { - pf = fopen("/etc/printcap", "r"); - } -} - -static void -pename_insert( - char ***target, - char *name, - int which - ) -{ - if (which == 0) { - *target = malloc(sizeof(char *) * 2); - } else { - *target = realloc(*target, sizeof(char *) * (which + 2)); - } - (*target)[which] = strdup(name); - (*target)[which + 1] = NULL; -} - -static void -peprop_insert( - prdb_property **target, - prdb_property prop, - int which - ) -{ - if (which == 0) { - *target = malloc(sizeof(prop)); - } else { - *target = realloc(*target, (which + 1) * sizeof(prop)); - } - (*target)[which] = prop; -} - -prdb_ent * -_old_prdb_get( - void - ) -{ - char *line; - char *p; - char *end; - char *hash; - char *equal; - char *where; - static prdb_ent ent; - prdb_property prop; - int which; - - _old_prdb_set(); - if (pf == NULL) { - return (NULL); - } - do { - line = getline(pf); - if (line == NULL) { - return (NULL); - } - } while (*line == 0); - where = line; - end = index(where, ':'); - if (end != NULL) { - *end++ = 0; - } - which = 0; - if (ent.pe_name != NULL) { - _prdb_free_ent(&ent); - } - for (;;) { - p = index(where, '|'); - if (p != NULL && (end == NULL || p < end)) { - *p++ = 0; - pename_insert(&ent.pe_name, where, which++); - where = p; - } else { - pename_insert(&ent.pe_name, where, which); - break; - } - } - where = end; - which = 0; - for (;;) { - end = index(where, ':'); - if (end != NULL) { - *end++ = 0; - } - hash = index(where, '#'); - equal = index(where, '='); - if (hash != NULL && (end == NULL || hash < end)) { - *hash = 0; - prop.pp_key = strdup(where); - *hash = '#'; - prop.pp_value = strdup(hash); - peprop_insert(&ent.pe_prop, prop, which++); - } else if (equal != NULL && (end == NULL || - equal < end)) { - *equal++ = 0; - prop.pp_key = strdup(where); - prop.pp_value = strdup(equal); - peprop_insert(&ent.pe_prop, prop, which++); - } else if (!emptyfield(where)) { - prop.pp_key = strdup(where); - prop.pp_value = strdup(""); - peprop_insert(&ent.pe_prop, prop, which++); - } - where = end; - if (end == NULL) { - break; - } - } - free(line); - ent.pe_nprops = which; - return (&ent); -} - -static int -prmatch( - prdb_ent *ent, - char *name - ) -{ - int i; - - for (i = 0; ent->pe_name[i] != NULL; i++) { - if (strcmp(ent->pe_name[i], name) == 0) { - return (1); - } - } - return (0); -} - -prdb_ent * -_old_prdb_getbyname( - char *prname - ) -{ - prdb_ent *ent; - - _old_prdb_set(); - if (pf == NULL) { - return (NULL); - } - while ((ent = _old_prdb_get())) { - if (prmatch(ent, prname)) { - break; - } - } - _old_prdb_end(); - return (ent); -} - - - -static char * -getline( - FILE *f - ) -{ - char line[BUFSIZ]; - char *res = NULL; - int more = 1; - int len; - int inclen; - - len = 0; - while (more && fgets(line, sizeof(line), f)) { - inclen = strlen(line); - if (line[inclen - 1] == '\n') { - line[inclen - 1] = 0; - inclen--; - } - if (*line == '#') { - continue; - } - if (res == NULL) { - res = malloc(inclen + 1); - } else { - res = realloc(res, len + inclen + 1); - } - if (line[inclen - 1] == '\\') { - line[inclen - 1] = 0; - inclen--; - } else { - more = 0; - } - bcopy(line, res + len, inclen); - len += inclen; - res[len] = 0; - } - return (res); -} - -static int -emptyfield( - char *line - ) -{ - while (*line) { - if (*line != ' ' && *line != '\t') { - return (0); - } - line++; - } - return (1); -} diff --git a/lookup.subproj/DSlibinfoMIG.defs b/lookup.subproj/DSlibinfoMIG.defs deleted file mode 100644 index 14ebc7e..0000000 --- a/lookup.subproj/DSlibinfoMIG.defs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header DSLookupMIG.defs - */ - -/* - * Warning! - * Do not re-order this file as it will cause MIG API number - * changes. Always add to the end of the file for new defs. - */ - -subsystem DSlibinfoMIG 50000; - -userprefix libinfoDSmig_; -serverprefix libinfoDSmig_do_; - -import ; - -#include -#include - -import ; - -type proc_name_t = c_string [* : 256]; -type inline_data_t = array [* : 16384] of char; - -routine GetProcedureNumber -( - server : mach_port_t; - name : proc_name_t; - out procno : int32_t; - ServerAuditToken bsmtoken : audit_token_t; - UserSecToken usertoken : security_token_t -); - -routine Query -( - server : mach_port_t; - proc : int32_t; - request : inline_data_t; - out reply : inline_data_t; - out ooreply : pointer_t, Dealloc; - ServerAuditToken bsmtoken : audit_token_t; - UserSecToken usertoken : security_token_t -); - -simpleroutine Query_async -( - server : mach_port_t; - replyToPort : mach_port_make_send_once_t; - proc : int32_t; - request : inline_data_t; - callbackAddr : mach_vm_address_t; - ServerAuditToken bsmtoken : audit_token_t -); diff --git a/lookup.subproj/Makefile b/lookup.subproj/Makefile index 4085a6a..f7b15bd 100644 --- a/lookup.subproj/Makefile +++ b/lookup.subproj/Makefile @@ -1,55 +1,66 @@ -# -# Generated by the NeXT 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 = lookup - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component - -HFILES = aliasdb.h bootparams.h kvbuf.h lookup_types.h lu_overrides.h\ - lu_host.h lu_utils.h netdb.h netdb_async.h printerdb.h - -CFILES = getaddrinfo.c lu_alias.c lu_bootp.c lu_bootparam.c lu_fstab.c\ - lu_group.c lu_host.c lu_host_async.c lu_netgroup.c lu_network.c\ - lu_printer.c lu_protocol.c lu_rpc.c lu_service.c lu_user.c lu_utils.c - -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ - bootparams.5 gai_strerror.3 getaddrinfo.3 getfsent.3 getgrent.3 getgrouplist.3\ - getnameinfo.3 getnetgrent.3 getpwent.3 initgroups.3\ - DSlibinfoMIG_types.h DSlibinfoMIG.defs DSlibinfoMIGAsyncReply.defs lookup.defs _lu_types.x - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -NEXTSTEP_INSTALLDIR = /Local/Developer/System -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - -PUBLIC_HEADERS = aliasdb.h bootparams.h netdb.h printerdb.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 - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies +Project = lookup +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES + +PRODUCT = $(shell tconf --product) + +HFILES = aliasdb.h bootparams.h ils.h kvbuf.h libinfo.h netdb.h netdb_async.h \ + printerdb.h si_data.h si_module.h thread_data.h + +CFILES = cache_module.c file_module.c ils.c kvbuf.c libinfo.c\ + mdns_module.c \ + search_module.c si_data.c si_getaddrinfo.c si_module.c thread_data.c + +ifeq ($(PRODUCT),MacOSX) +CFILES += ds_module.c +USERDEFS = /usr/local/include/DSlibinfoMIG.defs +SERVERDEFS = /usr/local/include/DSlibinfoMIGAsyncReply.defs +endif + +MANPAGES = bootparams.5 gai_strerror.3 getaddrinfo.3 getfsent.3 getgrent.3 \ + getgrouplist.3 getnameinfo.3 getnetgrent.3 getpwent.3 initgroups.3 + +Install_Headers = aliasdb.h bootparams.h netdb.h printerdb.h +Install_Private_Headers = ils.h kvbuf.h libinfo.h netdb_async.h si_data.h \ + si_module.h thread_data.h + +Extra_CC_Flags = -Wall -Werror -fno-common -I. \ + -I../gen.subproj \ + -D__MigTypeCheck=1 -D__DARWIN_NON_CANCELABLE=1 + +ifeq ($(PRODUCT),MacOSX) +Extra_CC_Flags += -DCONFIG_MAC -DDS_AVAILABLE -DSYNTH_ROOTFS +endif +ifeq ($(PRODUCT),AppleTV) +Extra_CC_Flags += -DCONFIG_APPLETV +endif +ifeq ($(PRODUCT),iPhone) +Extra_CC_Flags += -DCONFIG_IPHONE +endif + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +after_install: + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getaddrinfo.3" \ + "$(DSTROOT)/usr/share/man/man3/freeaddrinfo.3" + @for LINK in endfsent.3 getfsfile.3 getfsspec.3 getfstype.3 \ + setfsent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in endgrent.3 getgrgid.3 getgrgid_r.3 getgrnam.3 \ + getgrnam_r.3 setgrent.3 setgroupent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in endnetgrent.3 innetgr.3 setnetgrent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in endpwent.3 getpwnam.3 getpwnam_r.3 getpwuid.3 \ + getpwuid_r.3 setpassent.3 setpwent.3 setpwfile.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done diff --git a/lookup.subproj/Makefile.postamble b/lookup.subproj/Makefile.postamble deleted file mode 100644 index a5404b3..0000000 --- a/lookup.subproj/Makefile.postamble +++ /dev/null @@ -1,52 +0,0 @@ -%_xdr.c: %.x - $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x - -private_hdrs: $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(PRIVATE_HEADER_DIR_SUFFIX) - $(SILENT) $(FASTCP) $(PRIVATE_HDRS) $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(PRIVATE_HEADER_DIR_SUFFIX) - -$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(PRIVATE_HEADER_DIR_SUFFIX): - $(MKDIRS) $@ - -netinfo_hdrs: $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX) - $(SILENT) $(FASTCP) $(NETINFO_HDRS) $(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX) - -$(DSTROOT)$(PRIVATE_HDR_INSTALLDIR)$(NETINFO_HEADER_DIR_SUFFIX): - $(MKDIRS) $@ - -install-man-page: - mkdir -p "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 gai_strerror.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 getaddrinfo.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getaddrinfo.3" "$(DSTROOT)/usr/share/man/man3/freeaddrinfo.3" - install -c -m 644 getfsent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/endfsent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/getfsfile.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/getfsspec.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/getfstype.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getfsent.3" "$(DSTROOT)/usr/share/man/man3/setfsent.3" - install -c -m 644 getgrent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/endgrent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrgid.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrgid_r.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrnam.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/getgrnam_r.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/setgrent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getgrent.3" "$(DSTROOT)/usr/share/man/man3/setgroupent.3" - install -c -m 644 getgrouplist.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 getnameinfo.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 getnetgrent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" "$(DSTROOT)/usr/share/man/man3/endnetgrent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" "$(DSTROOT)/usr/share/man/man3/innetgr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getnetgrent.3" "$(DSTROOT)/usr/share/man/man3/setnetgrent.3" - install -c -m 644 getpwent.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/endpwent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwnam.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwnam_r.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwuid.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/getpwuid_r.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/setpassent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/setpwent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getpwent.3" "$(DSTROOT)/usr/share/man/man3/setpwfile.3" - install -c -m 644 initgroups.3 "$(DSTROOT)/usr/share/man/man3" - mkdir -p "$(DSTROOT)/usr/share/man/man5" - install -c -m 644 bootparams.5 "$(DSTROOT)/usr/share/man/man5" diff --git a/lookup.subproj/Makefile.preamble b/lookup.subproj/Makefile.preamble deleted file mode 100644 index 0300b74..0000000 --- a/lookup.subproj/Makefile.preamble +++ /dev/null @@ -1,17 +0,0 @@ -RPCFILES = _lu_types.x -OTHER_OFILES = DSlibinfoMIGUser.o DSlibinfoMIGAsyncReplyServer.o -AFTER_PREBUILD = _lu_types.h DSlibinfoMIGUser.c DSlibinfoMIGAsyncReplyServer.c -PRIVATE_HDRS = kvbuf.h netdb_async.h -NETINFO_HDRS = DSlibinfoMIG.h DSlibinfoMIGAsyncReply.h lookup.h _lu_types.h lookup_types.h lookup.defs _lu_types.x -BEFORE_INSTALLHDRS += $(SFILE_DIR) $(PRIVATE_HDRS) $(NETINFO_HDRS) -AFTER_INSTALLHDRS += private_hdrs netinfo_hdrs -PUBLIC_HEADER_DIR_SUFFIX = -PRIVATE_HEADER_DIR = /usr/local/include -PRIVATE_HEADER_DIR_SUFFIX = / -NETINFO_HEADER_DIR_SUFFIX = /netinfo -AFTER_POSTINSTALL += install-man-page -OTHER_CFLAGS += -D__MigTypeCheck=1 -D__DARWIN_NON_CANCELABLE=1 - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/lookup.subproj/PB.project b/lookup.subproj/PB.project deleted file mode 100644 index f54271c..0000000 --- a/lookup.subproj/PB.project +++ /dev/null @@ -1,61 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = ( - aliasdb.h, - bootparams.h, - kvbuf.h, - lookup_types.h, - lu_overrides.h, - lu_host.h, - lu_utils.h, - netdb.h, - netdb_async.h, - printerdb.h - ); - OTHER_LINKED = ( - getaddrinfo.c, - lu_alias.c, - lu_bootp.c, - lu_bootparam.c, - lu_fstab.c, - lu_group.c, - lu_host.c, - lu_host_async.c, - lu_netgroup.c, - lu_network.c, - lu_printer.c, - lu_protocol.c, - lu_rpc.c, - lu_service.c, - lu_user.c - ); - OTHER_SOURCES = ( - Makefile.preamble, - Makefile, - Makefile.postamble, - getaddrinfo.3, - getnameinfo.3, - lookup.defs, - _lu_types.x - ); - PRECOMPILED_HEADERS = (); - PROJECT_HEADERS = (); - PUBLIC_HEADERS = (aliasdb.h, bootparams.h, netdb.h, printerdb.h); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /bin/gnumake; - NEXTSTEP_INSTALLDIR = /Local/Developer/System; - 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 = lookup; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/lookup.subproj/_lu_types.x b/lookup.subproj/_lu_types.x deleted file mode 100644 index 0fa320e..0000000 --- a/lookup.subproj/_lu_types.x +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Lookup server protocol - Internal to NeXT - * Copyright (C) 1989 by NeXT, Inc. - * - * This server uses a protocol based upon XDR layered on top of - * a mach rpc call. There are three procedures defined in the "lookup.defs" - * file. A "lookup_link" operation takes a procedure string name and returns a - * number to be used in the other two calls. "lookup_all" takes a procedure - * number and XDR'd arguments and returns XDR'd results. It returns the - * entire list of entries. "lookup_one" has a similar calling convention, - * but returns only a single entry. - * - * The syntax of calls described here in comments looks like this: - * - * result_type procedure_name(arg_type1 arg1, arg_type2 arg2, ...) - * - * The arguments are assumed to be XDR'd in sequence and a single XDR'd - * result is returned. - */ -const _LU_MAXLUSTRLEN = 256; - -const _LU_MAXGRP = 1024; -const _LU_MAXHNAMES = 32; -const _LU_MAXADDRS = 32; -const _LU_MAXNNAMES = 32; -const _LU_MAXPNAMES = 32; -const _LU_MAXSNAMES = 32; -const _LU_MAXRNAMES = 32; -const _LU_MAXPRNAMES = 32; -const _LU_MAXPRPROPS = 1024; -const _LU_MAX_BOOTPARAMS_KV = 32; -const _LU_MAXALIASMEMBERS = 4096; - - -typedef string _lu_string<_LU_MAXLUSTRLEN>; - - -/* - * Calls available: - * int putpwpasswd(_lu_string long, _lu_string old, _lu_string new) - * _lu_passwd * getpwuid(int uid) - * _lu_passwd * getpwnam(_lu_string name) - * _lu_passwd<> getpwent(void) - */ -struct _lu_passwd { - _lu_string pw_name; - _lu_string pw_passwd; - int pw_uid; - int pw_gid; - int pw_change; - _lu_string pw_class; - _lu_string pw_gecos; - _lu_string pw_dir; - _lu_string pw_shell; - int pw_expire; -}; -typedef _lu_passwd *_lu_passwd_ptr; - - -/* - * Calls available: - * _lu_group * getgrgid(int gid) - * _lu_group * getgrnam(_lu_string name) - * _lu_group<> getgrent(void) - */ -struct _lu_group { - _lu_string gr_name; - _lu_string gr_passwd; - int gr_gid; - _lu_string gr_mem<_LU_MAXGRP>; -}; -typedef _lu_group *_lu_group_ptr; - -/* - * Calls available: - * _lu_hostent * gethostbyaddr(unsigned long addr) -- IP only - * _lu_hostent * gethostbyname(_lu_string name) - * _lu_hostent<> gethostent(void) - */ -struct _lu_hostent { - _lu_string h_names<_LU_MAXHNAMES>; - unsigned long h_addrs<_LU_MAXADDRS>; /* IP only */ -}; -typedef _lu_hostent *_lu_hostent_ptr; - -/* - * Calls available: - * _lu_netent * getnetbyaddr(unsigned long addr) --IP only - * _lu_netent * getnetbyname(_lu_string name) - * _lu_netent<> getnetent(void) - */ -struct _lu_netent { - _lu_string n_names<_LU_MAXNNAMES>; - unsigned long n_net; /* IP only */ -}; -typedef _lu_netent *_lu_netent_ptr; - - -/* - * Calls available: - * _lu_servent * getservbyport(int port, _lu_string proto) - * _lu_servent * getservbyname(_lu_string name, _lu_string proto) - * _lu_servent<> getservent(void) - */ -struct _lu_servent { - _lu_string s_names<_LU_MAXSNAMES>; - int s_port; - _lu_string s_proto; -}; -typedef _lu_servent *_lu_servent_ptr; - -/* - * Calls available: - * _lu_protoent * getprotobynumber(int number) - * _lu_protoent * getprotobyname(_lu_string name) - * _lu_protoent<> getprotoent(void) - */ -struct _lu_protoent { - _lu_string p_names<_LU_MAXPNAMES>; - int p_proto; -}; -typedef _lu_protoent *_lu_protoent_ptr; - - -/* - * Calls available: - * _lu_rpcent * getrpcbynumber(int number) - * _lu_rpcent * getrpcbyname(_lu_string name) - * _lu_rpcent<> getrpcent(void) - */ -struct _lu_rpcent { - _lu_string r_names<_LU_MAXRNAMES>; - int r_number; -}; -typedef _lu_rpcent *_lu_rpcent_ptr; - -/* - * Calls available: - * _lu_fsent<> getfsent(void) - * _lu_fsent * getfsbyname(_lu_string name) - */ -struct _lu_fsent { - _lu_string fs_spec; - _lu_string fs_file; - _lu_string fs_vfstype; - _lu_string fs_mntops; - _lu_string fs_type; - int fs_freq; - int fs_passno; -}; -typedef _lu_fsent *_lu_fsent_ptr; - -/* - * Calls available: - * _lu_prdb_ent * prdb_getbyname - * _lu_prdb_ent<> prdb_get(void) - */ -struct _lu_prdb_property { - _lu_string pp_key; - _lu_string pp_value; -}; - -struct _lu_prdb_ent { - _lu_string pe_names<_LU_MAXPRNAMES>; - _lu_prdb_property pe_props<_LU_MAXPRPROPS>; -}; -typedef _lu_prdb_ent *_lu_prdb_ent_ptr; - - -/* - * Calls available: - * _lu_bootp_ent * bootp_getbyip(unsigned long addr) - * _lu_bootp_ent * bootp_getbyether(opaque bootp_enaddr[6]) - */ -struct _lu_bootp_ent { - _lu_string bootp_name; - _lu_string bootp_bootfile; - unsigned long bootp_ipaddr; - opaque bootp_enaddr[6]; -}; -typedef _lu_bootp_ent *_lu_bootp_ent_ptr; - -/* - * Calls available: - * _lu_bootparams_ent * bootparams_getbyname(_lu_string name) - * _lu_bootparams_ent<> bootparams_getent(void) - */ -struct _lu_bootparams_ent { - _lu_string bootparams_name; - _lu_string bootparams_keyvalues<_LU_MAX_BOOTPARAMS_KV>; -}; -typedef _lu_bootparams_ent *_lu_bootparams_ent_ptr; - - -/* - * Calls available: - * _lu_aliasent * alias_getbyname(_lu_string name) - * _lu_aliasent<> alias_getent(void) - */ -struct _lu_aliasent { - _lu_string alias_name; - _lu_string alias_members<_LU_MAXALIASMEMBERS>; - int alias_local; -}; -typedef _lu_aliasent *_lu_aliasent_ptr; - -/* - * Calls available: - * int innetgr(_lu_innetgr_args args) - * _lu_netgrent<> getnetgrent(_lu_string group) - */ -struct _lu_innetgr_args { - _lu_string group; - _lu_string *host; - _lu_string *user; - _lu_string *domain; -}; - -struct _lu_netgrent{ - _lu_string ng_host; - _lu_string ng_user; - _lu_string ng_domain; -}; - diff --git a/lookup.subproj/cache_module.c b/lookup.subproj/cache_module.c new file mode 100644 index 0000000..8423f62 --- /dev/null +++ b/lookup.subproj/cache_module.c @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* GLOBAL */ +uint32_t gL1CacheEnabled = 1; + +#define CACHE_COUNT CATEGORY_COUNT +#define CACHE_MAX 20 + +typedef struct +{ + /* XXX should be mutex */ + OSSpinLock lock; + int head; + si_item_t *item[CACHE_MAX]; + si_list_t *list; +} cache_store_t; + +typedef struct +{ + cache_store_t cache_store[CACHE_COUNT]; +} cache_si_private_t; + +static void * +cache_validate_item(cache_si_private_t *pp, int cat, int where) +{ + si_item_t *item; + + item = pp->cache_store[cat].item[where]; + if (item == NULL) return NULL; + + if (si_item_is_valid(item)) return si_item_retain(item); + + si_item_release(item); + pp->cache_store[cat].item[where] = NULL; + + return NULL; +} + +static void * +cache_validate_list(cache_si_private_t *pp, int cat) +{ + uint32_t i, valid; + si_item_t *item, *last; + si_list_t *list; + + list = pp->cache_store[cat].list; + + if (list == NULL) return NULL; + if (list->count == 0) return NULL; + + last = list->entry[0]; + valid = si_item_is_valid(last); + + for (i = 1; (i < list->count) && (valid == 1); i++) + { + item = list->entry[i]; + if ((item->src == last->src) && (item->type == last->type) && (item->validation_a == last->validation_a) && (item->validation_b == last->validation_b)) continue; + + last = item; + valid = si_item_is_valid(last); + } + + if (valid) return si_list_retain(list); + + si_list_release(list); + pp->cache_store[cat].list = NULL; + + return NULL; +} + +static si_item_t * +cache_fetch_item(si_mod_t *si, int cat, const char *name, uint32_t num, int which) +{ + int i; + cache_si_private_t *pp; + si_item_t *item; + + if (si == NULL) return NULL; + if (gL1CacheEnabled == 0) return NULL; + + pp = (cache_si_private_t *)si->private; + if (pp == NULL) return NULL; + + OSSpinLockLock(&(pp->cache_store[cat].lock)); + + for (i = 0; i < CACHE_MAX; i++) + { + item = cache_validate_item(pp, cat, i); + if (item && si_item_match(item, cat, name, num, which)) + { + break; + } + else + { + si_item_release(item); + item = NULL; + } + } + + OSSpinLockUnlock(&(pp->cache_store[cat].lock)); + + return item; +} + +static si_list_t * +cache_fetch_list(si_mod_t *si, int cat) +{ + cache_si_private_t *pp; + si_list_t *list; + + if (si == NULL) return NULL; + if (gL1CacheEnabled == 0) return NULL; + + pp = (cache_si_private_t *)si->private; + if (pp == NULL) return NULL; + + OSSpinLockLock(&(pp->cache_store[cat].lock)); + list = cache_validate_list(pp, cat); + OSSpinLockUnlock(&(pp->cache_store[cat].lock)); + + return list; +} + +__private_extern__ si_item_t * +cache_user_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_USER, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_user_byuid(si_mod_t *si, uid_t uid) +{ + return cache_fetch_item(si, CATEGORY_USER, NULL, uid, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_user_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_USER); +} + +__private_extern__ si_item_t * +cache_group_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_GROUP, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_group_bygid(si_mod_t *si, gid_t gid) +{ + return cache_fetch_item(si, CATEGORY_GROUP, NULL, gid, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_group_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_GROUP); +} + +__private_extern__ si_item_t * +cache_grouplist(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_GROUPLIST, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_alias_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_ALIAS, name, 0, SEL_NAME); +} + +__private_extern__ si_list_t * +cache_alias_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_ALIAS); +} + +__private_extern__ si_item_t * +cache_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + si_item_t *item; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + item = NULL; + + if (af == AF_INET) item = cache_fetch_item(si, CATEGORY_HOST_IPV4, name, af, SEL_NAME); + else item = cache_fetch_item(si, CATEGORY_HOST_IPV6, name, af, SEL_NAME); + + if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + + return item; +} + +__private_extern__ si_item_t * +cache_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + si_item_t *item; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + item = NULL; + + if (af == AF_INET) item = cache_fetch_item(si, CATEGORY_HOST_IPV4, addr, af, SEL_NUMBER); + else item = cache_fetch_item(si, CATEGORY_HOST_IPV6, addr, af, SEL_NUMBER); + + if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + + return item; +} + +__private_extern__ si_list_t * +cache_host_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_HOST); +} + +__private_extern__ si_item_t * +cache_network_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_NETWORK, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_network_byaddr(si_mod_t *si, uint32_t addr) +{ + return cache_fetch_item(si, CATEGORY_NETWORK, NULL, addr, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_network_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_NETWORK); +} + +__private_extern__ si_item_t * +cache_service_byname(si_mod_t *si, const char *name, const char *proto) +{ + uint32_t pn; + + if (name == NULL) return NULL; + if (proto == NULL) return cache_fetch_item(si, CATEGORY_SERVICE, name, 0, SEL_NAME); + + pn = 1; + if (string_equal(proto, "tcp")) pn = 2; + + return cache_fetch_item(si, CATEGORY_SERVICE, name, pn, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_service_byport(si_mod_t *si, int port, const char *proto) +{ + return cache_fetch_item(si, CATEGORY_SERVICE, proto, port, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_service_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_SERVICE); +} + +__private_extern__ si_item_t * +cache_protocol_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_PROTOCOL, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_protocol_bynumber(si_mod_t *si, int number) +{ + return cache_fetch_item(si, CATEGORY_PROTOCOL, NULL, number, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_protocol_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_PROTOCOL); +} + +__private_extern__ si_item_t * +cache_rpc_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_RPC, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_rpc_bynumber(si_mod_t *si, int number) +{ + return cache_fetch_item(si, CATEGORY_RPC, NULL, number, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_rpc_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_RPC); +} + +__private_extern__ si_item_t * +cache_fs_byspec(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_FS, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_fs_byfile(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_FS, name, 0, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_fs_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_FS); +} + +__private_extern__ si_item_t * +cache_mac_byname(si_mod_t *si, const char *name) +{ + return cache_fetch_item(si, CATEGORY_MAC, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +cache_mac_bymac(si_mod_t *si, const char *mac) +{ + return cache_fetch_item(si, CATEGORY_MAC, mac, 0, SEL_NUMBER); +} + +__private_extern__ si_list_t * +cache_mac_all(si_mod_t *si) +{ + return cache_fetch_list(si, CATEGORY_MAC); +} + +__private_extern__ si_item_t * +cache_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, uint32_t *err) +{ + /* + * Caching of getnameinfo(3) is not supported. + * Only the individual host_byaddr and serv_byaddr responses will be cached. + * This is because getnameinfo(3) returns numeric responses instead of + * failing, which would poison the cache. + */ + if (err) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; +} + +__private_extern__ void +cache_close(si_mod_t *si) +{ + cache_si_private_t *pp; + int i, j; + + if (si == NULL) return; + + pp = (cache_si_private_t *)si->private; + if (pp == NULL) return; + + for (i = 0; i < CACHE_COUNT; i++) + { + si_list_release(pp->cache_store[i].list); + + for (j = 0; j < CACHE_MAX; j++) + { + si_item_release(pp->cache_store[i].item[j]); + pp->cache_store[i].item[j] = NULL; + } + } + + free(si->private); +} + +__private_extern__ si_mod_t * +si_module_static_cache() +{ + si_mod_t *out; + char *outname; + cache_si_private_t *pp; + + out = (si_mod_t *)calloc(1, sizeof(si_mod_t)); + outname = strdup("cache"); + pp = (cache_si_private_t *)calloc(1, sizeof(cache_si_private_t)); + + if ((out == NULL) || (outname == NULL) || (pp == NULL)) + { + if (out != NULL) free(out); + if (outname != NULL) free(outname); + if (pp != NULL) free(pp); + + errno = ENOMEM; + return NULL; + } + + out->name = outname; + out->vers = 1; + out->refcount = 1; + out->private = pp; + + out->sim_close = cache_close; + + out->sim_user_byname = cache_user_byname; + out->sim_user_byuid = cache_user_byuid; + out->sim_user_all = cache_user_all; + + out->sim_group_byname = cache_group_byname; + out->sim_group_bygid = cache_group_bygid; + out->sim_group_all = cache_group_all; + + out->sim_grouplist = cache_grouplist; + + /* no netgroup support */ + out->sim_netgroup_byname = NULL; + out->sim_in_netgroup = NULL; + + out->sim_alias_byname = cache_alias_byname; + out->sim_alias_all = cache_alias_all; + + out->sim_host_byname = cache_host_byname; + out->sim_host_byaddr = cache_host_byaddr; + out->sim_host_all = cache_host_all; + + out->sim_network_byname = cache_network_byname; + out->sim_network_byaddr = cache_network_byaddr; + out->sim_network_all = cache_network_all; + + out->sim_service_byname = cache_service_byname; + out->sim_service_byport = cache_service_byport; + out->sim_service_all = cache_service_all; + + out->sim_protocol_byname = cache_protocol_byname; + out->sim_protocol_bynumber = cache_protocol_bynumber; + out->sim_protocol_all = cache_protocol_all; + + out->sim_rpc_byname = cache_rpc_byname; + out->sim_rpc_bynumber = cache_rpc_bynumber; + out->sim_rpc_all = cache_rpc_all; + + out->sim_fs_byspec = cache_fs_byspec; + out->sim_fs_byfile = cache_fs_byfile; + out->sim_fs_all = cache_fs_all; + + out->sim_mac_byname = cache_mac_byname; + out->sim_mac_bymac = cache_mac_bymac; + out->sim_mac_all = cache_mac_all; + + /* no addrinfo support */ + out->sim_wants_addrinfo = NULL; + out->sim_addrinfo = NULL; + + /* no nameinfo support */ + out->sim_nameinfo = cache_nameinfo; + + return out; +} + +__private_extern__ void +si_cache_add_item(si_mod_t *si, si_mod_t *src, si_item_t *item) +{ + cache_si_private_t *pp; + int head, cat; + + if (si == NULL) return; + if (src == NULL) return; + if (item == NULL) return; + + if (si == src) return; + + if (src->name == NULL) return; + if (string_equal(src->name, "cache")) return; + + cat = item->type; + if ((cat < 0) || (cat >= CACHE_COUNT)) return; + + pp = (cache_si_private_t *)si->private; + if (pp == NULL) return; + + OSSpinLockLock(&(pp->cache_store[cat].lock)); + + head = pp->cache_store[item->type].head; + + si_item_release(pp->cache_store[item->type].item[head]); + pp->cache_store[item->type].item[head] = si_item_retain(item); + + head++; + if (head >= CACHE_MAX) head = 0; + pp->cache_store[item->type].head = head; + + OSSpinLockUnlock(&(pp->cache_store[cat].lock)); +} + +__private_extern__ void +si_cache_add_list(si_mod_t *si, si_mod_t *src, si_list_t *list) +{ + cache_si_private_t *pp; + si_item_t *item; + int cat; + + if (si == NULL) return; + if (src == NULL) return; + if (list == NULL) return; + if (list->count == 0) return; + + if (si == src) return; + + if (src->name == NULL) return; + if (string_equal(src->name, "cache")) return; + + item = list->entry[0]; + if (item == NULL) return; + + cat = item->type; + if ((cat < 0) || (cat >= CACHE_COUNT)) return; + + pp = (cache_si_private_t *)si->private; + if (pp == NULL) return; + + OSSpinLockLock(&(pp->cache_store[cat].lock)); + + si_list_release(pp->cache_store[item->type].list); + pp->cache_store[item->type].list = si_list_retain(list); + + OSSpinLockUnlock(&(pp->cache_store[cat].lock)); +} diff --git a/lookup.subproj/ds_module.c b/lookup.subproj/ds_module.c new file mode 100644 index 0000000..b5496b0 --- /dev/null +++ b/lookup.subproj/ds_module.c @@ -0,0 +1,2332 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This ds contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this ds except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * ds. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#define SOCK_UNSPEC 0 +#define IPPROTO_UNSPEC 0 + +#define IPV6_ADDR_LEN 16 +#define IPV4_ADDR_LEN 4 + +#define WANT_NOTHING 0 +#define WANT_A4_ONLY 1 +#define WANT_A6_ONLY 2 +#define WANT_A6_PLUS_MAPPED_A4 3 +#define WANT_MAPPED_A4_ONLY 4 + +/* ONLY TO BE USED BY getipv6nodebyaddr */ +#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 5 + +#define DS_NOTIFICATION_KEY_GLOBAL "com.apple.system.DirectoryService.InvalidateCache" +#define DS_NOTIFICATION_KEY_USER "com.apple.system.DirectoryService.InvalidateCache.user" +#define DS_NOTIFICATION_KEY_GROUP "com.apple.system.DirectoryService.InvalidateCache.group" +#define DS_NOTIFICATION_KEY_HOST "com.apple.system.DirectoryService.InvalidateCache.host" +#define DS_NOTIFICATION_KEY_SERVICE "com.apple.system.DirectoryService.InvalidateCache.service" + +#define MAX_LOOKUP_ATTEMPTS 10 + +#define INET_NTOP_AF_INET_OFFSET 4 +#define INET_NTOP_AF_INET6_OFFSET 8 + +extern mach_port_t _ds_port; +extern int _ds_running(); +extern uint32_t gL1CacheEnabled; + +static pthread_key_t _ds_serv_cache_key = 0; + +static void +_ds_serv_cache_free(void *x) +{ + if (x != NULL) si_item_release(x); +} + +__private_extern__ kern_return_t +libinfoDSmig_do_Response_async(mach_port_t server, char *reply, mach_msg_type_number_t replyCnt, vm_offset_t ooreply, mach_msg_type_number_t ooreplyCnt, mach_vm_address_t callbackAddr, security_token_t servertoken) +{ + return KERN_SUCCESS; +} + +__private_extern__ kern_return_t +LI_DSLookupGetProcedureNumber(const char *name, int32_t *procno) +{ + kern_return_t status; + security_token_t token; + uint32_t n, len; + + if (name == NULL) return KERN_FAILURE; + + len = strlen(name) + 1; + if (len == 1) return KERN_FAILURE; + + token.val[0] = -1; + token.val[1] = -1; + + if (_ds_running() == 0) return KERN_FAILURE; + if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; + + status = MIG_SERVER_DIED; + for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) + { + status = libinfoDSmig_GetProcedureNumber(_ds_port, (char *)name, procno, &token); + + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port); + if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL; + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s status %u", name, status); +#endif + return status; + } + + if (token.val[0] != 0) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s auth failure uid=%d", name, token.val[0]); +#endif + return KERN_FAILURE; + } + +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s = %d", name, *procno); +#endif + return status; +} + +__private_extern__ kern_return_t +LI_DSLookupQuery(int32_t procno, kvbuf_t *request, kvarray_t **reply) +{ + kern_return_t status; + security_token_t token; + uint32_t n; + mach_msg_type_number_t illen, oolen; + char ilbuf[MAX_MIG_INLINE_DATA]; + vm_offset_t oobuf; + kvbuf_t *out; + + if (reply == NULL) return KERN_FAILURE; + if ((request != NULL) && ((request->databuf == NULL) || (request->datalen == 0))) return KERN_FAILURE; + + token.val[0] = -1; + token.val[1] = -1; + *reply = NULL; + + if (_ds_running() == 0) return KERN_FAILURE; + if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; + + status = MIG_SERVER_DIED; + for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) + { + illen = 0; + oolen = 0; + oobuf = 0; + + if (request != NULL) + { + status = libinfoDSmig_Query(_ds_port, procno, request->databuf, request->datalen, ilbuf, &illen, &oobuf, &oolen, &token); + } + else + { + status = libinfoDSmig_Query(_ds_port, procno, "", 0, ilbuf, &illen, &oobuf, &oolen, &token); + } + + if (status == MACH_SEND_INVALID_DEST) + { + mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); + status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port); + if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL; + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status %u", procno, status); +#endif + return status; + } + + if (token.val[0] != 0) + { +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d auth failure uid=%d", procno, token.val[0]); +#endif + if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + return KERN_FAILURE; + } + + out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (out == NULL) + { + if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + return KERN_FAILURE; + } + + if (oolen > 0) + { + out->datalen = oolen; + out->databuf = malloc(oolen); + if (out->databuf == NULL) + { + free(out); + *reply = NULL; + vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + return KERN_FAILURE; + } + + memcpy(out->databuf, (char *)oobuf, oolen); + vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); + } + else if (illen > 0) + { + out->datalen = illen; + out->databuf = malloc(illen); + if (out->databuf == NULL) + { + free(out); + *reply = NULL; + return KERN_FAILURE; + } + + memcpy(out->databuf, ilbuf, illen); + } + + *reply = kvbuf_decode(out); + if (*reply == NULL) + { + /* DS returned no data */ + free(out->databuf); + free(out); + } + +#ifdef DEBUG + asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status OK", procno); +#endif + return status; +} + +/* notify SPI */ +uint32_t notify_peek(int token, uint32_t *val); + +typedef struct +{ + int notify_token_global; + int notify_token_user; + int notify_token_group; + int notify_token_host; + int notify_token_service; +} ds_si_private_t; + +static uid_t +audit_token_uid(audit_token_t a) +{ + /* + * This should really call audit_token_to_au32, + * but that's in libbsm, not in a Libsystem library. + */ + return (uid_t)a.val[1]; +} + +static void +ds_get_validation(si_mod_t *si, uint64_t *a, uint64_t *b, int cat) +{ + ds_si_private_t *pp; + uint32_t peek; + int status; + + if (si == NULL) return; + + pp = (ds_si_private_t *)si->private; + if (pp == NULL) return; + + if (a != NULL) + { + *a = 0; + status = notify_peek(pp->notify_token_global, &peek); + if (status == NOTIFY_STATUS_OK) *a = ntohl(peek); + } + + if (b != NULL) + { + *b = 0; + peek = 0; + status = NOTIFY_STATUS_FAILED; + + if (cat == CATEGORY_USER) status = notify_peek(pp->notify_token_user, &peek); + else if (cat == CATEGORY_GROUP) status = notify_peek(pp->notify_token_group, &peek); + else if (cat == CATEGORY_GROUPLIST) status = notify_peek(pp->notify_token_group, &peek); + else if (cat == CATEGORY_HOST_IPV4) status = notify_peek(pp->notify_token_host, &peek); + else if (cat == CATEGORY_HOST_IPV6) status = notify_peek(pp->notify_token_host, &peek); + else if (cat == CATEGORY_SERVICE) status = notify_peek(pp->notify_token_service, &peek); + + if (status == NOTIFY_STATUS_OK) *b = ntohl(peek); + } +} + +static si_list_t * +ds_list(si_mod_t *si, int cat, const char *procname, int *procnum, void *extra, si_item_t *(*extract)(si_mod_t *, kvarray_t *, void *, uint64_t, uint64_t), kvbuf_t *request) +{ + si_item_t *item; + si_list_t *list; + kvarray_t *reply; + kern_return_t status; + uint64_t va, vb; + + if (*procnum < 0) + { + status = LI_DSLookupGetProcedureNumber(procname, procnum); + if (status != KERN_SUCCESS) return NULL; + } + + reply = NULL; + ds_get_validation(si, &va, &vb, cat); + status = LI_DSLookupQuery(*procnum, request, &reply); + + if ((status != KERN_SUCCESS) || (reply == NULL)) return NULL; + + list = NULL; + while (reply->curr < reply->count) + { + item = extract(si, reply, extra, va, vb); + list = si_list_add(list, item); + si_item_release(item); + } + + kvarray_free(reply); + + return list; +} + +static si_item_t * +ds_item(si_mod_t *si, int cat, const char *procname, int *procnum, void *extra, si_item_t *(*extract)(si_mod_t *, kvarray_t *, void *, uint64_t, uint64_t), kvbuf_t *request) +{ + si_item_t *item; + kvarray_t *reply; + kern_return_t status; + uint64_t va, vb; + + if (*procnum < 0) + { + status = LI_DSLookupGetProcedureNumber(procname, procnum); + if (status != KERN_SUCCESS) return NULL; + } + + reply = NULL; + ds_get_validation(si, &va, &vb, cat); + status = LI_DSLookupQuery(*procnum, request, &reply); + + if ((status != KERN_SUCCESS) || (reply == NULL)) return NULL; + + item = extract(si, reply, extra, va, vb); + kvarray_free(reply); + + return item; +} + +/* + * Extract the next user entry from a kvarray. + */ +static si_item_t * +extract_user(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct passwd tmp; + uint32_t d, k, kcount; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + memset(&tmp, 0, sizeof(struct passwd)); + + tmp.pw_uid = -2; + tmp.pw_gid = -2; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "pw_name")) + { + if (tmp.pw_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "pw_passwd")) + { + if (tmp.pw_passwd != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_passwd = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "pw_uid")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_uid = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "pw_gid")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_gid = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "pw_change")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_change = atol(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "pw_expire")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.pw_expire = atol(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "pw_class")) + { + if (tmp.pw_class != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_class = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "pw_gecos")) + { + if (tmp.pw_gecos != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_gecos = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "pw_dir")) + { + if (tmp.pw_dir != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_dir = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "pw_shell")) + { + if (tmp.pw_shell != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.pw_shell = (char *)in->dict[d].val[k][0]; + } + } + + if (tmp.pw_name == NULL) tmp.pw_name = ""; + if (tmp.pw_passwd == NULL) tmp.pw_passwd = ""; + if (tmp.pw_class == NULL) tmp.pw_class = ""; + if (tmp.pw_gecos == NULL) tmp.pw_gecos = ""; + if (tmp.pw_dir == NULL) tmp.pw_dir = ""; + if (tmp.pw_shell == NULL) tmp.pw_shell = ""; + + return (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, valid_global, valid_cat, tmp.pw_name, tmp.pw_passwd, tmp.pw_uid, tmp.pw_gid, tmp.pw_change, tmp.pw_class, tmp.pw_gecos, tmp.pw_dir, tmp.pw_shell, tmp.pw_expire); +} + +static si_item_t * +extract_group(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct group tmp; + char *empty[1]; + uint32_t d, k, kcount; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct group)); + + tmp.gr_gid = -2; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "gr_name")) + { + if (tmp.gr_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.gr_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "gr_passwd")) + { + if (tmp.gr_passwd != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.gr_passwd = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "gr_gid")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.gr_gid = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "gr_mem")) + { + if (tmp.gr_mem != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.gr_mem = (char **)in->dict[d].val[k]; + } + } + + if (tmp.gr_name == NULL) tmp.gr_name = ""; + if (tmp.gr_passwd == NULL) tmp.gr_passwd = ""; + if (tmp.gr_mem == NULL) tmp.gr_mem = empty; + + return (si_item_t *)LI_ils_create("L4488ss4*", (unsigned long)si, CATEGORY_GROUP, 1, valid_global, valid_cat, tmp.gr_name, tmp.gr_passwd, tmp.gr_gid, tmp.gr_mem); +} + +static void +_free_addr_list(char **l) +{ + int i; + + if (l == NULL) return; + for (i = 0; l[i] != NULL; i++) free(l[i]); + free(l); +} + +/* map ipv4 addresses and append to v6 list */ +static int +_map_v4(char ***v6, uint32_t n6, char **v4, uint32_t n4) +{ + struct in6_addr a6; + uint32_t i; + + a6.__u6_addr.__u6_addr32[0] = 0x00000000; + a6.__u6_addr.__u6_addr32[1] = 0x00000000; + a6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); + + if (*v6 == NULL) + { + *v6 = (char **)calloc(n4 + 1, sizeof(char *)); + } + else + { + *v6 = (char **)reallocf(*v6, (n6 + n4 + 1) * sizeof(char *)); + } + + if (*v6 == NULL) return -1; + + for (i = 0; i < n4; i++) + { + (*v6)[n6] = (char *)calloc(1, IPV6_ADDR_LEN); + if ((*v6)[n6] == NULL) return -1; + + memcpy(&(a6.__u6_addr.__u6_addr32[3]), v4[i], IPV4_ADDR_LEN); + memcpy((*v6)[n6], &(a6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN); + + n6++; + } + + return 0; +} + +static si_item_t * +extract_netgroup(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + const char *host, *user, *domain; + uint32_t d, k, kcount; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + kcount = in->dict[d].kcount; + + host = NULL; + user = NULL; + domain = NULL; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "host")) + { + if (host != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + host = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "user")) + { + if (user != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + user = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "domain")) + { + if (domain != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + domain = (char *)in->dict[d].val[k][0]; + } + } + + if (host == NULL) host = ""; + if (user == NULL) user = ""; + if (domain == NULL) domain = ""; + + return (si_item_t *)LI_ils_create("L4488sss", (unsigned long)si, CATEGORY_ALIAS, 1, valid_global, valid_cat, host, user, domain); +} + +static si_item_t * +extract_alias(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct aliasent tmp; + char *empty[1]; + uint32_t d, k, kcount; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct group)); + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "alias_name")) + { + if (tmp.alias_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.alias_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "alias_members")) + { + if (tmp.alias_members != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.alias_members_len = in->dict[d].vcount[k]; + tmp.alias_members = (char **)in->dict[d].val[k]; + } + else if (string_equal(in->dict[d].key[k], "alias_local")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.alias_local = atoi(in->dict[d].val[k][0]); + } + } + + return (si_item_t *)LI_ils_create("L4488s4*4", (unsigned long)si, CATEGORY_ALIAS, 1, valid_global, valid_cat, tmp.alias_name, tmp.alias_members_len, tmp.alias_members, tmp.alias_local); +} + +static si_item_t * +extract_host(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat) +{ + struct hostent tmp; + si_item_t *out; + uint32_t i, d, k, kcount, vcount, v4count, v6count, want; + int status, addr_len; + int family, addr_count; + struct in_addr a4; + struct in6_addr a6; + char **v4addrs, **v6addrs; + char *empty[1]; + + v4addrs = NULL; + v6addrs = NULL; + v4count = 0; + v6count = 0; + addr_count = 0; + addr_len = sizeof(void *); + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct hostent)); + + family = AF_INET; + tmp.h_length = IPV4_ADDR_LEN; + + want = WANT_A4_ONLY; + if (extra != NULL) want = *(uint32_t *)extra; + + if (want != WANT_A4_ONLY) + { + family = AF_INET6; + tmp.h_length = IPV6_ADDR_LEN; + } + + tmp.h_addrtype = family; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "h_name")) + { + if (tmp.h_name != NULL) continue; + + vcount = in->dict[d].vcount[k]; + if (vcount == 0) continue; + + tmp.h_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "h_aliases")) + { + if (tmp.h_aliases != NULL) continue; + + vcount = in->dict[d].vcount[k]; + if (vcount == 0) continue; + + tmp.h_aliases = (char **)in->dict[d].val[k]; + } + else if (string_equal(in->dict[d].key[k], "h_ipv4_addr_list")) + { + if (v4addrs != NULL) continue; + + v4count = in->dict[d].vcount[k]; + if (v4count == 0) continue; + + v4addrs = (char **)calloc(v4count + 1, sizeof(char *)); + if (v4addrs == NULL) + { + _free_addr_list(v6addrs); + return NULL; + } + + for (i = 0; i < v4count; i++) + { + v4addrs[i] = calloc(1, IPV4_ADDR_LEN); + if (v4addrs[i] == NULL) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memset(&a4, 0, sizeof(struct in_addr)); + status = inet_pton(AF_INET, in->dict[d].val[k][i], &a4); + if (status != 1) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memcpy(v4addrs[i], &a4, IPV4_ADDR_LEN); + } + } + else if (string_equal(in->dict[d].key[k], "h_ipv6_addr_list")) + { + if (v6addrs != NULL) continue; + + v6count = in->dict[d].vcount[k]; + if (v6count == 0) continue; + + v6addrs = (char **)calloc(v6count + 1, sizeof(char *)); + if (v6addrs == NULL) + { + _free_addr_list(v4addrs); + return NULL; + } + + for (i = 0; i < v6count; i++) + { + v6addrs[i] = calloc(1, IPV6_ADDR_LEN); + if (v6addrs[i] == NULL) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memset(&a6, 0, sizeof(struct in6_addr)); + status = inet_pton(AF_INET6, in->dict[d].val[k][i], &a6); + if (status != 1) + { + _free_addr_list(v4addrs); + _free_addr_list(v6addrs); + return NULL; + } + + memcpy(v6addrs[i], &(a6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN); + } + } + } + + if (tmp.h_name == NULL) tmp.h_name = ""; + if (tmp.h_aliases == NULL) tmp.h_aliases = empty; + + if (want == WANT_A4_ONLY) + { + _free_addr_list(v6addrs); + if (v4addrs == NULL) return NULL; + + tmp.h_addr_list = v4addrs; + out = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, valid_global, valid_cat, tmp.h_name, tmp.h_aliases, tmp.h_addrtype, tmp.h_length, tmp.h_addr_list); + _free_addr_list(v4addrs); + return out; + } + else if ((want == WANT_A6_ONLY) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (v6count > 0))) + { + _free_addr_list(v4addrs); + if (v6addrs == NULL) return NULL; + + tmp.h_addr_list = v6addrs; + out = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, valid_global, valid_cat, tmp.h_name, tmp.h_aliases, tmp.h_addrtype, tmp.h_length, tmp.h_addr_list); + _free_addr_list(v6addrs); + return out; + } + + /* + * At this point, want is WANT_A6_PLUS_MAPPED_A4, WANT_MAPPED_A4_ONLY, + * or WANT_A6_OR_MAPPED_A4_IF_NO_A6. In the last case, there are no ipv6 + * addresses, so that case degenerates into WANT_MAPPED_A4_ONLY. + */ + if (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) want = WANT_MAPPED_A4_ONLY; + + if (want == WANT_MAPPED_A4_ONLY) + { + _free_addr_list(v6addrs); + v6addrs = NULL; + v6count = 0; + } + + status = _map_v4(&v6addrs, v6count, v4addrs, v4count); + _free_addr_list(v4addrs); + if (status != 0) + { + _free_addr_list(v6addrs); + return NULL; + } + + if (v6addrs == NULL) return NULL; + + tmp.h_addr_list = v6addrs; + out = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, valid_global, valid_cat, tmp.h_name, tmp.h_aliases, tmp.h_addrtype, tmp.h_length, tmp.h_addr_list); + _free_addr_list(v6addrs); + return out; +} + +static si_item_t * +extract_network(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct netent tmp; + uint32_t d, k, kcount; + char *empty[1]; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct netent)); + + tmp.n_addrtype = AF_INET; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "n_name")) + { + if (tmp.n_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.n_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "n_net")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.n_net = inet_network(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "n_addrtype")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.n_addrtype = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "n_aliases")) + { + if (tmp.n_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.n_aliases = (char **)in->dict[d].val[k]; + } + } + + if (tmp.n_name == NULL) tmp.n_name = ""; + if (tmp.n_aliases == NULL) tmp.n_aliases = empty; + + return (si_item_t *)LI_ils_create("L4488s*44", (unsigned long)si, CATEGORY_NETWORK, 1, valid_global, valid_cat, tmp.n_name, tmp.n_aliases, tmp.n_addrtype, tmp.n_net); +} + +static si_item_t * +extract_service(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct servent tmp; + char *empty[1]; + uint32_t d, k, kcount; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct servent)); + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "s_name")) + { + if (tmp.s_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.s_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "s_aliases")) + { + if (tmp.s_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.s_aliases = (char **)in->dict[d].val[k]; + } + else if (string_equal(in->dict[d].key[k], "s_port")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.s_port = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "s_proto")) + { + if (tmp.s_proto != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.s_proto = (char *)in->dict[d].val[k][0]; + } + } + + if (tmp.s_name == NULL) tmp.s_name = ""; + if (tmp.s_proto == NULL) tmp.s_proto = ""; + if (tmp.s_aliases == NULL) tmp.s_aliases = empty; + + /* strange but correct */ + tmp.s_port = htons(tmp.s_port); + + return (si_item_t *)LI_ils_create("L4488s*4s", (unsigned long)si, CATEGORY_SERVICE, 1, valid_global, valid_cat, tmp.s_name, tmp.s_aliases, tmp.s_port, tmp.s_proto); +} + +static si_item_t * +extract_protocol(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct protoent tmp; + uint32_t d, k, kcount; + char *empty[1]; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct protoent)); + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "p_name")) + { + if (tmp.p_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.p_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "p_proto")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.p_proto = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "p_aliases")) + { + if (tmp.p_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.p_aliases = (char **)in->dict[d].val[k]; + } + } + + if (tmp.p_name == NULL) tmp.p_name = ""; + if (tmp.p_aliases == NULL) tmp.p_aliases = empty; + + return (si_item_t *)LI_ils_create("L4488s*4", (unsigned long)si, CATEGORY_PROTOCOL, 1, valid_global, valid_cat, tmp.p_name, tmp.p_aliases, tmp.p_proto); +} + +static si_item_t * +extract_rpc(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat) +{ + struct rpcent tmp; + uint32_t d, k, kcount; + char *empty[1]; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + empty[0] = NULL; + memset(&tmp, 0, sizeof(struct rpcent)); + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "r_name")) + { + if (tmp.r_name != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.r_name = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "r_number")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.r_number = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "r_aliases")) + { + if (tmp.r_aliases != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.r_aliases = (char **)in->dict[d].val[k]; + } + } + + if (tmp.r_name == NULL) tmp.r_name = ""; + if (tmp.r_aliases == NULL) tmp.r_aliases = empty; + + return (si_item_t *)LI_ils_create("L4488s*4", (unsigned long)si, CATEGORY_RPC, 1, valid_global, valid_cat, tmp.r_name, tmp.r_aliases, tmp.r_number); +} + +static si_item_t * +extract_fstab(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat) +{ + struct fstab tmp; + uint32_t d, k, kcount; + char *file; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + + file = NULL; + if (extra != NULL) file = (char *)extra; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + memset(&tmp, 0, sizeof(struct fstab)); + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "fs_spec")) + { + if (tmp.fs_spec != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_spec = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "fs_file")) + { + if (tmp.fs_file != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_file = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "fs_vfstype")) + { + if (tmp.fs_vfstype != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_vfstype = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "fs_mntops")) + { + if (tmp.fs_mntops != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_mntops = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "fs_type")) + { + if (tmp.fs_type != NULL) continue; + if (in->dict[d].vcount[k] == 0) continue; + + tmp.fs_type = (char *)in->dict[d].val[k][0]; + } + else if (string_equal(in->dict[d].key[k], "fs_freq")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.fs_freq = atoi(in->dict[d].val[k][0]); + } + else if (string_equal(in->dict[d].key[k], "fs_passno")) + { + if (in->dict[d].vcount[k] == 0) continue; + tmp.fs_passno = atoi(in->dict[d].val[k][0]); + } + } + + if (tmp.fs_spec == NULL) tmp.fs_spec = ""; + if (tmp.fs_file == NULL) tmp.fs_file = ""; + if (tmp.fs_vfstype == NULL) tmp.fs_vfstype = ""; + if (tmp.fs_mntops == NULL) tmp.fs_mntops = ""; + if (tmp.fs_type == NULL) tmp.fs_type = ""; + + if ((file != NULL) && string_not_equal(file, tmp.fs_file)) return NULL; + + return (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, valid_global, valid_cat, tmp.fs_spec, tmp.fs_file, tmp.fs_vfstype, tmp.fs_mntops, tmp.fs_type, tmp.fs_freq, tmp.fs_passno); +} + +static si_item_t * +extract_mac_mac(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat) +{ + uint32_t d, k, kcount; + char *cmac; + si_item_t *out; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + if (extra == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + kcount = in->dict[d].kcount; + + cmac = NULL; + for (k = 0; k < kcount; k++) + { + if ((cmac == NULL) && (string_equal(in->dict[d].key[k], "mac"))) + { + if (in->dict[d].vcount[k] == 0) continue; + cmac = si_canonical_mac_address(in->dict[d].val[k][0]); + if (cmac == NULL) return NULL; + } + } + + if (cmac == NULL) return NULL; + + out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, valid_global, valid_cat, extra, cmac); + free(cmac); + return out; +} + +static si_item_t * +extract_mac_name(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat) +{ + uint32_t d, k, kcount; + const char *name; + si_item_t *out; + + if (si == NULL) return NULL; + if (in == NULL) return NULL; + if (extra == NULL) return NULL; + + d = in->curr; + in->curr++; + + if (d >= in->count) return NULL; + + kcount = in->dict[d].kcount; + + name = NULL; + for (k = 0; k < kcount; k++) + { + if ((name == NULL) && (string_equal(in->dict[d].key[k], "name"))) + { + if (in->dict[d].vcount[k] == 0) continue; + name = in->dict[d].val[k][0]; + } + } + + if (name == NULL) return NULL; + + out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, valid_global, valid_cat, name, extra); + return out; +} + +__private_extern__ si_item_t * +ds_user_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("login", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_USER, "getpwnam", &proc, NULL, extract_user, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_user_byuid(si_mod_t *si, uid_t uid) +{ + static int proc = -1; + char val[16]; + kvbuf_t *request; + si_item_t *item; + + snprintf(val, sizeof(val), "%d", (int)uid); + request = kvbuf_query_key_val("uid", val); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_USER, "getpwuid", &proc, NULL, extract_user, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_user_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_USER, "getpwent", &proc, NULL, extract_user, NULL); +} + +__private_extern__ si_item_t * +ds_group_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_GROUP, "getgrnam", &proc, NULL, extract_group, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_group_bygid(si_mod_t *si, gid_t gid) +{ + static int proc = -1; + char val[16]; + kvbuf_t *request; + si_item_t *item; + + snprintf(val, sizeof(val), "%d", (int)gid); + request = kvbuf_query_key_val("gid", val); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_GROUP, "getgrgid", &proc, NULL, extract_group, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_group_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_GROUP, "getgrent", &proc, NULL, extract_group, NULL); +} + +__private_extern__ si_item_t * +ds_grouplist(si_mod_t *si, const char *name) +{ + struct passwd *pw; + kern_return_t kstatus; + uint32_t i, j, count, uid, basegid, gidptrCnt; + int32_t *gidp; + gid_t *gidptr; + audit_token_t token; + si_item_t *user, *item; + char **gidlist; + uint64_t va, vb; + size_t gidptrsz; + + if (name == NULL) return NULL; + + user = ds_user_byname(si, name); + if (user == NULL) return NULL; + + pw = (struct passwd *)((uintptr_t)user + sizeof(si_item_t)); + uid = pw->pw_uid; + basegid = pw->pw_gid; + + free(user); + + count = 0; + gidptr = NULL; + gidptrCnt = 0; + gidptrsz = 0; + memset(&token, 0, sizeof(audit_token_t)); + + kstatus = memberdDSmig_GetAllGroups(_ds_port, uid, &count, &gidptr, &gidptrCnt, &token); + if (kstatus != KERN_SUCCESS) return NULL; + + gidptrsz = gidptrCnt * sizeof(gid_t); + + if ((audit_token_uid(token) != 0) || (count == 0)) + { + if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); + return NULL; + } + + gidlist = (char **)calloc(count + 1, sizeof(char *)); + if (gidlist == NULL) + { + if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); + return NULL; + } + + for (i = 0; i < count; i++) + { + gidp = (int32_t *)calloc(1, sizeof(int32_t)); + if (gidp == NULL) + { + for (j = 0; j < i; j++) free(gidlist[j]); + free(gidlist); + count = 0; + break; + } + + *gidp = gidptr[i]; + gidlist[i] = (char *)gidp; + } + + if (count == 0) + { + if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); + return NULL; + } + + va = 0; + vb = 0; + ds_get_validation(si, &va, &vb, CATEGORY_GROUPLIST); + + item = (si_item_t *)LI_ils_create("L4488s44a", (unsigned long)si, CATEGORY_GROUPLIST, 1, va, vb, name, basegid, count, gidlist); + + if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); + + for (i = 0; i <= count; i++) free(gidlist[i]); + free(gidlist); + + return item; +} + +__private_extern__ si_list_t * +ds_netgroup_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_list_t *list; + + request = kvbuf_query_key_val("netgroup", name); + if (request == NULL) return NULL; + + list = ds_list(si, CATEGORY_NETGROUP, "getnetgrent", &proc, NULL, extract_netgroup, request); + + kvbuf_free(request); + + return list; +} + +static int +check_innetgr(kvarray_t *in) +{ + uint32_t d, k, kcount; + + if (in == NULL) return 0; + + d = in->curr; + if (d >= in->count) return 0; + + kcount = in->dict[d].kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(in->dict[d].key[k], "result")) + { + if (in->dict[d].vcount[k] == 0) continue; + return atoi(in->dict[d].val[k][0]); + } + } + + return 0; +} + +__private_extern__ int +ds_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain) +{ + int is_innetgr; + kvbuf_t *request; + kvarray_t *reply; + kern_return_t status; + static int proc = -1; + + if (proc < 0) + { + status = LI_DSLookupGetProcedureNumber("innetgr", &proc); + if (status != KERN_SUCCESS) return 0; + } + + /* Encode NULL */ + if (group == NULL) group = ""; + if (host == NULL) host = ""; + if (user == NULL) user = ""; + if (domain == NULL) domain = ""; + + request = kvbuf_query("ksksksks", "netgroup", group, "host", host, "user", user, "domain", domain); + if (request == NULL) return 0; + + reply = NULL; + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); + + if ((status != KERN_SUCCESS) || (reply == NULL)) return 0; + + is_innetgr = check_innetgr(reply); + + kvarray_free(reply); + + return is_innetgr; +} + +__private_extern__ si_item_t * +ds_alias_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_ALIAS, "alias_getbyname", &proc, NULL, extract_alias, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_alias_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_ALIAS, "alias_getent", &proc, NULL, extract_alias, NULL); +} + +__private_extern__ si_item_t * +ds_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + uint32_t want4, want6; + int cat; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (name == NULL) + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + want4 = 0; + want6 = 0; + + cat = CATEGORY_HOST_IPV4; + + if (af == AF_INET) + { + want4 = 1; + } + else if (af == AF_INET6) + { + want6 = 1; + cat = CATEGORY_HOST_IPV6; + } + else + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6); + if (request == NULL) + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + item = ds_item(si, cat, "gethostbyname", &proc, NULL, extract_host, request); + + if ((item == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + struct in_addr addr4; + struct in6_addr addr6; + char val[64 + 1 + IF_NAMESIZE]; + int cat; + uint32_t want; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + cat = CATEGORY_HOST_IPV4; + + memset(&addr4, 0, sizeof(struct in_addr)); + memset(&addr6, 0, sizeof(struct in6_addr)); + memset(val, 0, sizeof(val)); + + want = WANT_A4_ONLY; + + if (af == AF_INET) + { + memcpy(&addr4.s_addr, addr, IPV4_ADDR_LEN); + if (inet_ntop(af, &addr4, val, sizeof(val)) == NULL) + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + } + else if (af == AF_INET6) + { + want = WANT_A6_ONLY; + cat = CATEGORY_HOST_IPV6; + memcpy(&addr6, addr, IPV6_ADDR_LEN); + if (inet_ntop(af, &addr6, val, sizeof(val)) == NULL) + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + } + else + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + request = kvbuf_query("ksku", "address", val, "family", af); + if (request == NULL) + { + *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + item = ds_item(si, cat, "gethostbyaddr", &proc, &want, extract_host, request); + + if ((item == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_host_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_HOST_IPV4, "gethostent", &proc, NULL, extract_host, NULL); +} + +__private_extern__ si_item_t * +ds_network_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_NETWORK, "getnetbyname", &proc, NULL, extract_network, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_network_byaddr(si_mod_t *si, uint32_t addr) +{ + static int proc = -1; + unsigned char f1, f2, f3; + char val[64]; + kvbuf_t *request; + si_item_t *item; + + f1 = addr & 0xff; + addr >>= 8; + f2 = addr & 0xff; + addr >>= 8; + f3 = addr & 0xff; + + if (f3 != 0) snprintf(val, sizeof(val), "%u.%u.%u", f3, f2, f1); + else if (f2 != 0) snprintf(val, sizeof(val), "%u.%u", f2, f1); + else snprintf(val, sizeof(val), "%u", f1); + + request = kvbuf_query_key_val("net", val); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_NETWORK, "getnetbyaddr", &proc, NULL, extract_network, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_network_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_NETWORK, "getnetent", &proc, NULL, extract_network, NULL); +} + +__private_extern__ si_item_t * +ds_service_byname(si_mod_t *si, const char *name, const char *proto) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + struct servent *s; + + if (name == NULL) name = ""; + if (proto == NULL) proto = ""; + + /* Check our local service cache (see ds_addrinfo). */ + item = pthread_getspecific(_ds_serv_cache_key); + if (item != NULL) + { + s = (struct servent *)((uintptr_t)item + sizeof(si_item_t)); + if (string_equal(name, s->s_name)) return si_item_retain(item); + } + + request = kvbuf_query("ksks", "name", name, "proto", proto); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_SERVICE, "getservbyname", &proc, NULL, extract_service, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_service_byport(si_mod_t *si, int port, const char *proto) +{ + static int proc = -1; + uint16_t sport; + char val[16]; + kvbuf_t *request; + si_item_t *item; + + if (proto == NULL) proto = ""; + + sport = port; + snprintf(val, sizeof(val), "%d", ntohs(sport)); + + request = kvbuf_query("ksks", "port", val, "proto", proto); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_SERVICE, "getservbyport", &proc, NULL, extract_service, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_service_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_SERVICE, "getservent", &proc, NULL, extract_service, NULL); +} + +__private_extern__ si_item_t * +ds_protocol_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_PROTOCOL, "getprotobyname", &proc, NULL, extract_protocol, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_protocol_bynumber(si_mod_t *si, int number) +{ + static int proc = -1; + char val[16]; + kvbuf_t *request; + si_item_t *item; + + snprintf(val, sizeof(val), "%d", number); + request = kvbuf_query_key_val("number", val); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_PROTOCOL, "getprotobynumber", &proc, NULL, extract_protocol, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_protocol_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_PROTOCOL, "getprotoent", &proc, NULL, extract_protocol, NULL); +} + +__private_extern__ si_item_t * +ds_rpc_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_RPC, "getrpcbyname", &proc, NULL, extract_rpc, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_rpc_bynumber(si_mod_t *si, int number) +{ + static int proc = -1; + char val[16]; + kvbuf_t *request; + si_item_t *item; + + snprintf(val, sizeof(val), "%u", (uint32_t)number); + request = kvbuf_query_key_val("number", val); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_RPC, "getrpcbynumber", &proc, NULL, extract_rpc, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_rpc_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_RPC, "getrpcent", &proc, NULL, extract_rpc, NULL); +} + +__private_extern__ si_item_t * +ds_fs_byspec(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_FS, "getfsbyname", &proc, NULL, extract_fstab, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_list_t * +ds_fs_all(si_mod_t *si) +{ + static int proc = -1; + + return ds_list(si, CATEGORY_FS, "getfsent", &proc, NULL, extract_fstab, NULL); +} + +__private_extern__ si_item_t * +ds_fs_byfile(si_mod_t *si, const char *name) +{ + si_item_t *item; + si_list_t *list; + uint32_t i; + struct fstab *f; + + if (name == NULL) return NULL; + + list = ds_fs_all(si); + if (list == NULL) return NULL; + + item = NULL; + for (i = 0; (i < list->count) && (item == NULL); i++) + { + f = (struct fstab *)((uintptr_t)(list->entry[i]) + sizeof(si_item_t)); + if (string_equal(name, f->fs_file)) item = si_item_retain(list->entry[i]); + } + + si_list_release(list); + return item; +} + +__private_extern__ si_item_t * +ds_mac_byname(si_mod_t *si, const char *name) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + + request = kvbuf_query_key_val("name", name); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_MAC, "getmacbyname", &proc, (void *)name, extract_mac_mac, request); + + kvbuf_free(request); + return item; +} + +__private_extern__ si_item_t * +ds_mac_bymac(si_mod_t *si, const char *mac) +{ + static int proc = -1; + kvbuf_t *request; + si_item_t *item; + char *cmac; + + cmac = si_canonical_mac_address(mac); + if (cmac == NULL) return NULL; + + request = kvbuf_query_key_val("mac", cmac); + if (request == NULL) return NULL; + + item = ds_item(si, CATEGORY_MAC, "gethostbymac", &proc, cmac, extract_mac_name, request); + + free(cmac); + kvbuf_free(request); + return item; +} + +static si_list_t * +ds_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, uint32_t *err) +{ + static int proc = -1; + si_list_t *list, *out; + si_item_t *item; + kvbuf_t *request = NULL; + kvdict_t *dict; + kvarray_t *reply = NULL; + kern_return_t status = 0; + uint16_t scope = 0; + int i, k, kcount, d; + uint32_t port; + + struct hostent *h; + char *h_name = NULL; + int h_aliases_cnt = 0; + const char **h_aliases = NULL; + struct in_addr *a4 = NULL; + struct in6_addr *a6 = NULL; + int a4_cnt = 0; + int a6_cnt = 0; + struct servent *s; + const char *s_name = NULL; + int s_aliases_cnt = 0; + const char **s_aliases = NULL; + uint16_t s_port = 0; + const char *s_proto = NULL; + const char *protoname; + int wantv4, wantv6; + + int numericserv = ((flags & AI_NUMERICSERV) != 0); + int numerichost = ((flags & AI_NUMERICHOST) != 0); + + wantv4 = 0; + wantv6 = 0; + + if (node != NULL) + { + wantv4 = (family != AF_INET6); + wantv6 = (family != AF_INET); + } + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (proc < 0) + { + status = LI_DSLookupGetProcedureNumber("gethostbyname_service", &proc); + if (status != KERN_SUCCESS) + { + if (err != NULL) *err = SI_STATUS_EAI_SYSTEM; + return NULL; + } + } + + /* look up canonical name of numeric host */ + if ((numerichost == 1) && (flags & AI_CANONNAME) && (node != NULL)) + { + item = si_host_byaddr(si, node, family, NULL); + if (item != NULL) + { + h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); + h_name = strdup(h->h_name); + si_item_release(item); + } + } + + if (numericserv == 1) + { + s_port = *(int16_t *)serv; + } + + if ((numericserv == 0) || (numerichost == 0)) + { + request = kvbuf_new(); + if (request != NULL) + { + kvbuf_add_dict(request); + + if (numerichost == 0) + { + kvbuf_add_key(request, "name"); + kvbuf_add_val(request, node); + kvbuf_add_key(request, "ipv4"); + kvbuf_add_val(request, wantv4 ? "1" : "0"); + kvbuf_add_key(request, "ipv6"); + kvbuf_add_val(request, wantv6 ? "1" : "0"); + } + + if (numericserv == 0) + { + protoname = NULL; + if (proto == IPPROTO_UDP) protoname = "udp"; + if (proto == IPPROTO_TCP) protoname = "tcp"; + + kvbuf_add_key(request, "s_name"); + kvbuf_add_val(request, serv); + if (protoname != NULL) + { + kvbuf_add_key(request, "s_proto"); + kvbuf_add_val(request, protoname); + } + } + + status = LI_DSLookupQuery(proc, request, &reply); + kvbuf_free(request); + } + else + { + if (err != NULL) *err = SI_STATUS_EAI_SYSTEM; + } + } + + if ((status != KERN_SUCCESS) || (reply == NULL)) + { + free(h_name); + return NULL; + } + + for (d = 0; d < reply->count; d++) + { + dict = reply->dict + d; + kcount = dict->kcount; + + for (k = 0; k < kcount; k++) + { + if (string_equal(dict->key[k], "h_name")) + { + if (dict->vcount[k] == 0) continue; + h_name = strdup(dict->val[k][0]); + } + else if (string_equal(dict->key[k], "h_aliases")) + { + h_aliases_cnt = dict->vcount[k]; + h_aliases = (const char **)calloc(h_aliases_cnt, sizeof(char *)); + if (h_aliases == NULL) h_aliases_cnt = 0; + + for (i = 0; i < h_aliases_cnt; ++i) + { + h_aliases[i] = dict->val[k][i]; + } + } + else if (wantv4 && (string_equal(dict->key[k], "h_ipv4_addr_list"))) + { + a4_cnt = dict->vcount[k]; + a4 = calloc(a4_cnt, sizeof(struct in_addr)); + if (a4 == NULL) a4_cnt = 0; + + for (i = 0; i < a4_cnt; ++i) + { + memset(&a4[i], 0, sizeof(struct in_addr)); + inet_pton(AF_INET, dict->val[k][i], &a4[i]); + } + } + else if (wantv6 && (string_equal(dict->key[k], "h_ipv6_addr_list"))) + { + a6_cnt = dict->vcount[k]; + a6 = calloc(a6_cnt, sizeof(struct in6_addr)); + if (a6 == NULL) a6_cnt = 0; + + for (i = 0; i < a6_cnt; ++i) + { + memset(&a6[i], 0, sizeof(struct in6_addr)); + inet_pton(AF_INET6, dict->val[k][i], &a6[i]); + } + } + else if (string_equal(dict->key[k], "s_name")) + { + if (dict->vcount[k] == 0) continue; + s_name = dict->val[k][0]; + } + else if (string_equal(dict->key[k], "s_port")) + { + if (dict->vcount[k] == 0) continue; + s_port = atoi(dict->val[k][0]); + } + else if (string_equal(dict->key[k], "s_aliases")) + { + s_aliases_cnt = dict->vcount[k]; + s_aliases = (const char **)calloc(s_aliases_cnt+1, sizeof(char *)); + if (s_aliases == NULL) s_aliases_cnt = 0; + + for (i = 0; i < s_aliases_cnt; ++i) + { + s_aliases[i] = dict->val[k][i]; + } + } + else if (string_equal(dict->key[k], "s_proto")) + { + if (dict->vcount[k] == 0) continue; + s_proto = dict->val[k][0]; + } + } + } + + kvarray_free(reply); + + /* check if we actually got back what we wanted */ + if (((wantv4 || wantv6) && (a4_cnt == 0) && (a6_cnt == 0)) || ((serv != NULL) && (s_port == 0))) + { + if (err != NULL) *err = SI_STATUS_EAI_NONAME; + + free(h_name); + free(h_aliases); + free(s_aliases); + free(a4); + free(a6); + + return NULL; + } + + /* + * Cache the service entry regardless of whether there is a host match. + * This allows later modules to get the service entry quickly. + * This should really be part of the general cache mechanism, but that's + * not currently visible outside of the search module. + */ + if ((s_name != NULL) && (s_port != 0)) + { + port = htons(s_port); + + item = pthread_getspecific(_ds_serv_cache_key); + if (item != NULL) + { + s = (struct servent *)((uintptr_t)item + sizeof(si_item_t)); + if ((port != s->s_port) || string_not_equal(s_name, s->s_name)) + { + si_item_release(item); + item = NULL; + } + } + + if (item == NULL) + { + item = LI_ils_create("L4488s*4s", (unsigned long)si, CATEGORY_SERVICE, 1, (uint64_t)1, (uint64_t)1, s_name, s_aliases, port, s_proto); + pthread_setspecific(_ds_serv_cache_key, item); + } + } + + /* Construct the addrinfo list from the returned addresses (if found). */ + out = NULL; + for (i = 0; i < a6_cnt; i++) + { + list = si_addrinfo_list(si, socktype, proto, NULL, &a6[i], s_port, scope, NULL, h_name); + out = si_list_concat(out, list); + si_list_release(list); + } + + for (i = 0; i < a4_cnt; i++) + { + list = si_addrinfo_list(si, socktype, proto, &a4[i], NULL, s_port, 0, h_name, NULL); + out = si_list_concat(out, list); + si_list_release(list); + } + + free(h_name); + free(h_aliases); + free(s_aliases); + free(a4); + free(a6); + + return out; +} + +__private_extern__ int +ds_is_valid(si_mod_t *si, si_item_t *item) +{ + si_mod_t *src; + ds_si_private_t *pp; + int status; + uint32_t oldval, newval; + + if (si == NULL) return 0; + if (item == NULL) return 0; + if (si->name == NULL) return 0; + if (item->src == NULL) return 0; + + pp = (ds_si_private_t *)si->private; + if (pp == NULL) return 0; + + src = (si_mod_t *)item->src; + + if (src->name == NULL) return 0; + if (string_not_equal(si->name, src->name)) return 0; + + /* check global invalidation */ + oldval = item->validation_a; + newval = -1; + status = notify_peek(pp->notify_token_global, &newval); + if (status != NOTIFY_STATUS_OK) return 0; + + newval = ntohl(newval); + if (oldval != newval) return 0; + + oldval = item->validation_b; + newval = -1; + if (item->type == CATEGORY_USER) status = notify_peek(pp->notify_token_user, &newval); + else if (item->type == CATEGORY_GROUP) status = notify_peek(pp->notify_token_group, &newval); + else if (item->type == CATEGORY_HOST_IPV4) status = notify_peek(pp->notify_token_host, &newval); + else if (item->type == CATEGORY_HOST_IPV6) status = notify_peek(pp->notify_token_host, &newval); + else if (item->type == CATEGORY_SERVICE) status = notify_peek(pp->notify_token_service, &newval); + else return 0; + + if (status != NOTIFY_STATUS_OK) return 0; + + newval = ntohl(newval); + if (oldval != newval) return 0; + + return 1; +} + +__private_extern__ si_mod_t * +si_module_static_ds() +{ + si_mod_t *out; + char *outname; + ds_si_private_t *pp; + int status; + + out = (si_mod_t *)calloc(1, sizeof(si_mod_t)); + outname = strdup("ds"); + pp = (ds_si_private_t *)calloc(1, sizeof(ds_si_private_t)); + + if ((out == NULL) || (outname == NULL) || (pp == NULL)) + { + if (out != NULL) free(out); + if (outname != NULL) free(outname); + if (pp != NULL) free(pp); + + errno = ENOMEM; + return NULL; + } + + pthread_key_create(&_ds_serv_cache_key, _ds_serv_cache_free); + + pp->notify_token_global = -1; + pp->notify_token_user = -1; + pp->notify_token_group = -1; + pp->notify_token_host = -1; + pp->notify_token_service = -1; + + /* + * Don't register for notifications if the cache is disabled. + * notifyd (notably) disables the cache to prevent deadlocks. + */ + if (gL1CacheEnabled != 0) + { + /* + * Errors in registering for cache invalidation notifications are ignored. + * If there are failures, the tokens remain set to -1 which just causes + * cached items to be invalidated. + */ + status = notify_register_check(DS_NOTIFICATION_KEY_GLOBAL, &(pp->notify_token_global)); + status = notify_register_check(DS_NOTIFICATION_KEY_GLOBAL, &(pp->notify_token_user)); + status = notify_register_check(DS_NOTIFICATION_KEY_GLOBAL, &(pp->notify_token_group)); + status = notify_register_check(DS_NOTIFICATION_KEY_GLOBAL, &(pp->notify_token_host)); + status = notify_register_check(DS_NOTIFICATION_KEY_GLOBAL, &(pp->notify_token_service)); + } + + out->name = outname; + out->vers = 1; + out->refcount = 1; + out->private = pp; + + out->sim_is_valid = ds_is_valid; + + out->sim_user_byname = ds_user_byname; + out->sim_user_byuid = ds_user_byuid; + out->sim_user_all = ds_user_all; + + out->sim_group_byname = ds_group_byname; + out->sim_group_bygid = ds_group_bygid; + out->sim_group_all = ds_group_all; + + out->sim_grouplist = ds_grouplist; + + out->sim_netgroup_byname = ds_netgroup_byname; + out->sim_in_netgroup = ds_in_netgroup; + + out->sim_alias_byname = ds_alias_byname; + out->sim_alias_all = ds_alias_all; + + out->sim_host_byname = ds_host_byname; + out->sim_host_byaddr = ds_host_byaddr; + out->sim_host_all = ds_host_all; + + out->sim_network_byname = ds_network_byname; + out->sim_network_byaddr = ds_network_byaddr; + out->sim_network_all = ds_network_all; + + out->sim_service_byname = ds_service_byname; + out->sim_service_byport = ds_service_byport; + out->sim_service_all = ds_service_all; + + out->sim_protocol_byname = ds_protocol_byname; + out->sim_protocol_bynumber = ds_protocol_bynumber; + out->sim_protocol_all = ds_protocol_all; + + out->sim_rpc_byname = ds_rpc_byname; + out->sim_rpc_bynumber = ds_rpc_bynumber; + out->sim_rpc_all = ds_rpc_all; + + out->sim_fs_byspec = ds_fs_byspec; + out->sim_fs_byfile = ds_fs_byfile; + out->sim_fs_all = ds_fs_all; + + out->sim_mac_byname = ds_mac_byname; + out->sim_mac_bymac = ds_mac_bymac; + + /* si_mac_all not supported */ + out->sim_mac_all = NULL; + + out->sim_addrinfo = ds_addrinfo; + + return out; +} diff --git a/lookup.subproj/file_module.c b/lookup.subproj/file_module.c new file mode 100644 index 0000000..b58558f --- /dev/null +++ b/lookup.subproj/file_module.c @@ -0,0 +1,1758 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* These really should be in netdb.h & etc. */ +#define _PATH_RPCS "/etc/rpc" +#define _PATH_ALIASES "/etc/aliases" +#define _PATH_ETHERS "/etc/ethers" + +static si_item_t *rootfs = NULL; + +static char * +_fsi_copy_string(char *s) +{ + int len; + char *t; + + if (s == NULL) return NULL; + + len = strlen(s) + 1; + t = malloc(len); + bcopy(s, t, len); + return t; +} + +static char ** +_fsi_append_string(char *s, char **l) +{ + int i, len; + + if (s == NULL) return l; + if (l == NULL) + { + l = (char **)malloc(2 * sizeof(char *)); + l[0] = s; + l[1] = NULL; + return l; + } + + for (i = 0; l[i] != NULL; i++); + len = i + 1; /* count the NULL on the end of the list too! */ + + l = (char **)reallocf(l, (len + 1) * sizeof(char *)); + + l[len - 1] = s; + l[len] = NULL; + return l; +} + +__private_extern__ char ** +_fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens) +{ + char **tokens; + int p, i, start, end, more, len, end_on_sep; + int scanning; + + tokens = NULL; + end_on_sep = 0; + + if (data == NULL) return NULL; + + if (ntokens != NULL) *ntokens = 0; + if (sep == NULL) + { + tokens = _fsi_append_string(data, tokens); + if (ntokens != NULL) *ntokens = *ntokens + 1; + return tokens; + } + + len = strlen(sep); + p = 0; + + while (data[p] != '\0') + { + end_on_sep = 1; + /* skip leading white space */ + while ((data[p] == ' ') || (data[p] == '\t') || (data[p] == '\n')) p++; + + /* check for end of line */ + if (data[p] == '\0') break; + + /* scan for separator */ + start = p; + end = p; + scanning = 1; + end_on_sep = 0; + + while (scanning == 1) + { + if (data[p] == '\0') break; + + for (i = 0; i < len; i++) + { + if (data[p] == sep[i]) + { + scanning = 0; + end_on_sep = 1; + break; + } + } + + /* end is last non-whitespace character */ + if ((scanning == 1) && (data[p] != ' ') && (data[p] != '\t') && (data[p] != '\n')) end = p; + + p += scanning; + } + + /* see if there's data left after p */ + more = 0; + if (data[p] != '\0') more = 1; + + /* set the character following the token to nul */ + if (start == p) data[p] = '\0'; + else data[end + 1] = '\0'; + + tokens = _fsi_append_string(data + start, tokens); + if (ntokens != NULL) *ntokens = *ntokens + 1; + p += more; + } + + if ((end_on_sep == 1) && (trailing_empty != 0)) + { + /* if the scan ended on an empty token, add a null string */ + tokens = _fsi_append_string(data + p, tokens); + if (ntokens != NULL) *ntokens = *ntokens + 1; + } + + return tokens; +} + +__private_extern__ char * +_fsi_get_line(FILE *fp) +{ + char s[4096]; + char *out; + + s[0] = '\0'; + + fgets(s, sizeof(s), fp); + if ((s == NULL) || (s[0] == '\0')) return NULL; + + if (s[0] != '#') s[strlen(s) - 1] = '\0'; + + out = _fsi_copy_string(s); + return out; +} + +/* USERS */ + +static si_item_t * +_fsi_parse_user(si_mod_t *si, const char *name, uid_t uid, int which, char *data, int format, uint64_t sec, uint64_t nsec) +{ + char **tokens; + int ntokens, match; + time_t change, exsire; + si_item_t *item; + uid_t xuid; + + if (data == NULL) return NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, ":", 1, &ntokens); + if (((format == 0) && (ntokens != 10)) || ((format == 1) && (ntokens != 7))) + { + free(tokens); + return NULL; + } + + xuid = atoi(tokens[2]); + match = 0; + + /* XXX MATCH GECOS? XXX*/ + if (which == SEL_ALL) match = 1; + else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; + else if ((which == SEL_NUMBER) && (uid == xuid)) match = 1; + + if (match == 0) + { + free(tokens); + return NULL; + } + + if (format == 0) + { + /* master.passwd: name[0] passwd[1] uid[2] gid[3] class[4] change[5] exsire[6] gecos[7] dir[8] shell[9] */ + /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[5] class[4] gecos[7] dir[8] shell[9] exsire[6] */ + change = atoi(tokens[5]); + exsire = atoi(tokens[6]); + item = (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, sec, nsec, tokens[0], tokens[1], xuid, atoi(tokens[3]), change, tokens[4], tokens[7], tokens[8], tokens[9], exsire); + } + else + { + /* passwd: name[0] passwd[1] uid[2] gid[3] gecos[4] dir[5] shell[6] */ + /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[-] class[-] gecos[4] dir[5] shell[6] exsire[-] */ + item = (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, sec, nsec, tokens[0], tokens[1], xuid, atoi(tokens[3]), 0, "", tokens[4], tokens[5], tokens[6], 0); + } + + free(tokens); + return item; +} + +static void * +_fsi_get_user(si_mod_t *si, const char *name, uid_t uid, int which) +{ + char *line; + si_item_t *item; + int fmt; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + if ((which == SEL_NAME) && (name == NULL)) return NULL; + + all = NULL; + f = NULL; + fmt = 0; + sec = 0; + nsec = 0; + + if (geteuid() == 0) + { + f = fopen(_PATH_MASTERPASSWD, "r"); + } + else + { + f = fopen(_PATH_PASSWD, "r"); + fmt = 1; + } + + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + item = _fsi_parse_user(si, name, uid, which, line, fmt, sec, nsec); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + fclose(f); + return all; +} + +/* GROUPS */ + +static si_item_t * +_fsi_parse_group(si_mod_t *si, const char *name, gid_t gid, int which, char *data, uint64_t sec, uint64_t nsec) +{ + char **tokens, **members; + int ntokens, match; + si_item_t *item; + gid_t xgid; + + if (data == NULL) return NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, ":", 1, &ntokens); + if (ntokens != 4) + { + free(tokens); + return NULL; + } + + xgid = atoi(tokens[2]); + match = 0; + + if (which == SEL_ALL) match = 1; + else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; + else if ((which == SEL_NUMBER) && (gid == xgid)) match = 1; + + if (match == 0) + { + free(tokens); + return NULL; + } + + ntokens = 0; + members = _fsi_tokenize(tokens[3], ",", 1, &ntokens); + + item = (si_item_t *)LI_ils_create("L4488ss4*", (unsigned long)si, CATEGORY_GROUP, 1, sec, nsec, tokens[0], tokens[1], xgid, members); + + free(tokens); + free(members); + + return item; +} + +static void * +_fsi_get_group(si_mod_t *si, const char *name, gid_t gid, int which) +{ + char *line; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + if ((which == SEL_NAME) && (name == NULL)) return NULL; + + all = NULL; + f = NULL; + sec = 0; + nsec = 0; + + f = fopen(_PATH_GROUP, "r"); + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + item = _fsi_parse_group(si, name, gid, which, line, sec, nsec); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +static void * +_fsi_get_grouplist(si_mod_t *si, const char *user) +{ + char **tokens, **members; + int ntokens, i, match, gidcount; + char *line; + si_item_t *item; + FILE *f; + struct stat sb; + uint64_t sec, nsec; + int32_t gid, basegid, *gidp; + char **gidlist; + struct passwd *pw; + + if (user == NULL) return NULL; + + gidlist = NULL; + gidcount = 0; + f = NULL; + sec = 0; + nsec = 0; + basegid = -1; + + item = si->sim_user_byname(si, user); + if (item != NULL) + { + pw = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); + basegid = pw->pw_gid; + free(item); + } + + f = fopen(_PATH_GROUP, "r"); + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + ntokens = 0; + tokens = _fsi_tokenize(line, ":", 1, &ntokens); + if (ntokens != 4) + { + free(tokens); + continue; + } + + ntokens = 0; + members = _fsi_tokenize(tokens[3], ",", 1, &ntokens); + + match = 0; + gid = -2; + + for (i = 0; (i < ntokens) && (match == 0); i++) + { + if (string_equal(user, members[i])) + { + gid = atoi(tokens[2]); + match = 1; + } + } + + free(tokens); + free(members); + free(line); + line = NULL; + + if (match == 1) + { + if (gidcount == 0) gidlist = (char **)calloc(1, sizeof(char *)); + else gidlist = (char **)reallocf(gidlist, (gidcount + 1) * sizeof(char *)); + gidp = (int32_t *)calloc(1, sizeof(int32_t)); + + if (gidlist == NULL) + { + gidcount = 0; + break; + } + + if (gidp == NULL) + { + for (i = 0; i < gidcount; i++) free(gidlist[i]); + free(gidlist); + gidcount = 0; + break; + } + + *gidp = gid; + gidlist[gidcount++] = (char *)gidp; + } + } + + fclose(f); + + if (gidcount == 0) return NULL; + + gidlist = (char **)reallocf(gidlist, (gidcount + 1) * sizeof(int32_t *)); + if (gidlist == NULL) return NULL; + gidlist[gidcount] = NULL; + + item = (si_item_t *)LI_ils_create("L4488s44a", (unsigned long)si, CATEGORY_GROUPLIST, 1, sec, nsec, user, basegid, gidcount, gidlist); + + for (i = 0; i <= gidcount; i++) free(gidlist[i]); + free(gidlist); + + return item; +} + +/* ALIASES */ + +static si_item_t * +_fsi_parse_alias(si_mod_t *si, const char *name, int which, char *data, uint64_t sec, uint64_t nsec) +{ + char **tokens, **members; + int ntokens, match; + si_item_t *item; + + if (data == NULL) return NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, ":", 1, &ntokens); + if (ntokens < 2) + { + free(tokens); + return NULL; + } + + match = 0; + + if (which == SEL_ALL) match = 1; + else if (string_equal(name, tokens[0])) match = 1; + + if (match == 0) + { + free(tokens); + return NULL; + } + + ntokens = 0; + members = _fsi_tokenize(tokens[3], ",", 1, &ntokens); + + item = (si_item_t *)LI_ils_create("L4488s4*4", (unsigned long)si, CATEGORY_ALIAS, 1, sec, nsec, tokens[0], ntokens, members, 1); + + free(tokens); + free(members); + + return item; +} + +static void * +_fsi_get_alias(si_mod_t *si, const char *name, int which) +{ + char *line; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + if ((which == SEL_NAME) && (name == NULL)) return NULL; + + all = NULL; + f = NULL; + sec = 0; + nsec = 0; + + f = fopen(_PATH_ALIASES, "r"); + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + item = _fsi_parse_alias(si, name, which, line, sec, nsec); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +/* ETHERS */ + +static si_item_t * +_fsi_parse_ether(si_mod_t *si, const char *name, int which, char *data, uint64_t sec, uint64_t nsec) +{ + char **tokens; + char *cmac; + int ntokens, match; + si_item_t *item; + + if (data == NULL) return NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, " \t", 1, &ntokens); + if (ntokens != 2) + { + free(tokens); + return NULL; + } + + cmac = si_canonical_mac_address(tokens[1]); + if (cmac == NULL) + { + free(tokens); + return NULL; + } + + match = 0; + if (which == SEL_ALL) match = 1; + else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; + else if ((which == SEL_NUMBER) && (string_equal(name, cmac))) match = 1; + + if (match == 0) + { + free(tokens); + free(cmac); + return NULL; + } + + item = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, sec, nsec, tokens[0], cmac); + + free(tokens); + free(cmac); + + return item; +} + +static void * +_fsi_get_ether(si_mod_t *si, const char *name, int which) +{ + char *line, *cmac; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + if ((which != SEL_ALL) && (name == NULL)) return NULL; + + cmac = NULL; + if (which == SEL_NUMBER) + { + cmac = si_canonical_mac_address(name); + if (cmac == NULL) return NULL; + } + + all = NULL; + f = NULL; + sec = 0; + nsec = 0; + + f = fopen(_PATH_ETHERS, "r"); + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + item = NULL; + if (which == SEL_NUMBER) item = _fsi_parse_ether(si, cmac, which, line, sec, nsec); + else item = _fsi_parse_ether(si, name, which, line, sec, nsec); + + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +/* HOSTS */ + +static si_item_t * +_fsi_parse_host(si_mod_t *si, const char *name, const void *addr, int af, int which, char *data, uint64_t sec, uint64_t nsec) +{ + char **tokens, **h_aliases, *null_alias; + int i, ntokens, match, xaf, h_length; + struct in_addr a4; + struct in6_addr a6; + si_item_t *item; + char *h_addr_list[2]; + char h_addr_4[4], h_addr_6[16]; + + if (data == NULL) return NULL; + + null_alias = NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, " ", 0, &ntokens); + if (ntokens < 2) + { + free(tokens); + return NULL; + } + + h_addr_list[1] = NULL; + + xaf = AF_UNSPEC; + if (inet_pton(AF_INET, tokens[0], &a4) == 1) + { + xaf = AF_INET; + h_length = sizeof(struct in_addr); + memcpy(h_addr_4, &a4, 4); + h_addr_list[0] = h_addr_4; + } + else if (inet_pton(AF_INET6, tokens[0], &a6) == 1) + { + xaf = AF_INET6; + h_length = sizeof(struct in6_addr); + memcpy(h_addr_6, &a6, 16); + h_addr_list[0] = h_addr_6; + } + + if (xaf == AF_UNSPEC) + { + free(tokens); + return NULL; + } + + h_aliases = NULL; + if (ntokens > 2) h_aliases = &(tokens[2]); + + match = 0; + + if (which == SEL_ALL) match = 1; + else + { + if (af == xaf) + { + if (which == SEL_NAME) + { + if (string_equal(name, tokens[1])) match = 1; + else if (h_aliases != NULL) + { + for (i = 0; (h_aliases[i] != NULL) && (match == 0); i++) + if (string_equal(name, h_aliases[i])) match = 1; + } + } + else if (which == SEL_NUMBER) + { + if (memcmp(addr, h_addr_list[0], h_length) == 0) match = 1; + } + } + } + + if (match == 0) + { + free(tokens); + return NULL; + } + + item = NULL; + + if (h_aliases == NULL) h_aliases = &null_alias; + + if (af == AF_INET) + { + item = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, sec, nsec, tokens[1], h_aliases, af, h_length, h_addr_list); + } + else + { + item = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, sec, nsec, tokens[1], h_aliases, af, h_length, h_addr_list); + } + + free(tokens); + + return item; +} + +static void * +_fsi_get_host(si_mod_t *si, const char *name, const void *addr, int af, int which, uint32_t *err) +{ + char *line; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + sec = 0; + nsec = 0; + + if ((which == SEL_NAME) && (name == NULL)) + { + if (err != NULL) *err = NO_RECOVERY; + return NULL; + } + + if ((which == SEL_NUMBER) && (addr == NULL)) + { + if (err != NULL) *err = NO_RECOVERY; + return NULL; + } + + f = fopen(_PATH_HOSTS, "r"); + if (f == NULL) + { + if (err != NULL) *err = NO_RECOVERY; + return NULL; + } + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + all = NULL; + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + item = _fsi_parse_host(si, name, addr, af, which, line, sec, nsec); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +/* SERVICE */ + +static si_item_t * +_fsi_parse_service(si_mod_t *si, const char *name, const char *proto, int port, int which, char *data, uint64_t sec, uint64_t nsec) +{ + char **tokens, **s_aliases, *xproto; + int i, ntokens, match; + si_item_t *item; + int xport; + + if (data == NULL) return NULL; + + port = ntohs(port); + + ntokens = 0; + tokens = _fsi_tokenize(data, " ", 0, &ntokens); + if (ntokens < 2) + { + free(tokens); + return NULL; + } + + s_aliases = NULL; + if (ntokens > 2) s_aliases = &(tokens[2]); + + xport = atoi(tokens[1]); + + xproto = strchr(tokens[1], '/'); + + if (xproto == NULL) + { + free(tokens); + return NULL; + } + + *xproto++ = '\0'; + if ((proto != NULL) && (string_not_equal(proto, xproto))) + { + free(tokens); + return NULL; + } + + match = 0; + if (which == SEL_ALL) match = 1; + else if (which == SEL_NAME) + { + if (string_equal(name, tokens[0])) match = 1; + else if (s_aliases != NULL) + { + for (i = 0; (s_aliases[i] != NULL) && (match == 0); i++) + if (string_equal(name, s_aliases[i])) match = 1; + } + } + else if ((which == SEL_NUMBER) && (port == xport)) match = 1; + + if (match == 0) + { + free(tokens); + return NULL; + } + + /* strange but correct */ + xport = htons(xport); + + item = (si_item_t *)LI_ils_create("L4488s*4s", (unsigned long)si, CATEGORY_SERVICE, 1, sec, nsec, tokens[0], s_aliases, xport, xproto); + + free(tokens); + + return item; +} + +static void * +_fsi_get_service(si_mod_t *si, const char *name, const char *proto, int port, int which) +{ + char *p, *line; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + sec = 0; + nsec = 0; + + if ((which == SEL_NAME) && (name == NULL)) return NULL; + if ((which == SEL_NUMBER) && (port == 0)) return NULL; + + f = fopen(_PATH_SERVICES, "r"); + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + all = NULL; + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + p = strchr(line, '#'); + if (p != NULL) *p = '\0'; + + item = _fsi_parse_service(si, name, proto, port, which, line, sec, nsec); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +/* + * Generic name/number/aliases lookup + * Works for protocols, networks, and rpcs + */ + +static si_item_t * +_fsi_parse_name_num_aliases(si_mod_t *si, const char *name, int num, int which, char *data, uint64_t sec, uint64_t nsec, int cat) +{ + char **tokens, **aliases; + int i, ntokens, match, xnum; + si_item_t *item; + + if (data == NULL) return NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, " ", 0, &ntokens); + if (ntokens < 2) + { + free(tokens); + return NULL; + } + + xnum = atoi(tokens[1]); + + aliases = NULL; + if (ntokens > 2) aliases = &(tokens[2]); + + match = 0; + + if (which == SEL_ALL) match = 1; + else if (which == SEL_NAME) + { + if (string_equal(name, tokens[0])) match = 1; + else if (aliases != NULL) + { + for (i = 0; (aliases[i] != NULL) && (match == 0); i++) + if (string_equal(name, aliases[i])) match = 1; + } + } + else if ((which == SEL_NUMBER) && (num == xnum)) match = 1; + + if (match == 0) + { + free(tokens); + return NULL; + } + + item = (si_item_t *)LI_ils_create("L4488s*4", (unsigned long)si, cat, 1, sec, nsec, tokens[0], aliases, xnum); + + free(tokens); + + return item; +} + +static void * +_fsi_get_name_number_aliases(si_mod_t *si, const char *name, int num, int which, int cat, const char *path) +{ + char *p, *line; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + + sec = 0; + nsec = 0; + + f = fopen(path, "r"); + if (f == NULL) return NULL; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + all = NULL; + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + p = strchr(line, '#'); + if (p != NULL) *p = '\0'; + + item = _fsi_parse_name_num_aliases(si, name, num, which, line, sec, nsec, cat); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +/* MOUNT */ + +static si_item_t * +_fsi_parse_fs(si_mod_t *si, const char *name, int which, char *data, uint64_t sec, uint64_t nsec) +{ + char **tokens, *tmp, **opts, *fstype; + int ntokens, match, i, freq, passno; + si_item_t *item; + + if (data == NULL) return NULL; + + freq = 0; + passno = 0; + fstype = NULL; + + ntokens = 0; + tokens = _fsi_tokenize(data, " ", 0, &ntokens); + if ((ntokens < 4) || (ntokens > 6)) + { + free(tokens); + return NULL; + } + + if (ntokens >= 5) freq = atoi(tokens[4]); + if (ntokens == 6) passno = atoi(tokens[5]); + + tmp = strdup(tokens[3]); + if (tmp == NULL) + { + free(tokens); + return NULL; + } + + ntokens = 0; + opts = _fsi_tokenize(tmp, ",", 0, &ntokens); + + if (opts == NULL) + { + free(tokens); + free(tmp); + return NULL; + } + + for (i = 0; i < ntokens; i++) + { + if ((string_equal(opts[i], "rw")) || (string_equal(opts[i], "ro")) || (string_equal(opts[i], "sw")) || (string_equal(opts[i], "xx"))) + { + fstype = opts[i]; + break; + } + } + + match = 0; + + if (which == SEL_ALL) match = 1; + else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; + else if ((which == SEL_NUMBER) && (string_equal(name, tokens[1]))) match = 1; + + if (match == 0) + { + free(tokens); + return NULL; + } + + item = (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, sec, nsec, tokens[0], tokens[1], tokens[2], tokens[3], (fstype == NULL) ? "rw" : fstype, freq, passno); + + free(tokens); + free(opts); + free(tmp); + + return item; +} + +static char * +_fsi_get_device_path(dev_t target_dev) +{ + char *result; + char dev[PATH_MAX]; + char *name; + char namebuf[PATH_MAX]; + + result = NULL; + + strlcpy(dev, _PATH_DEV, sizeof(dev)); + + /* The root device in fstab should always be a block special device */ + name = devname_r(target_dev, S_IFBLK, namebuf, sizeof(namebuf)); + if (name == NULL) + { + DIR *dirp; + struct stat devst; + struct dirent *ent, entbuf; + + /* No _PATH_DEVDB. We have to search for it the slow way */ + dirp = opendir(_PATH_DEV); + if (dirp == NULL) return NULL; + + while (readdir_r(dirp, &entbuf, &ent) == 0 && ent != NULL) + { + /* Look for a block special device */ + if (ent->d_type == DT_BLK) + { + strlcat(dev, ent->d_name, sizeof(dev)); + if (stat(dev, &devst) == 0) + { + if (devst.st_rdev == target_dev) { + result = strdup(dev); + break; + } + } + } + + /* reset dev to _PATH_DEV and try again */ + dev[sizeof(_PATH_DEV) - 1] = '\0'; + } + + if (dirp) closedir(dirp); + } + else + { + /* We found the _PATH_DEVDB entry */ + strlcat(dev, name, sizeof(dev)); + result = strdup(dev); + } + + return result; +} + +static si_item_t * +_fsi_fs_root(si_mod_t *si) +{ + struct stat rootstat; + struct statfs rootfsinfo; + char *root_spec; + const char *root_path; + + if (rootfs != NULL) return si_item_retain(rootfs); + + root_path = "/"; + + if (stat(root_path, &rootstat) < 0) return NULL; + if (statfs(root_path, &rootfsinfo) < 0) return NULL; + + /* Check to make sure we're not looking at a synthetic root: */ + if (string_equal(rootfsinfo.f_fstypename, "synthfs")) + { + root_path = "/root"; + if (stat(root_path, &rootstat) < 0) return NULL; + if (statfs(root_path, &rootfsinfo) < 0) return NULL; + } + + root_spec = _fsi_get_device_path(rootstat.st_dev); + + rootfs = (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, 0LL, 0LL, root_spec, root_path, rootfsinfo.f_fstypename, FSTAB_RW, FSTAB_RW, 0, 1); + return rootfs; +} + + +static void * +_fsi_get_fs(si_mod_t *si, const char *name, int which) +{ + char *line; + si_item_t *item; + FILE *f; + si_list_t *all; + struct stat sb; + uint64_t sec, nsec; + int synthesize_root; + struct fstab *rfs; + + if ((which != SEL_ALL) && (name == NULL)) return NULL; + + all = NULL; + f = NULL; + sec = 0; + nsec = 0; +#ifdef SYNTH_ROOTFS + synthesize_root = 1; +#else + synthesize_root = 0; +#endif + + f = fopen(_PATH_FSTAB, "r"); + if ((f == NULL) || (synthesize_root == 1)) + { + item = _fsi_fs_root(si); + + rfs = NULL; + if (item != NULL) rfs = (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); + + switch (which) + { + case SEL_NAME: + { + if ((rfs != NULL) && (string_equal(name, rfs->fs_spec))) + { + if (f != NULL) fclose(f); + return item; + } + + break; + } + + case SEL_NUMBER: + { + if ((rfs != NULL) && (string_equal(name, rfs->fs_file))) + { + if (f != NULL) fclose(f); + return item; + } + + break; + } + + case SEL_ALL: + { + all = si_list_add(all, item); + si_item_release(item); + break; + } + } + } + + if (f == NULL) return all; + + memset(&sb, 0, sizeof(struct stat)); + if (fstat(fileno(f), &sb) == 0) + { + sec = sb.st_mtimespec.tv_sec; + nsec = sb.st_mtimespec.tv_nsec; + } + + forever + { + line = _fsi_get_line(f); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + item = _fsi_parse_fs(si, name, which, line, sec, nsec); + free(line); + line = NULL; + + if (item == NULL) continue; + + if (which == SEL_ALL) + { + all = si_list_add(all, item); + si_item_release(item); + continue; + } + + fclose(f); + return item; + } + + fclose(f); + return all; +} + +__private_extern__ int +file_is_valid(si_mod_t *si, si_item_t *item) +{ + struct stat sb; + uint64_t sec, nsec; + const char *path; + si_mod_t *src; + + if (si == NULL) return 0; + if (item == NULL) return 0; + if (si->name == NULL) return 0; + if (item->src == NULL) return 0; + + src = (si_mod_t *)item->src; + + if (src->name == NULL) return 0; + if (string_not_equal(si->name, src->name)) return 0; + + if (item == rootfs) return 1; + + path = NULL; + memset(&sb, 0, sizeof(struct stat)); + sec = item->validation_a; + nsec = item->validation_b; + + if (item->type == CATEGORY_USER) + { + if (geteuid() == 0) path = _PATH_MASTERPASSWD; + else path = _PATH_PASSWD; + } + else if (item->type == CATEGORY_GROUP) path = _PATH_GROUP; + else if (item->type == CATEGORY_HOST_IPV4) path = _PATH_HOSTS; + else if (item->type == CATEGORY_HOST_IPV6) path = _PATH_HOSTS; + else if (item->type == CATEGORY_NETWORK) path = _PATH_NETWORKS; + else if (item->type == CATEGORY_SERVICE) path = _PATH_SERVICES; + else if (item->type == CATEGORY_PROTOCOL) path = _PATH_PROTOCOLS; + else if (item->type == CATEGORY_RPC) path = _PATH_RPCS; + else if (item->type == CATEGORY_FS) path = _PATH_FSTAB; + + if (path == NULL) return 0; + if (stat(path, &sb) != 0) return 0; + if (sec != sb.st_mtimespec.tv_sec) return 0; + if (nsec != sb.st_mtimespec.tv_nsec) return 0; + + return 1; +} + +__private_extern__ si_item_t * +file_user_byname(si_mod_t *si, const char *name) +{ + return _fsi_get_user(si, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +file_user_byuid(si_mod_t *si, uid_t uid) +{ + return _fsi_get_user(si, NULL, uid, SEL_NUMBER); +} + +__private_extern__ si_list_t * +file_user_all(si_mod_t *si) +{ + return _fsi_get_user(si, NULL, 0, SEL_ALL); +} + +__private_extern__ si_item_t * +file_group_byname(si_mod_t *si, const char *name) +{ + return _fsi_get_group(si, name, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +file_group_bygid(si_mod_t *si, gid_t gid) +{ + return _fsi_get_group(si, NULL, gid, SEL_NUMBER); +} + +__private_extern__ si_list_t * +file_group_all(si_mod_t *si) +{ + return _fsi_get_group(si, NULL, 0, SEL_ALL); +} + +__private_extern__ si_item_t * +file_grouplist(si_mod_t *si, const char *name) +{ + return _fsi_get_grouplist(si, name); +} + +__private_extern__ si_item_t * +file_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + si_item_t *item; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + item = _fsi_get_host(si, name, NULL, af, SEL_NAME, err); + if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + + return item; +} + +__private_extern__ si_item_t * +file_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + si_item_t *item; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + item = _fsi_get_host(si, NULL, addr, af, SEL_NUMBER, err); + if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + + return item; +} + +__private_extern__ si_list_t * +file_host_all(si_mod_t *si) +{ + return _fsi_get_host(si, NULL, NULL, 0, SEL_ALL, NULL); +} + +__private_extern__ si_item_t * +file_network_byname(si_mod_t *si, const char *name) +{ + if (name == NULL) return NULL; + return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_NETWORK, _PATH_NETWORKS); +} + +__private_extern__ si_item_t * +file_network_byaddr(si_mod_t *si, uint32_t addr) +{ + return _fsi_get_name_number_aliases(si, NULL, (int)addr, SEL_NUMBER, CATEGORY_NETWORK, _PATH_NETWORKS); +} + +__private_extern__ si_list_t * +file_network_all(si_mod_t *si) +{ + return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_NETWORK, _PATH_NETWORKS); +} + +__private_extern__ si_item_t * +file_service_byname(si_mod_t *si, const char *name, const char *proto) +{ + return _fsi_get_service(si, name, proto, 0, SEL_NAME); +} + +__private_extern__ si_item_t * +file_service_byport(si_mod_t *si, int port, const char *proto) +{ + return _fsi_get_service(si, NULL, proto, port, SEL_NUMBER); +} + +__private_extern__ si_list_t * +file_service_all(si_mod_t *si) +{ + return _fsi_get_service(si, NULL, NULL, 0, SEL_ALL); +} + +__private_extern__ si_item_t * +file_protocol_byname(si_mod_t *si, const char *name) +{ + if (name == NULL) return NULL; + return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_PROTOCOL, _PATH_PROTOCOLS); +} + +__private_extern__ si_item_t * +file_protocol_bynumber(si_mod_t *si, int number) +{ + return _fsi_get_name_number_aliases(si, NULL, number, SEL_NUMBER, CATEGORY_PROTOCOL, _PATH_PROTOCOLS); +} + +__private_extern__ si_list_t * +file_protocol_all(si_mod_t *si) +{ + return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_PROTOCOL, _PATH_PROTOCOLS); +} + +__private_extern__ si_item_t * +file_rpc_byname(si_mod_t *si, const char *name) +{ + if (name == NULL) return NULL; + return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_RPC, _PATH_RPCS); +} + +__private_extern__ si_item_t * +file_rpc_bynumber(si_mod_t *si, int number) +{ + return _fsi_get_name_number_aliases(si, NULL, number, SEL_NUMBER, CATEGORY_RPC, _PATH_RPCS); +} + +__private_extern__ si_list_t * +file_rpc_all(si_mod_t *si) +{ + return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_RPC, _PATH_RPCS); +} + +__private_extern__ si_item_t * +file_fs_byspec(si_mod_t *si, const char *spec) +{ + return _fsi_get_fs(si, spec, SEL_NAME); +} + +__private_extern__ si_item_t * +file_fs_byfile(si_mod_t *si, const char *file) +{ + return _fsi_get_fs(si, file, SEL_NUMBER); +} + +__private_extern__ si_list_t * +file_fs_all(si_mod_t *si) +{ + return _fsi_get_fs(si, NULL, SEL_ALL); +} + +__private_extern__ si_item_t * +file_alias_byname(si_mod_t *si, const char *name) +{ + return _fsi_get_alias(si, name, SEL_NAME); +} + +__private_extern__ si_list_t * +file_alias_all(si_mod_t *si) +{ + return _fsi_get_alias(si, NULL, SEL_ALL); +} + +__private_extern__ si_item_t * +file_mac_byname(si_mod_t *si, const char *name) +{ + return _fsi_get_ether(si, name, SEL_NAME); +} + +__private_extern__ si_item_t * +file_mac_bymac(si_mod_t *si, const char *mac) +{ + return _fsi_get_ether(si, mac, SEL_NUMBER); +} + +__private_extern__ si_list_t * +file_mac_all(si_mod_t *si) +{ + return _fsi_get_ether(si, NULL, SEL_ALL); +} + +__private_extern__ si_mod_t * +si_module_static_file() +{ + si_mod_t *out; + char *outname; + + out = (si_mod_t *)calloc(1, sizeof(si_mod_t)); + outname = strdup("file"); + + if ((out == NULL) || (outname == NULL)) + { + if (out != NULL) free(out); + if (outname != NULL) free(outname); + + errno = ENOMEM; + return NULL; + } + + out->name = outname; + out->vers = 1; + out->refcount = 1; + + out->sim_is_valid = file_is_valid; + + out->sim_user_byname = file_user_byname; + out->sim_user_byuid = file_user_byuid; + out->sim_user_all = file_user_all; + + out->sim_group_byname = file_group_byname; + out->sim_group_bygid = file_group_bygid; + out->sim_group_all = file_group_all; + + out->sim_grouplist = file_grouplist; + + /* NETGROUP SUPPORT NOT IMPLEMENTED */ + out->sim_netgroup_byname = NULL; + out->sim_in_netgroup = NULL; + + out->sim_alias_byname = file_alias_byname; + out->sim_alias_all = file_alias_all; + + out->sim_host_byname = file_host_byname; + out->sim_host_byaddr = file_host_byaddr; + out->sim_host_all = file_host_all; + + out->sim_network_byname = file_network_byname; + out->sim_network_byaddr = file_network_byaddr; + out->sim_network_all = file_network_all; + + out->sim_service_byname = file_service_byname; + out->sim_service_byport = file_service_byport; + out->sim_service_all = file_service_all; + + out->sim_protocol_byname = file_protocol_byname; + out->sim_protocol_bynumber = file_protocol_bynumber; + out->sim_protocol_all = file_protocol_all; + + out->sim_rpc_byname = file_rpc_byname; + out->sim_rpc_bynumber = file_rpc_bynumber; + out->sim_rpc_all = file_rpc_all; + + out->sim_fs_byspec = file_fs_byspec; + out->sim_fs_byfile = file_fs_byfile; + out->sim_fs_all = file_fs_all; + + out->sim_mac_byname = file_mac_byname; + out->sim_mac_bymac = file_mac_bymac; + out->sim_mac_all = file_mac_all; + + /* no addrinfo support */ + out->sim_wants_addrinfo = NULL; + out->sim_addrinfo = NULL; + + /* no nameinfo support */ + out->sim_nameinfo = NULL; + + return out; +} diff --git a/lookup.subproj/gai_strerror.3 b/lookup.subproj/gai_strerror.3 index 5ed9474..a358d45 100644 --- a/lookup.subproj/gai_strerror.3 +++ b/lookup.subproj/gai_strerror.3 @@ -16,9 +16,9 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.\" $FreeBSD: src/lib/libc/net/gai_strerror.3,v 1.3 2005/06/16 19:01:06 ru Exp $ +.\" $FreeBSD: src/lib/libc/net/gai_strerror.3,v 1.5 2006/09/17 21:27:33 ru Exp $ .\" -.Dd December 20, 2004 +.Dd May 21, 2006 .Dt GAI_STRERROR 3 .Os .Sh NAME @@ -29,9 +29,7 @@ .In sys/socket.h .In netdb.h .Ft "const char *" -.Fo gai_strerror -.Fa "int ecode" -.Fc +.Fn gai_strerror "int ecode" .Sh DESCRIPTION The .Fn gai_strerror @@ -65,6 +63,8 @@ memory allocation failure or .Fa servname not provided, or not known +.It Dv EAI_OVERFLOW +argument buffer overflow .It Dv EAI_PROTOCOL resolved protocol is unknown .It Dv EAI_SERVICE @@ -87,16 +87,6 @@ returns a pointer to the error message string corresponding to If .Fa ecode is out of range, an implementation-specific error message string is returned. -.Sh LEGACY SYNOPSIS -.Fd #include -.Fd #include -.Fd #include -.Pp -The include files -.In sys/types.h -and -.In sys/socket.h -are necessary. .Sh SEE ALSO .Xr getaddrinfo 3 , .Xr getnameinfo 3 diff --git a/lookup.subproj/getaddrinfo.3 b/lookup.subproj/getaddrinfo.3 index b03fa0c..f068342 100644 --- a/lookup.subproj/getaddrinfo.3 +++ b/lookup.subproj/getaddrinfo.3 @@ -1,4 +1,3 @@ -.\" $NetBSD: getaddrinfo.3,v 1.39 2005/01/11 06:01:41 itojun Exp $ .\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $ .\" @@ -17,34 +16,33 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.Dd December 20, 2004 +.\" $FreeBSD: src/lib/libc/net/getaddrinfo.3,v 1.34 2008/07/01 22:59:20 danger Exp $ +.\" +.Dd July 1, 2008 .Dt GETADDRINFO 3 .Os .Sh NAME -.Nm freeaddrinfo , -.Nm getaddrinfo +.Nm getaddrinfo , +.Nm freeaddrinfo .Nd socket address structure to host and service name .Sh SYNOPSIS +.Fd #include .Fd #include .Fd #include -.Ft void -.Fo freeaddrinfo -.Fa "struct addrinfo *ai" -.Fc .Ft int .Fo getaddrinfo -.Fa "const char *restrict nodename" -.Fa "const char *restrict servname" -.Fa "const struct addrinfo *restrict hints" -.Fa "struct addrinfo **restrict res" +.Fa "const char *hostname" "const char *servname" +.Fa "const struct addrinfo *hints" "struct addrinfo **res" .Fc +.Ft void +.Fn freeaddrinfo "struct addrinfo *ai" .Sh DESCRIPTION The .Fn getaddrinfo function is used to get a list of .Tn IP addresses and port numbers for host -.Fa nodename +.Fa hostname and service .Fa servname . It is a replacement for and provides more flexibility than the @@ -54,12 +52,12 @@ and functions. .Pp The -.Fa nodename +.Fa hostname and .Fa servname arguments are either pointers to NUL-terminated strings or the null pointer. An acceptable value for -.Fa nodename +.Fa hostname is either a valid host name or a numeric host address string consisting of a dotted decimal IPv4 address or an IPv6 address. The @@ -67,7 +65,7 @@ The is either a decimal port number or a service name listed in .Xr services 5 . At least one of -.Fa nodename +.Fa hostname and .Fa servname must be non-null. @@ -121,11 +119,41 @@ If .Fa ai_protocol is zero the caller will accept any protocol. .It Fa ai_flags +The .Fa ai_flags -is formed by -.Tn OR Ns 'ing -the following values: +field to which the +.Fa hints +parameter points shall be set to zero +or be the bitwise-inclusive OR of one or more of the values +.Dv AI_ADDRCONFIG , +.Dv AI_ALL , +.Dv AI_CANONNAME , +.Dv AI_NUMERICHOST , +.Dv AI_NUMERICSERV , +.Dv AI_PASSIVE , +and +.Dv AI_V4MAPPED . .Bl -tag -width "AI_CANONNAMEXX" +.It Dv AI_ADDRCONFIG +If the +.Dv AI_ADDRCONFIG +bit is set, IPv4 addresses shall be returned only if +an IPv4 address is configured on the local system, +and IPv6 addresses shall be returned only if +an IPv6 address is configured on the local system. +.It Dv AI_ALL +If the +.Dv AI_ALL +bit is set with the +.Dv AI_V4MAPPED +bit, then +.Fn getaddrinfo +shall return all matching IPv6 and IPv4 addresses. +The +.Dv AI_ALL +bit without the +.Dv AI_V4MAPPED +bit is ignored. .It Dv AI_CANONNAME If the .Dv AI_CANONNAME @@ -141,9 +169,21 @@ structure returned. If the .Dv AI_NUMERICHOST bit is set, it indicates that -.Fa nodename +.Fa hostname should be treated as a numeric string defining an IPv4 or IPv6 address and no name resolution should be attempted. +.It Dv AI_NUMERICSERV +If the +.Dv AI_NUMERICSERV +bit is set, +then a non-null +.Fa servname +string supplied shall be a numeric port string. +Otherwise, an +.Dv EAI_NONAME +error shall be returned. +This bit shall prevent any type of name resolution service +(for example, NIS+) from being invoked. .It Dv AI_PASSIVE If the .Dv AI_PASSIVE @@ -151,7 +191,7 @@ bit is set it indicates that the returned socket address structure is intended for use in a call to .Xr bind 2 . In this case, if the -.Fa nodename +.Fa hostname argument is the null pointer, then the IP address portion of the socket address structure will be set to .Dv INADDR_ANY @@ -174,10 +214,29 @@ The .Tn IP address portion of the socket address structure will be set to the loopback address if -.Fa nodename +.Fa hostname is the null pointer and .Dv AI_PASSIVE is not set. +.It Dv AI_V4MAPPED +If the +.Dv AI_V4MAPPED +flag is specified along with an +.Fa ai_family +of +.Dv AF_INET6 , +then +.Fn getaddrinfo +shall return IPv4-mapped IPv6 addresses +on finding no matching IPv6 addresses ( +.Fa ai_addrlen +shall be 16). +The +.Dv AI_V4MAPPED +flag shall be ignored unless +.Fa ai_family +equals +.Dv AF_INET6 . .El .El .Pp @@ -384,14 +443,6 @@ if (nsock == 0) { } freeaddrinfo(res0); .Ed -.Sh LEGACY SYNOPSIS -.Fd #include -.Fd #include -.Fd #include -.Pp -The include file -.In sys/types.h -is necessary. .Sh SEE ALSO .Xr bind 2 , .Xr connect 2 , @@ -434,11 +485,23 @@ is necessary. .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re +.\".Sh BUGS +.\"The +.\".Nm +.\"function as implemented in +.\".Fx +.\"currently does not support +.\".Dv AI_ALL +.\"and +.\".Dv AI_V4MAPPED +.\"flags and returns +.\".Dv EAI_BADFLAGS +.\"if one of them is specified. .Sh STANDARDS The .Fn getaddrinfo function is defined by the -.St -p1003.1g-2000 -draft specification and documented in +.St -p1003.1-2004 +specification and documented in .Dv "RFC 3493" , .Dq Basic Socket Interface Extensions for IPv6 . diff --git a/lookup.subproj/getaddrinfo.c b/lookup.subproj/getaddrinfo.c deleted file mode 100644 index 6680f4a..0000000 --- a/lookup.subproj/getaddrinfo.c +++ /dev/null @@ -1,1733 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "netdb_async.h" - -#define SOCK_UNSPEC 0 -#define IPPROTO_UNSPEC 0 - -#define MAX_LOOKUP_ATTEMPTS 10 - -#define INET_NTOP_AF_INET_OFFSET 4 -#define INET_NTOP_AF_INET6_OFFSET 8 - -static int gai_proc = -1; -static int gni_proc = -1; - -static const int32_t supported_family[] = -{ - PF_UNSPEC, - PF_INET, - PF_INET6 -}; -static const int32_t supported_family_count = (sizeof(supported_family) / sizeof(supported_family[0])); - -static const int32_t supported_socket[] = -{ - SOCK_RAW, - SOCK_UNSPEC, - SOCK_DGRAM, - SOCK_STREAM -}; -static const int32_t supported_socket_count = (sizeof(supported_socket) / sizeof(supported_socket[0])); - -static const int32_t supported_protocol[] = -{ - IPPROTO_UNSPEC, - IPPROTO_ICMP, - IPPROTO_ICMPV6, - IPPROTO_UDP, - IPPROTO_TCP -}; -static const int32_t supported_protocol_count = (sizeof(supported_protocol) / sizeof(supported_protocol[0])); - -static const int32_t supported_socket_protocol_pair[] = -{ - SOCK_RAW, IPPROTO_UNSPEC, - SOCK_RAW, IPPROTO_UDP, - SOCK_RAW, IPPROTO_TCP, - SOCK_RAW, IPPROTO_ICMP, - SOCK_RAW, IPPROTO_ICMPV6, - SOCK_UNSPEC, IPPROTO_UNSPEC, - SOCK_UNSPEC, IPPROTO_UDP, - SOCK_UNSPEC, IPPROTO_TCP, - SOCK_UNSPEC, IPPROTO_ICMP, - SOCK_UNSPEC, IPPROTO_ICMPV6, - SOCK_DGRAM, IPPROTO_UNSPEC, - SOCK_DGRAM, IPPROTO_UDP, - SOCK_STREAM, IPPROTO_UNSPEC, - SOCK_STREAM, IPPROTO_TCP -}; -static const int32_t supported_socket_protocol_pair_count = (sizeof(supported_socket_protocol_pair) / (sizeof(supported_socket_protocol_pair[0]) * 2)); - -static int -gai_family_type_check(int32_t f) -{ - int32_t i; - - for (i = 0; i < supported_family_count; i++) - { - if (f == supported_family[i]) return 0; - } - - return 1; -} - -static int -gai_socket_type_check(int32_t s) -{ - int32_t i; - - for (i = 0; i < supported_socket_count; i++) - { - if (s == supported_socket[i]) return 0; - } - - return 1; -} - -static int -gai_protocol_type_check(int32_t p) -{ - int32_t i; - - for (i = 0; i < supported_protocol_count; i++) - { - if (p == supported_protocol[i]) return 0; - } - - return 1; -} - -static int -gai_socket_protocol_type_check(int32_t s, int32_t p) -{ - int32_t i, j, ss, sp; - - for (i = 0, j = 0; i < supported_socket_protocol_pair_count; i++, j+=2) - { - ss = supported_socket_protocol_pair[j]; - sp = supported_socket_protocol_pair[j+1]; - if ((s == ss) && (p == sp)) return 0; - } - - return 1; -} - -const char * -gai_strerror(int32_t err) -{ - switch (err) - { - case EAI_ADDRFAMILY: return "Address family for nodename not supported"; - case EAI_AGAIN: return "Temporary failure in name resolution"; - case EAI_BADFLAGS: return "Invalid value for ai_flags"; - case EAI_FAIL: return "Non-recoverable failure in name resolution"; - case EAI_FAMILY: return "ai_family not supported"; - case EAI_MEMORY: return "Memory allocation failure"; - case EAI_NODATA: return "No address associated with nodename"; - case EAI_NONAME: return "nodename nor servname provided, or not known"; - case EAI_SERVICE: return "servname not supported for ai_socktype"; - case EAI_SOCKTYPE: return "ai_socktype not supported"; - case EAI_SYSTEM: return "System error"; - case EAI_BADHINTS: return "Bad hints"; - case EAI_PROTOCOL: return "ai_protocol not supported"; - } - - return "Unknown error"; -} - -static void -append_addrinfo(struct addrinfo **l, struct addrinfo *a) -{ - struct addrinfo *x; - - if (l == NULL) return; - if (a == NULL) return; - - if (*l == NULL) - { - *l = a; - return; - } - - x = *l; - - if (a->ai_family == PF_INET6) - { - if (x->ai_family == PF_INET) - { - *l = a; - a->ai_next = x; - return; - } - - while ((x->ai_next != NULL) && (x->ai_next->ai_family != PF_INET)) x = x->ai_next; - a->ai_next = x->ai_next; - x->ai_next = a; - } - else - { - while (x->ai_next != NULL) x = x->ai_next; - a->ai_next = NULL; - x->ai_next = a; - } -} - -void -freeaddrinfo(struct addrinfo *a) -{ - struct addrinfo *next; - - while (a != NULL) - { - next = a->ai_next; - if (a->ai_addr != NULL) free(a->ai_addr); - if (a->ai_canonname != NULL) free(a->ai_canonname); - free(a); - a = next; - } -} - -static struct addrinfo * -new_addrinfo_v4(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr addr, uint32_t iface, const char *cname) -{ - struct addrinfo *a; - struct sockaddr_in *sa; - int32_t len; - - a = (struct addrinfo *)calloc(1, sizeof(struct addrinfo)); - if (a == NULL) return NULL; - - a->ai_next = NULL; - - a->ai_flags = flags; - a->ai_family = PF_INET; - a->ai_socktype = sock; - a->ai_protocol = proto; - - a->ai_addrlen = sizeof(struct sockaddr_in); - - sa = (struct sockaddr_in *)calloc(1, a->ai_addrlen); - if (sa == NULL) - { - free(a); - return NULL; - } - - sa->sin_len = a->ai_addrlen; - sa->sin_family = PF_INET; - sa->sin_port = htons(port); - sa->sin_addr = addr; - - /* Kludge: Jam the interface number into sin_zero. */ - memmove(sa->sin_zero, &iface, sizeof(uint32_t)); - - a->ai_addr = (struct sockaddr *)sa; - - if (cname != NULL) - { - len = strlen(cname) + 1; - a->ai_canonname = malloc(len); - memmove(a->ai_canonname, cname, len); - } - - return a; -} - -static struct addrinfo * -new_addrinfo_v6(int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr addr, uint16_t scopeid, const char *cname) -{ - struct addrinfo *a; - struct sockaddr_in6 *sa; - int32_t len; - uint16_t esid; - - a = (struct addrinfo *)calloc(1, sizeof(struct addrinfo)); - if (a == NULL) return NULL; - - a->ai_next = NULL; - - a->ai_flags = flags; - a->ai_family = PF_INET6; - a->ai_socktype = sock; - a->ai_protocol = proto; - - a->ai_addrlen = sizeof(struct sockaddr_in6); - - sa = (struct sockaddr_in6 *)calloc(1, a->ai_addrlen); - if (sa == NULL) - { - free(a); - return NULL; - } - - sa->sin6_len = a->ai_addrlen; - sa->sin6_family = PF_INET6; - sa->sin6_port = htons(port); - sa->sin6_addr = addr; - - /* sin6_scope_id is in host byte order */ - sa->sin6_scope_id = scopeid; - - a->ai_addr = (struct sockaddr *)sa; - - if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) - { - /* check for embedded scopeid */ - esid = ntohs(sa->sin6_addr.__u6_addr.__u6_addr16[1]); - if (esid != 0) - { - sa->sin6_addr.__u6_addr.__u6_addr16[1] = 0; - if (scopeid == 0) sa->sin6_scope_id = esid; - } - } - - if (cname != NULL) - { - len = strlen(cname) + 1; - a->ai_canonname = malloc(len); - memmove(a->ai_canonname, cname, len); - } - - return a; -} - -/* - * getaddrinfo - * - * Input dict may contain the following - * - * name: nodename - * service: servname - * protocol: [IPPROTO_UNSPEC] | IPPROTO_UDP | IPPROTO_TCP - * socktype: [SOCK_UNSPEC] | SOCK_DGRAM | SOCK_STREAM - * family: [PF_UNSPEC] | PF_INET | PF_INET6 - * canonname: [0] | 1 - * passive: [0] | 1 - * numerichost: [0] | 1 - * - * Output dictionary may contain the following - * All values are encoded as strings. - * - * flags: unsigned long - * family: unsigned long - * socktype: unsigned long - * protocol: unsigned long - * port: unsigned long - * address: char * - * scopeid: unsigned long - * canonname: char * - * - */ - -static struct addrinfo * -gai_extract(kvarray_t *in) -{ - uint32_t d, k, kcount; - uint32_t flags, family, socktype, protocol, port32; - uint16_t port, scopeid; - const char *addr, *canonname; - struct addrinfo *a; - struct in_addr a4; - struct in6_addr a6; - - flags = 0; - family = PF_UNSPEC; - socktype = SOCK_UNSPEC; - protocol = IPPROTO_UNSPEC; - port = 0; - scopeid = 0; - addr = NULL; - canonname = NULL; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "gai_flags")) - { - if (in->dict[d].vcount[k] == 0) continue; - flags = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "gai_family")) - { - if (in->dict[d].vcount[k] == 0) continue; - family = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "gai_socktype")) - { - if (in->dict[d].vcount[k] == 0) continue; - socktype = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "gai_protocol")) - { - if (in->dict[d].vcount[k] == 0) continue; - protocol = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "gai_port")) - { - if (in->dict[d].vcount[k] == 0) continue; - port32 = atoi(in->dict[d].val[k][0]); - port = port32; - } - else if (!strcmp(in->dict[d].key[k], "gai_scopeid")) - { - if (in->dict[d].vcount[k] == 0) continue; - scopeid = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "gai_address")) - { - if (in->dict[d].vcount[k] == 0) continue; - addr = in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "gai_canonname")) - { - if (in->dict[d].vcount[k] == 0) continue; - canonname = in->dict[d].val[k][0]; - } - } - - if (family == PF_UNSPEC) return NULL; - - a = NULL; - if (family == PF_INET) - { - inet_aton(addr, &a4); - a = new_addrinfo_v4(flags, socktype, protocol, port, a4, scopeid, canonname); - } - else if (family == PF_INET6) - { - inet_pton(AF_INET6, addr, &a6); - a = new_addrinfo_v6(flags, socktype, protocol, port, a6, scopeid, canonname); - } - - return a; -} - -static kvbuf_t * -gai_make_query(const char *nodename, const char *servname, const struct addrinfo *hints) -{ - int32_t flags, family, proto, socktype; - kvbuf_t *request; - char str[64], *cname; - - /* new default for SULeoDeo */ - flags = AI_PARALLEL; - family = PF_UNSPEC; - proto = IPPROTO_UNSPEC; - socktype = SOCK_UNSPEC; - cname = NULL; - - if (hints != NULL) - { - family = hints->ai_family; - if (hints->ai_flags & AI_NUMERICHOST) flags |= AI_NUMERICHOST; - if (hints->ai_flags & AI_CANONNAME) flags |= AI_CANONNAME; - if (hints->ai_flags & AI_PASSIVE) flags |= AI_PASSIVE; - - proto = hints->ai_protocol; - - if (hints->ai_socktype == SOCK_DGRAM) - { - socktype = SOCK_DGRAM; - proto = IPPROTO_UDP; - } - - if (hints->ai_socktype == SOCK_STREAM) - { - socktype = SOCK_STREAM; - proto = IPPROTO_TCP; - } - } - - request = kvbuf_new(); - if (request == NULL) - { - errno = ENOMEM; - return NULL; - } - - kvbuf_add_dict(request); - - if (nodename != NULL) - { - kvbuf_add_key(request, "name"); - kvbuf_add_val(request, nodename); - } - - if (servname != NULL) - { - kvbuf_add_key(request, "service"); - kvbuf_add_val(request, servname); - } - - if (proto != IPPROTO_UNSPEC) - { - snprintf(str, sizeof(str), "%u", proto); - kvbuf_add_key(request, "protocol"); - kvbuf_add_val(request, str); - } - - if (socktype != SOCK_UNSPEC) - { - snprintf(str, sizeof(str), "%u", socktype); - kvbuf_add_key(request, "socktype"); - kvbuf_add_val(request, str); - } - - if (family != PF_UNSPEC) - { - snprintf(str, sizeof(str), "%u", family); - kvbuf_add_key(request, "family"); - kvbuf_add_val(request, str); - } - - snprintf(str, sizeof(str), "%u", flags); - kvbuf_add_key(request, "ai_flags"); - kvbuf_add_val(request, str); - - return request; -} - -static int32_t -is_a_number(const char *s) -{ - int32_t i, len; - - if (s == NULL) return 0; - - len = strlen(s); - for (i = 0; i < len; i++) - { - if (isdigit(s[i]) == 0) return 0; - } - - return 1; -} - -static int -gai_trivial(struct in_addr *in4, struct in6_addr *in6, int16_t port, const struct addrinfo *hints, struct addrinfo **res) -{ - int32_t family, wantv4, wantv6, proto; - char *loopv4, *loopv6; - struct in_addr a4; - struct in6_addr a6; - struct addrinfo *a; - - family = PF_UNSPEC; - if (hints != NULL) family = hints->ai_family; - - wantv4 = 1; - wantv6 = 1; - - if (family == PF_INET6) wantv4 = 0; - if (family == PF_INET) wantv6 = 0; - - memset(&a4, 0, sizeof(struct in_addr)); - memset(&a6, 0, sizeof(struct in6_addr)); - - if ((in4 == NULL) && (in6 == NULL)) - { - loopv4 = "127.0.0.1"; - loopv6 = "0:0:0:0:0:0:0:1"; - - if ((hints != NULL) && ((hints->ai_flags & AI_PASSIVE) == 1)) - { - loopv4 = "0.0.0.0"; - loopv6 = "0:0:0:0:0:0:0:0"; - } - - if ((family == PF_UNSPEC) || (family == PF_INET)) - { - inet_pton(AF_INET, loopv4, &a4); - } - - if ((family == PF_UNSPEC) || (family == PF_INET6)) - { - inet_pton(AF_INET6, loopv6, &a6); - } - } - else if (in4 == NULL) - { - if (family == PF_INET) return EAI_BADHINTS; - - wantv4 = 0; - memcpy(&a6, in6, sizeof(struct in6_addr)); - } - else if (in6 == NULL) - { - if (family == PF_INET6) return EAI_BADHINTS; - - wantv6 = 0; - memcpy(&a4, in4, sizeof(struct in_addr)); - } - else - { - return EAI_NONAME; - } - - proto = IPPROTO_UNSPEC; - - if (hints != NULL) - { - proto = hints->ai_protocol; - if (proto == IPPROTO_UNSPEC) - { - if (hints->ai_socktype == SOCK_DGRAM) proto = IPPROTO_UDP; - else if (hints->ai_socktype == SOCK_STREAM) proto = IPPROTO_TCP; - } - } - - if (wantv4 == 1) - { - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) - { - a = new_addrinfo_v4(0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, NULL); - append_addrinfo(res, a); - } - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) - { - a = new_addrinfo_v4(0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, NULL); - append_addrinfo(res, a); - } - - if (proto == IPPROTO_ICMP) - { - a = new_addrinfo_v4(0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, NULL); - append_addrinfo(res, a); - } - } - - if (wantv6 == 1) - { - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) - { - a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, 0, NULL); - append_addrinfo(res, a); - } - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) - { - a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, 0, NULL); - append_addrinfo(res, a); - } - - if (proto == IPPROTO_ICMPV6) - { - a = new_addrinfo_v6(0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, 0, NULL); - append_addrinfo(res, a); - } - } - - return 0; -} - -static int -gai_files(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) -{ - int32_t i, status, numericserv, numerichost, family, proto, wantv4, wantv6, count; - uint16_t scopeid; - int16_t port; - struct servent *s; - struct hostent *h; - char *protoname, *loopv4, *loopv6; - struct in_addr a4; - struct in6_addr a6; - struct addrinfo *a; - - count = 0; - scopeid = 0; - - numericserv = 0; - if (servname != NULL) numericserv = is_a_number(servname); - - family = PF_UNSPEC; - if (hints != NULL) family = hints->ai_family; - - numerichost = 0; - - if (nodename == NULL) - { - numerichost = 1; - - loopv4 = "127.0.0.1"; - loopv6 = "0:0:0:0:0:0:0:1"; - - if ((hints != NULL) && ((hints->ai_flags & AI_PASSIVE) == 1)) - { - loopv4 = "0.0.0.0"; - loopv6 = "0:0:0:0:0:0:0:0"; - } - - if ((family == PF_UNSPEC) || (family == PF_INET)) - { - inet_pton(AF_INET, loopv4, &a4); - } - - if ((family == PF_UNSPEC) || (family == PF_INET6)) - { - inet_pton(AF_INET6, loopv6, &a6); - } - } - else - { - if ((family == PF_UNSPEC) || (family == PF_INET)) - { - status = inet_pton(AF_INET, nodename, &a4); - if (status == 1) - { - numerichost = 1; - if (family == PF_UNSPEC) family = PF_INET; - } - } - - if ((family == PF_UNSPEC) || (family == PF_INET6)) - { - status = inet_pton(AF_INET6, nodename, &a6); - if (status == 1) - { - numerichost = 1; - if (family == PF_UNSPEC) family = PF_INET6; - if ((IN6_IS_ADDR_LINKLOCAL(&a6)) && (a6.__u6_addr.__u6_addr16[1] != 0)) - { - scopeid = ntohs(a6.__u6_addr.__u6_addr16[1]); - a6.__u6_addr.__u6_addr16[1] = 0; - } - } - } - } - - wantv4 = 1; - wantv6 = 1; - if (family == PF_INET6) wantv4 = 0; - if (family == PF_INET) wantv6 = 0; - - proto = IPPROTO_UNSPEC; - protoname = NULL; - - if (hints != NULL) - { - proto = hints->ai_protocol; - if (proto == IPPROTO_UNSPEC) - { - if (hints->ai_socktype == SOCK_DGRAM) proto = IPPROTO_UDP; - else if (hints->ai_socktype == SOCK_STREAM) proto = IPPROTO_TCP; - } - } - - if (proto == IPPROTO_UDP) protoname = "udp"; - else if (proto == IPPROTO_TCP) protoname = "tcp"; - - s = NULL; - port = 0; - - if (numericserv != 0) - { - port = htons(atoi(servname)); - } - else if (servname != NULL) - { - s = getservbyname(servname, protoname); - if (s != NULL) port = s->s_port; - } - - /* new_addrinfo_v4 and new_addrinfo_v6 expect port in host byte order */ - port = ntohs(port); - - if (numerichost != 0) - { - if (wantv4 == 1) - { - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) - { - a = new_addrinfo_v4(0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, NULL); - append_addrinfo(res, a); - count++; - } - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) - { - a = new_addrinfo_v4(0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, NULL); - append_addrinfo(res, a); - count++; - } - - if (proto == IPPROTO_ICMP) - { - a = new_addrinfo_v4(0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, NULL); - append_addrinfo(res, a); - count++; - } - } - - if (wantv6 == 1) - { - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) - { - a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, scopeid, NULL); - append_addrinfo(res, a); - count++; - } - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) - { - a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, scopeid, NULL); - append_addrinfo(res, a); - count++; - } - - if (proto == IPPROTO_ICMPV6) - { - a = new_addrinfo_v6(0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, scopeid, NULL); - append_addrinfo(res, a); - count++; - } - } - - if (count == 0) return EAI_AGAIN; - return 0; - } - - if (wantv4 == 1) - { - h = gethostbyname(nodename); - if (h == NULL) return EAI_AGAIN; - - for (i = 0; h->h_addr_list[i] != 0; i++) - { - memmove((void *)&a4.s_addr, h->h_addr_list[i], h->h_length); - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) - { - a = new_addrinfo_v4(0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, NULL); - append_addrinfo(res, a); - count++; - } - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) - { - a = new_addrinfo_v4(0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, NULL); - append_addrinfo(res, a); - count++; - } - } - } - - if (wantv6 == 1) - { - h = gethostbyname2(nodename, AF_INET6); - if (h == NULL) return EAI_AGAIN; - - for (i = 0; h->h_addr_list[i] != 0; i++) - { - memmove(&(a6.__u6_addr.__u6_addr32[0]), h->h_addr_list[i], h->h_length); - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) - { - a = new_addrinfo_v6(0, SOCK_DGRAM, IPPROTO_UDP, port, a6, 0, NULL); - append_addrinfo(res, a); - count++; - } - - if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) - { - a = new_addrinfo_v6(0, SOCK_STREAM, IPPROTO_TCP, port, a6, 0, NULL); - append_addrinfo(res, a); - count++; - } - } - } - - if (count == 0) return EAI_AGAIN; - return 0; -} - -static int -ds_getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) -{ - uint32_t i; - kvbuf_t *request; - kvarray_t *reply; - char *cname; - kern_return_t status; - struct addrinfo *a; - - if (_ds_running() == 0) - { - return gai_files(nodename, servname, hints, res); - } - - if (gai_proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getaddrinfo", &gai_proc); - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - } - - request = gai_make_query(nodename, servname, hints); - if (request == NULL) return EAI_SYSTEM; - - reply = NULL; - status = LI_DSLookupQuery(gai_proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - - if (reply == NULL) return EAI_NONAME; - - cname = NULL; - for (i = 0; i < reply->count; i++) - { - a = gai_extract(reply); - if (a == NULL) continue; - if ((cname == NULL) && (a->ai_canonname != NULL)) cname = a->ai_canonname; - append_addrinfo(res, a); - } - - kvarray_free(reply); - - if ((cname != NULL) && (res != NULL) && (res[0] != NULL) && (res[0]->ai_canonname == NULL)) - { - res[0]->ai_canonname = strdup(cname); - } - - return 0; -} - -static int -gai_checkhints(const struct addrinfo *hints) -{ - if (hints == NULL) return 0; - if (hints->ai_addrlen != 0) return EAI_BADHINTS; - if (hints->ai_canonname != NULL) return EAI_BADHINTS; - if (hints->ai_addr != NULL) return EAI_BADHINTS; - if (hints->ai_next != NULL) return EAI_BADHINTS; - - /* Check for supported protocol family */ - if (gai_family_type_check(hints->ai_family) != 0) return EAI_FAMILY; - - /* Check for supported socket */ - if (gai_socket_type_check(hints->ai_socktype) != 0) return EAI_BADHINTS; - - /* Check for supported protocol */ - if (gai_protocol_type_check(hints->ai_protocol) != 0) return EAI_BADHINTS; - - /* Check that socket type is compatible with protocol */ - if (gai_socket_protocol_type_check(hints->ai_socktype, hints->ai_protocol) != 0) return EAI_BADHINTS; - - return 0; -} - -int -getaddrinfo(const char * __restrict nodename, const char * __restrict servname, const struct addrinfo * __restrict hints, struct addrinfo ** __restrict res) -{ - int32_t status, nodenull, servnull; - int32_t numericserv, numerichost, family; - int16_t port; - struct in_addr a4, *p4; - struct in6_addr a6, *p6; - - if (res == NULL) return 0; - *res = NULL; - - /* Check input */ - nodenull = 0; - if ((nodename == NULL) || (nodename[0] == '\0')) nodenull = 1; - - servnull = 0; - if ((servname == NULL) || (servname[0] == '\0')) servnull = 1; - - if ((nodenull == 1) && (servnull == 1)) return EAI_NONAME; - - status = gai_checkhints(hints); - if (status != 0) return status; - - /* - * Trap the "trivial" cases that can be answered without a query. - * (nodename == numeric) && (servname == NULL) - * (nodename == numeric) && (servname == numeric) - * (nodename == NULL) && (servname == numeric) - */ - p4 = NULL; - p6 = NULL; - - memset(&a4, 0, sizeof(struct in_addr)); - memset(&a6, 0, sizeof(struct in6_addr)); - - numericserv = 0; - port = 0; - if (servnull == 0) numericserv = is_a_number(servname); - if (numericserv == 1) port = atoi(servname); - - family = PF_UNSPEC; - if (hints != NULL) family = hints->ai_family; - - numerichost = 0; - if (nodenull == 0) - { - if ((family == PF_UNSPEC) || (family == PF_INET)) - { - status = inet_pton(AF_INET, nodename, &a4); - if (status == 1) - { - p4 = &a4; - numerichost = 1; - } - } - - if ((family == PF_UNSPEC) || (family == PF_INET6)) - { - status = inet_pton(AF_INET6, nodename, &a6); - if (status == 1) - { - p6 = &a6; - numerichost = 1; - } - } - } - - if ((nodenull == 1) && (numericserv == 1)) return gai_trivial(NULL, NULL, port, hints, res); - if ((numerichost == 1) && (numericserv == 1)) return gai_trivial(p4, p6, port, hints, res); - if ((numerichost == 1) && (servnull == 1)) return gai_trivial(p4, p6, 0, hints, res); - - if (nodenull == 1) status = ds_getaddrinfo(NULL, servname, hints, res); - else if (servnull == 1) status = ds_getaddrinfo(nodename, NULL, hints, res); - else status = ds_getaddrinfo(nodename, servname, hints, res); - - if ((status == 0) && (*res == NULL)) status = EAI_NONAME; - - return status; -} - -int32_t -getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, getaddrinfo_async_callback callback, void *context) -{ - int32_t status; - kvbuf_t *request; - - *p = MACH_PORT_NULL; - - if ((nodename == NULL) && (servname == NULL)) return EAI_NONAME; - - status = gai_checkhints(hints); - if (status != 0) return EAI_BADHINTS; - - if (gai_proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getaddrinfo", &gai_proc); - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - } - - request = gai_make_query(nodename, servname, hints); - if (request == NULL) return EAI_SYSTEM; - - status = LI_async_start(p, gai_proc, request, (void *)callback, context); - - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - - return 0; -} - -void -getaddrinfo_async_cancel(mach_port_t p) -{ - LI_async_call_cancel(p, NULL); -} - -int32_t -getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints) -{ - return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL); -} - -int32_t -getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res) -{ - kern_return_t status; - char *cname; - kvarray_t *reply; - uint32_t i; - struct addrinfo *a; - - if (res == NULL) return 0; - *res = NULL; - - reply = NULL; - - status = LI_async_receive(p, &reply); - if (status < 0) return EAI_FAIL; - if (reply == NULL) return EAI_NONAME; - - cname = NULL; - for (i = 0; i < reply->count; i++) - { - a = gai_extract(reply); - if (a == NULL) continue; - if ((cname == NULL) && (a->ai_canonname != NULL)) cname = a->ai_canonname; - append_addrinfo(res, a); - } - - kvarray_free(reply); - - if ((cname != NULL) && (res != NULL) && (res[0] != NULL) && (res[0]->ai_canonname == NULL)) - { - res[0]->ai_canonname = strdup(cname); - } - - - if (*res == NULL) return EAI_NONAME; - - return 0; -} - -int32_t -getaddrinfo_async_handle_reply(void *msg) -{ - getaddrinfo_async_callback callback; - void *context; - char *buf, *cname; - uint32_t i, len; - int status; - kvarray_t *reply; - struct addrinfo *l, *a, **res; - - callback = (getaddrinfo_async_callback)NULL; - context = NULL; - buf = NULL; - len = 0; - reply = NULL; - l = NULL; - res = &l; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, &context); - if (status != KERN_SUCCESS) - { - if (status == MIG_REPLY_MISMATCH) return 0; - if (callback != NULL) callback(EAI_FAIL, NULL, context); - return EAI_FAIL; - } - - if (reply == NULL) - { - if (callback != NULL) callback(EAI_NONAME, NULL, context); - return EAI_NONAME; - } - - cname = NULL; - for (i = 0; i < reply->count; i++) - { - a = gai_extract(reply); - if (a == NULL) continue; - if ((cname == NULL) && (a->ai_canonname != NULL)) cname = a->ai_canonname; - append_addrinfo(res, a); - } - - kvarray_free(reply); - - if ((cname != NULL) && (res[0] != NULL) && (res[0]->ai_canonname == NULL)) - { - res[0]->ai_canonname = strdup(cname); - } - - if (*res == NULL) - { - callback(EAI_NONAME, NULL, context); - return EAI_NONAME; - } - - callback(0, *res, context); - return 0; -} - -/* - * getnameinfo - */ - -/* - * getnameinfo support in Directory Service - * Input dict may contain the following - * - * ip_address: node address - * ipv6_address: node address - * port: service number - * protocol: [tcp] | udp - * fqdn: [1] | 0 - * numerichost: [0] | 1 - * name_required: [0] | 1 - * numericserv: [0] | 1 - * - * Output dictionary may contain the following - * All values are encoded as strings. - * - * name: char * - * service: char * - */ - -static int -gni_extract(kvarray_t *in, const char **host, const char **serv) -{ - uint32_t d, k, kcount; - - if (in == NULL) return -1; - - if ((host == NULL) || (serv == NULL)) - { - errno = EINVAL; - return EAI_SYSTEM; - } - - *host = NULL; - *serv = NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return EAI_NONAME; - - kcount = in->dict[d].kcount; - if (kcount == 0) return EAI_NONAME; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "gni_name")) - { - if (in->dict[d].vcount[k] == 0) continue; - if (*host != NULL) continue; - - *host = in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "gni_service")) - { - if (in->dict[d].vcount[k] == 0) continue; - if (*serv != NULL) continue; - - *serv = in->dict[d].val[k][0]; - } - } - - if ((*host == NULL) && (*serv == NULL)) return EAI_NONAME; - return 0; -} - -static kvbuf_t * -gni_make_query(const struct sockaddr *sa, size_t salen, int wanthost, int wantserv, int flags) -{ - kvbuf_t *request; - uint16_t port, ifnum; - char str[NI_MAXHOST], ifname[IF_NAMESIZE], tmp[64]; - uint32_t a4, offset, isll; - struct sockaddr_in6 *s6; - - if (sa == NULL) - { - errno = EINVAL; - return NULL; - } - - if (sa->sa_len != salen) - { - errno = EINVAL; - return NULL; - } - - isll = 0; - - offset = INET_NTOP_AF_INET_OFFSET; - port = 0; - - if (sa->sa_family == PF_INET) - { - a4 = ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr); - if (IN_MULTICAST(a4) || IN_EXPERIMENTAL(a4)) flags |= NI_NUMERICHOST; - a4 >>= IN_CLASSA_NSHIFT; - if (a4 == 0) flags |= NI_NUMERICHOST; - - port = ntohs(((struct sockaddr_in *)sa)->sin_port); - } - else if (sa->sa_family == PF_INET6) - { - s6 = (struct sockaddr_in6 *)sa; - switch (s6->sin6_addr.s6_addr[0]) - { - case 0x00: - { - if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) - { - } - else if (IN6_IS_ADDR_LOOPBACK(&s6->sin6_addr)) - { - } - else - { - flags |= NI_NUMERICHOST; - } - break; - } - default: - { - if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) - { - isll = 1; - } - else if (IN6_IS_ADDR_MULTICAST(&s6->sin6_addr)) - { - flags |= NI_NUMERICHOST; - } - break; - } - } - - if (isll != 0) - { - ifnum = ntohs(s6->sin6_addr.__u6_addr.__u6_addr16[1]); - if (ifnum == 0) ifnum = s6->sin6_scope_id; - else if ((s6->sin6_scope_id != 0) && (ifnum != s6->sin6_scope_id)) - { - errno = EINVAL; - return NULL; - } - - s6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; - s6->sin6_scope_id = ifnum; - if ((ifnum != 0) && (flags & NI_NUMERICHOST)) flags |= NI_WITHSCOPEID; - } - - offset = INET_NTOP_AF_INET6_OFFSET; - port = ntohs(s6->sin6_port); - } - else - { - errno = EPFNOSUPPORT; - return NULL; - } - - request = kvbuf_new(); - if (request == NULL) - { - errno = ENOMEM; - return NULL; - } - - kvbuf_add_dict(request); - - if (wanthost != 0) - { - inet_ntop(sa->sa_family, (char *)(sa) + offset, str, NI_MAXHOST); - - if (isll != 0) - { - ifnum = ((struct sockaddr_in6 *)sa)->sin6_scope_id; - if ((ifnum != 0) && (if_indextoname(ifnum, ifname) != NULL)) - { - strcat(str, "%"); - strcat(str, ifname); - } - } - - kvbuf_add_key(request, "address"); - kvbuf_add_val(request, str); - - kvbuf_add_key(request, "family"); - snprintf(tmp, sizeof(tmp), "%u", sa->sa_family); - kvbuf_add_val(request, tmp); - } - - if (wantserv != 0) - { - snprintf(tmp, sizeof(tmp), "%hu", port); - kvbuf_add_key(request, "port"); - kvbuf_add_val(request, tmp); - } - - snprintf(tmp, sizeof(tmp), "%u", flags); - kvbuf_add_key(request, "flags"); - kvbuf_add_val(request, tmp); - - return request; -} - -int -getnameinfo(const struct sockaddr * __restrict sa, socklen_t salen, char * __restrict host, socklen_t hostlen, char * __restrict serv, socklen_t servlen, int flags) -{ - uint32_t n, i, ifnum; - int wanth, wants, isll; - kvbuf_t *request; - kvarray_t *reply; - char ifname[IF_NAMESIZE]; - const char *hval, *sval; - kern_return_t status; - struct sockaddr_in *s4, s4buf; - struct sockaddr_in6 *s6, s6buf; - struct in_addr *a4; - struct in6_addr *a6; - - /* Check input */ - if (sa == NULL) return EAI_FAIL; - - isll = 0; - ifnum = 0; - - s4 = &s4buf; - a4 = NULL; - - s6 = &s6buf; - a6 = NULL; - - if (sa->sa_family == AF_INET) - { - memcpy(s4, sa, sizeof(struct sockaddr_in)); - a4 = &(s4->sin_addr); - } - else if (sa->sa_family == AF_INET6) - { - memcpy(s6, sa, sizeof(struct sockaddr_in6)); - a6 = &(s6->sin6_addr); - - if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) isll = 1; - - /* - * Link-local IPv6 addresses may have a scope id - * in s6->sin6_addr.__u6_addr.__u6_addr16[1] as well as in s6->sin6_scope_id. - * If they are both non-zero, they must be equal. - * We zero s6->sin6_addr.__u6_addr.__u6_addr16[1] and set s6->sin6_scope_id. - */ - if (isll != 0) - { - ifnum = ntohs(s6->sin6_addr.__u6_addr.__u6_addr16[1]); - if (ifnum == 0) ifnum = s6->sin6_scope_id; - else if ((s6->sin6_scope_id != 0) && (ifnum != s6->sin6_scope_id)) return EAI_FAIL; - - s6->sin6_addr.__u6_addr.__u6_addr16[1] = 0; - s6->sin6_scope_id = ifnum; - } - - /* V4 mapped and compat addresses are converted to plain V4 */ - if ((IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) || (IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr))) - { - memset(s4, 0, sizeof(struct sockaddr_in)); - - s4->sin_len = sizeof(struct sockaddr_in); - s4->sin_family = AF_INET; - s4->sin_port = s6->sin6_port; - memcpy(&(s4->sin_addr.s_addr), &(s6->sin6_addr.s6_addr[12]), 4); - - return getnameinfo((const struct sockaddr *)s4, s4->sin_len, host, hostlen, serv, servlen, flags); - } - } - else return EAI_FAMILY; - - wanth = 0; - if ((host != NULL) && (hostlen != 0)) wanth = 1; - - wants = 0; - if ((serv != NULL) && (servlen != 0)) wants = 1; - - if ((wanth == 0) && (wants == 0)) return 0; - - /* - * Special cases handled by the library - */ - if ((wanth == 1) && (flags & NI_NUMERICHOST)) - { - if (sa->sa_family == AF_INET) - { - if (inet_ntop(AF_INET, a4, host, hostlen) == NULL) return EAI_FAIL; - } - else - { - if (inet_ntop(AF_INET6, a6, host, hostlen) == NULL) return EAI_FAIL; - } - - if ((isll != 0) && (ifnum != 0)) - { - /* append interface name */ - if (if_indextoname(ifnum, ifname) != NULL) - { - strcat(host, "%"); - strcat(host, ifname); - } - } - - if (wants == 0) return 0; - } - - if ((wants == 1) && (flags & NI_NUMERICSERV)) - { - if (sa->sa_family == PF_INET) - { - n = snprintf(serv, servlen, "%hu", ntohs(s4->sin_port)); - if (n >= servlen) return EAI_FAIL; - } - else - { - n = snprintf(serv, servlen, "%hu", ntohs(s6->sin6_port)); - if (n >= servlen) return EAI_FAIL; - } - - if (wanth == 0) return 0; - } - - if ((wanth == 1) && (flags & NI_NUMERICHOST) && (wants == 1) && (flags & NI_NUMERICSERV)) return 0; - - if (_ds_running() == 0) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - - if (gni_proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getnameinfo", &gni_proc); - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - } - - request = gni_make_query(sa, salen, wanth, wants, flags); - if (request == NULL) return EAI_SYSTEM; - - reply = NULL; - status = LI_DSLookupQuery(gni_proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - - if (reply == NULL) return EAI_NONAME; - - hval = NULL; - sval = NULL; - - status = gni_extract(reply, &hval, &sval); - - if (status != 0) - { - kvarray_free(reply); - return status; - } - - i = 0; - if (hval != NULL) i = strlen(hval) + 1; - if ((host != NULL) && (hostlen != 0) && (i != 0)) - { - if (i > hostlen) - { - kvarray_free(reply); - return EAI_FAIL; - } - - memcpy(host, hval, i); - } - - i = 0; - if (sval != NULL) i = strlen(sval) + 1; - if ((serv != NULL) && (servlen != 0) && (i != 0)) - { - if (i > servlen) - { - kvarray_free(reply); - return EAI_FAIL; - } - - memcpy(serv, sval, i); - } - - kvarray_free(reply); - return 0; -} - -int32_t -getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, getnameinfo_async_callback callback, void *context) -{ - int32_t status; - kvbuf_t *request; - - *p = MACH_PORT_NULL; - - /* Check input */ - if (sa == NULL) return EAI_FAIL; - - if (gni_proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getnameinfo", &gni_proc); - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - } - - request = gni_make_query(sa, salen, 1, 1, flags); - if (request == NULL) return EAI_SYSTEM; - - status = LI_async_start(p, gni_proc, request, (void *)callback, context); - - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - errno = ECONNREFUSED; - return EAI_SYSTEM; - } - - return 0; -} - -void -getnameinfo_async_cancel(mach_port_t p) -{ - LI_async_call_cancel(p, NULL); -} - -int32_t -getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags) -{ - return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL); -} - -int32_t -getnameinfo_async_receive(mach_port_t p, char **host, char **serv) -{ - kern_return_t status; - const char *hval, *sval; - kvarray_t *reply; - - reply = NULL; - - status = LI_async_receive(p, &reply); - if (status < 0) return EAI_FAIL; - if (reply == NULL) return EAI_NONAME; - - hval = NULL; - sval = NULL; - - status = gni_extract(reply, &hval, &sval); - if (status != 0) - { - kvarray_free(reply); - return status; - } - - if (hval != NULL) *host = strdup(hval); - if (sval != NULL) *serv = strdup(sval); - - kvarray_free(reply); - return 0; -} - -int32_t -getnameinfo_async_handle_reply(void *msg) -{ - getnameinfo_async_callback callback; - void *context; - const char *hval, *sval; - char *host, *serv; - uint32_t len; - int status; - kvarray_t *reply; - - callback = (getnameinfo_async_callback)NULL; - context = NULL; - reply = NULL; - len = 0; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, &context); - if ((status != KERN_SUCCESS) || (reply == NULL)) - { - if (status == MIG_REPLY_MISMATCH) return 0; - if (callback != NULL) callback(EAI_NONAME, NULL, NULL, context); - return EAI_NONAME; - } - - hval = NULL; - sval = NULL; - - status = gni_extract(reply, &hval, &sval); - if (status != 0) - { - if (callback != NULL) callback(status, NULL, NULL, context); - kvarray_free(reply); - return status; - } - - host = NULL; - serv = NULL; - - if (hval != NULL) host = strdup(hval); - if (sval != NULL) serv = strdup(sval); - kvarray_free(reply); - - callback(0, host, serv, context); - return 0; -} diff --git a/lookup.subproj/getfsent.3 b/lookup.subproj/getfsent.3 index a898b04..299267b 100644 --- a/lookup.subproj/getfsent.3 +++ b/lookup.subproj/getfsent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,9 +26,9 @@ .\" SUCH DAMAGE. .\" .\" @(#)getfsent.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/gen/getfsent.3,v 1.9 2001/10/01 16:08:51 ru Exp $ +.\" $FreeBSD: src/lib/libc/gen/getfsent.3,v 1.17 2007/01/09 00:27:53 imp Exp $ .\" -.Dd June 4, 1993 +.Dd April 7, 2003 .Dt GETFSENT 3 .Os .Sh NAME @@ -46,16 +42,20 @@ .Lb libc .Sh SYNOPSIS .In fstab.h -.Ft struct fstab * +.Ft "struct fstab *" .Fn getfsent void -.Ft struct fstab * +.Ft "struct fstab *" .Fn getfsspec "const char *spec" -.Ft struct fstab * +.Ft "struct fstab *" .Fn getfsfile "const char *file" .Ft int .Fn setfsent void .Ft void .Fn endfsent void +.\".Ft void +.\".Fn setfstab "const char *file" +.\".Ft "const char *" +.\".Fn getfstab void .Sh DESCRIPTION The .Fn getfsent , @@ -66,7 +66,7 @@ functions each return a pointer to an object with the following structure containing the broken-out fields of a line in the file system description file, -.Aq Pa fstab.h . +.In fstab.h . .Bd -literal -offset indent struct fstab { char *fs_spec; /* block special device name */ @@ -92,6 +92,18 @@ The .Fn endfsent function closes the file. +.\".Pp +.\"The +.\".Fn setfstab +.\"function sets the file to be used by subsequent operations. +.\"The value set by +.\".Fn setfstab +.\"does not persist across calls to +.\".Fn endfsent . +.\".Pp +.\"The +.\".Fn getfstab +.\"function returns the name of the file that will be used. .Pp The .Fn getfsspec @@ -128,6 +140,20 @@ The .Fn endfsent function returns nothing. +.\".Sh ENVIRONMENT +.\".Bl -tag -width ".Ev PATH_FSTAB" +.\".It Ev PATH_FSTAB +.\"If the environment variable +.\".Ev PATH_FSTAB +.\"is set, all operations are performed against the specified file. +.\".Ev PATH_FSTAB +.\"will not be honored if the process environment or memory address space is +.\"considered +.\".Dq tainted . +.\"(See +.\".Xr issetugid 2 +.\"for more information.) +.\".El .Sh FILES .Bl -tag -width /etc/fstab -compact .It Pa /etc/fstab @@ -147,7 +173,17 @@ and .Fn setfsent functions appeared in .Bx 4.3 . +.\".Bx 4.3 ; +.\"the +.\".Fn setfstab +.\"and +.\".Fn getfstab +.\"functions appeared in +.\".Fx 5.1 . .Sh BUGS -These functions use static data storage; -if the data is needed for future use, it should be -copied before any subsequent calls overwrite it. +The data space used by +these functions is thread-specific; if future use requires the data, it should be +copied before any subsequent calls to these functions overwrite it. +.\"These functions use static data storage; +.\"if the data is needed for future use, it should be +.\"copied before any subsequent calls overwrite it. diff --git a/lookup.subproj/getgrent.3 b/lookup.subproj/getgrent.3 index c4c212c..2a95a2d 100644 --- a/lookup.subproj/getgrent.3 +++ b/lookup.subproj/getgrent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,84 +26,63 @@ .\" SUCH DAMAGE. .\" .\" From: @(#)getgrent.3 8.2 (Berkeley) 4/19/94 -.\" $FreeBSD: src/lib/libc/gen/getgrent.3,v 1.16 2001/10/01 16:08:51 ru Exp $ +.\" $FreeBSD: src/lib/libc/gen/getgrent.3,v 1.28 2007/01/09 00:27:53 imp Exp $ .\" -.Dd September 29, 1994 +.Dd April 16, 2003 .Dt GETGRENT 3 .Os .Sh NAME -.Nm endgrent , .Nm getgrent , -.Nm getgrgid , -.Nm getgrgid_r , +.\".Nm getgrent_r , .Nm getgrnam , .Nm getgrnam_r , +.Nm getgrgid , +.Nm getgrgid_r , +.Nm setgroupent , .Nm setgrent , -.\" .Nm setgrfile , -.Nm setgroupent +.Nm endgrent .Nd group database operations .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In grp.h -.Ft void -.Fo endgrent -.Fa void -.Fc .Ft struct group * -.Fo getgrent -.Fa void -.Fc +.Fn getgrent void +.\".Ft int +.\".Fn getgrent_r "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result" .Ft struct group * -.Fo getgrgid -.Fa "gid_t gid" -.Fc +.Fn getgrnam "const char *name" .Ft int -.Fo getgrgid_r -.Fa "gid_t gid" -.Fa "struct group *grp" -.Fa "char *buffer" -.Fa "size_t bufsize" -.Fa "struct group **result" -.Fc +.Fn getgrnam_r "const char *name" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result" .Ft struct group * -.Fo getgrnam -.Fa "const char *name" -.Fc +.Fn getgrgid "gid_t gid" .Ft int -.Fo getgrnam_r -.Fa "const char *name" -.Fa "struct group *grp" -.Fa "char *buffer" -.Fa "size_t bufsize" -.Fa "struct group **result" -.Fc -.Ft void -.Fo setgrent -.Fa void -.Fc -.\" .Ft void -.\" .Fn setgrfile "const char *name" +.Fn getgrgid_r "gid_t gid" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result" +.Ft int +.Fn setgroupent "int stayopen" .Ft int -.Fo setgroupent -.Fa "int stayopen" -.Fc +.Fn setgrent void +.Ft void +.Fn endgrent void .Sh DESCRIPTION -These functions operate on the group database file -.Pa /etc/group , +.\"These functions operate on the group database file +These functions obtain information from +.Xr DirectoryService 8 , +including records in +.Pa /etc/group which is described in .Xr group 5 . Each line of the database is defined by the structure -.Ar group , +.Vt group found in the include file -.Aq Pa grp.h : +.In grp.h : .Bd -literal -offset indent struct group { char *gr_name; /* group name */ char *gr_passwd; /* group password */ - int gr_gid; /* group id */ + gid_t gr_gid; /* group id */ char **gr_mem; /* group members */ }; .Ed @@ -116,65 +91,72 @@ The functions .Fn getgrnam and .Fn getgrgid -search the group database for the given group name (pointed to by -.Ar name ) -or the group id (pointed to by -.Ar gid ) , -respectively, returning the first one encountered. Identical group -names or group ids may result in undefined behavior. +search the group database for the given group name pointed to by +.Fa name +or the group id pointed to by +.Fa gid , +respectively, returning the first one encountered. +Identical group +names or group gids may result in undefined behavior. +.Pp +On Mac OS X, these routines are thread-safe and return a pointer to a +thread-specific data structure. The contents of this data +structure are automatically released by subsequent calls to +any of these routines on the same thread, or when the thread exits. .Pp -All of these routines are thread-safe. The -.Fn getgrent , -.Fn getgrgid , -and -.Fn getgrnam -routines return a pointer to a result managed by the system library in a -thread-specific data structure. -Every thread has space for a pointer to a struct group and allocates its own storage for the result. -Neither previously returned values in memory nor a previously returned pointer value should be used -by a thread after calling any one of these three routines. -Memory allocated by a thread is automatically released on subsequent calls by the same thread to any of these -three routines, and when the thread exits. +.Fn getgrent +function +sequentially reads the group database and is intended for programs +that wish to step through the complete list of groups. .Pp The functions +.\".Fn getgrent_r , +.\".Fn getgrnam_r , +.Fn getgrnam_r +and .Fn getgrgid_r +are thread-safe versions of +.\".Fn getgrent , +.\".Fn getgrnam , +.Fn getgrnam and -.Fn getgrnam_r -take additional arguments which supply storage space for the returned result. -The -.Fa grp -parameter is a pointer to a struct group, which must be allocated by the caller. -The -.Fa buffer -parameter is a pointer to a block of memory with a size specified by -.Pa bufsize . -This buffer is used to hold the values which are pointed to by values filled in +.Fn getgrgid , +respectively. +The caller must provide storage for the results of the search in the +.Fa grp , +.Fa buffer , +.Fa bufsize , +and +.Fa result +arguments. +When these functions are successful, the .Fa grp -structure. -Zero is returned on success. -If insufficient memory is supplied, these routines return ERANGE. +argument will be filled-in, and a pointer to that argument will be +stored in +.Fa result . +If an entry is not found or an error occurs, +.Fa result +will be set to +.Dv NULL . .Pp -The -.Fn getgrent -function -sequentially reads the group database and is intended for programs -that wish to step through the complete list of groups. -.Pp -All three routines will open the group file for reading, if necessary. +These functions will open the group file for reading, if necessary. .Pp The .Fn setgroupent function -opens the file, or rewinds it if it is already open. If +opens the file, or rewinds it if it is already open. +If .Fa stayopen is non-zero, file descriptors are left open, significantly speeding -functions' subsequent calls. This functionality is unnecessary for -.Fn getgrent , -as it doesn't close its file descriptors by default. It should also +functions subsequent calls. +This functionality is unnecessary for +.Fn getgrent +as it does not close its file descriptors by default. +It should also be noted that it is dangerous for long-running programs to use this -functionality, as the group file may be updated. +functionality as the group file may be updated. .Pp The .Fn setgrent @@ -190,18 +172,41 @@ closes any open files. .Sh RETURN VALUES The functions .Fn getgrent , +.Fn getgrnam , +and .Fn getgrgid , +return a pointer to a group structure on success or +.Dv NULL +if the entry is not found or if an error occurs. +If an error does occur, +.Va errno +will be set. +Note that programs must explicitly set +.Va errno +to zero before calling any of these functions if they need to +distinguish between a non-existent entry and an error. +The functions +.\".Fn getgrent_r , +.\".Fn getgrnam_r , +.Fn getgrnam_r and -.Fn getgrnam -each return a pointer to the group entry if successful; if end-of-file -is reached or an error occurs, a null pointer is returned. -The function +.Fn getgrgid_r +return 0 if no error occurred, or an error number to indicate failure. +It is not an error if a matching entry is not found. +(Thus, if +.Fa result +is set to +.Dv NULL +and the return value is 0, no matching entry exists.) +.Pp +The functions .Fn setgroupent -returns the value 1 if successful; -otherwise, the value 0 is returned. +and +.Fn setgrent +return the value 1 if successful, otherwise the value +0 is returned. The functions -.Fn endgrent , -.Fn setgrent , +.Fn endgrent and .Fn setgrfile have no return value. @@ -210,23 +215,34 @@ have no return value. .It Pa /etc/group group database file .El -.Sh LEGACY SYNOPSIS -.Fd #include -.Pp -.Ft int -.br -.Fo setgrent -.Fa void -.Fc ; -.Pp -The function -.Fn setgrent -returns the value 1 if successful; -otherwise, the value 0 is returned. +.Sh COMPATIBILITY +The historic function +.Fn setgrfile , +which allowed the specification of alternate password databases, has +been deprecated and is no longer available. .Sh SEE ALSO .Xr getpwent 3 , -.Xr yp 8 , -.Xr group 5 +.Xr group 5 , +.\".Xr nsswitch.conf 5 , +.Xr DirectoryService 8 , +.Xr yp 8 +.Sh STANDARDS +The +.Fn getgrent , +.Fn getgrnam , +.Fn getgrnam_r , +.Fn getgrgid , +.Fn getgrgid_r +and +.Fn endgrent +functions conform to +.St -p1003.1-96 . +The +.Fn setgrent +function differs from that standard in that its return type is +.Vt int +rather than +.Vt void . .Sh HISTORY The functions .Fn endgrent , @@ -243,18 +259,42 @@ and .Fn setgroupent appeared in .Bx 4.3 Reno . -.Sh COMPATIBILITY -The historic function -.Fn setgrfile , -which allowed the specification of alternate password databases, has -been deprecated and is no longer available. +The functions +.\".Fn getgrent_r , +.\".Fn getgrnam_r , +.Fn getgrnam_r +and +.Fn getgrgid_r +appeared in +.Fx 5.1 . .Sh BUGS The functions .Fn getgrent , .Fn getgrnam , -and .Fn getgrgid , -leave their results in internal thread-specific memory and return +.Fn setgroupent +and +.Fn setgrent +leave their results in an internal thread-specific memory and return a pointer to that object. -Subsequent calls to any of these three routines by the same thread will -release the object and return a new pointer value. +Subsequent calls to +the same function +will modify the same object. +.\".Pp +.\"The functions +.\".Fn getgrent , +.\".Fn getgrent_r , +.\".Fn endgrent , +.\".Fn setgroupent , +.\"and +.\".Fn setgrent +.\"are fairly useless in a networked environment and should be +.\"avoided, if possible. +.\"The +.\".Fn getgrent +.\"and +.\".Fn getgrent_r +.\"functions +.\"make no attempt to suppress duplicate information if multiple +.\"sources are specified in +.\".Xr nsswitch.conf 5 . diff --git a/lookup.subproj/getgrouplist.3 b/lookup.subproj/getgrouplist.3 index 28364eb..fa62c54 100644 --- a/lookup.subproj/getgrouplist.3 +++ b/lookup.subproj/getgrouplist.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)getgrouplist.3 8.1 (Berkeley) 6/9/93 -.\" $FreeBSD: src/lib/libc/gen/getgrouplist.3,v 1.7 2001/10/01 16:08:51 ru Exp $ +.\" $FreeBSD: src/lib/libc/gen/getgrouplist.3,v 1.9 2007/01/09 00:27:53 imp Exp $ .\" .Dd June 9, 1993 .Dt GETGROUPLIST 3 @@ -44,6 +40,7 @@ .In unistd.h .Ft int .Fn getgrouplist "const char *name" "int basegid" "int *groups" "int *ngroups" +.\".Fn getgrouplist "const char *name" "gid_t basegid" "gid_t *groups" "int *ngroups" .Sh DESCRIPTION The .Fn getgrouplist @@ -56,7 +53,7 @@ is automatically included in the groups list. Typically this value is given as the group number from the password file. .Pp -The resulting group list is returned in the integer array pointed to by +The resulting group list is returned in the array pointed to by .Fa groups . The caller specifies the size of the .Fa groups diff --git a/lookup.subproj/getnameinfo.3 b/lookup.subproj/getnameinfo.3 index 8b0e939..a121a45 100644 --- a/lookup.subproj/getnameinfo.3 +++ b/lookup.subproj/getnameinfo.3 @@ -1,4 +1,3 @@ -.\" $NetBSD: getnameinfo.3,v 1.34 2005/01/12 14:44:11 wiz Exp $ .\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $ .\" $OpenBSD: getnameinfo.3,v 1.36 2004/12/21 09:48:20 jmc Exp $ .\" @@ -17,24 +16,23 @@ .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR .\" PERFORMANCE OF THIS SOFTWARE. .\" -.Dd December 20, 2004 +.\" $FreeBSD: src/lib/libc/net/getnameinfo.3,v 1.25 2007/02/28 21:28:33 bms Exp $ +.\" +.Dd February 28, 2007 .Dt GETNAMEINFO 3 .Os .Sh NAME .Nm getnameinfo .Nd socket address structure to hostname and service name .Sh SYNOPSIS -.In sys/socket.h -.In netdb.h +.Fd #include +.Fd #include +.Fd #include .Ft int .Fo getnameinfo -.Fa "const struct sockaddr *restrict sa" -.Fa "socklen_t salen" -.Fa "char *restrict node" -.Fa "socklen_t nodelen" -.Fa "char *restrict service" -.Fa "socklen_t servicelen" -.Fa "int flags" +.Fa "const struct sockaddr *sa" "socklen_t salen" "char *host" +.Fa "socklen_t hostlen" "char *serv" "socklen_t servlen" "int flags" +.\".Fa "size_t hostlen" "char *serv" "size_t servlen" "int flags" .Fc .Sh DESCRIPTION The @@ -49,12 +47,30 @@ and functions and is the converse of the .Xr getaddrinfo 3 function. +.\".Pp +.\"If a link-layer address is passed to +.\".Fn getnameinfo , +.\"its ASCII representation will be stored in +.\".Fa host . +.\"The string pointed to by +.\".Fa serv +.\"will be set to the empty string if non-NULL; +.\".Fa flags +.\"will always be ignored. +.\"This is intended as a replacement for the legacy +.\".Xr link_ntoa 3 +.\"function. .Pp The .Li sockaddr structure .Fa sa should point to either a +.\".Li sockaddr_in , +.\".Li sockaddr_in6 +.\"or +.\".Li sockaddr_dl +.\"structure (for IPv4, IPv6 or link-layer respectively) that is .Li sockaddr_in or .Li sockaddr_in6 @@ -65,19 +81,20 @@ bytes long. The host and service names associated with .Fa sa are stored in -.Fa node +.Fa host and -.Fa service +.Fa serv which have length parameters -.Fa nodelen +.Fa hostlen and -.Fa servicelen . +.Fa servlen . The maximum value for -.Fa nodelen +.Fa hostlen is .Dv NI_MAXHOST -and the maximum value for -.Fa servicelen +and +the maximum value for +.Fa servlen is .Dv NI_MAXSERV , as defined by @@ -89,7 +106,7 @@ host name or service string plus a byte for the NUL terminator. The .Fa flags argument is formed by -.Sy OR Ns 'ing +.Tn OR Ns 'ing the following values: .Bl -tag -width "NI_NUMERICHOSTXX" .It Dv NI_NOFQDN @@ -142,7 +159,7 @@ Observe that there is no hardcoded reference to a particular address family. struct sockaddr *sa; /* input */ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; -if (getnameinfo(sa, sa-\*[Gt]sa_len, hbuf, sizeof(hbuf), sbuf, +if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { errx(1, "could not get numeric hostname"); /*NOTREACHED*/ @@ -155,44 +172,20 @@ The following version checks if the socket address has a reverse address mapping struct sockaddr *sa; /* input */ char hbuf[NI_MAXHOST]; -if (getnameinfo(sa, sa-\*[Gt]sa_len, hbuf, sizeof(hbuf), NULL, 0, +if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD)) { errx(1, "could not resolve hostname"); /*NOTREACHED*/ } printf("host=%s\en", hbuf); .Ed -.Sh LEGACY SYNOPSIS -.Fd #include -.Fd #include -.Fd #include -.Pp -The include file -.In sys/types.h -is necessary. -.Pp -.Ft int -.Fo getnameinfo -.Fa "const struct sockaddr *restrict sa" -.Fa "socklen_t salen" -.Fa "char *restrict node" -.Fa "size_t nodelen" -.Fa "char *service" -.Fa "size_t servicelen" -.Fa "int flags" -.Fc ; -.Pp -The type of -.Fa nodelen -and -.Fa servicelen -has changed. .Sh SEE ALSO .Xr gai_strerror 3 , .Xr getaddrinfo 3 , .Xr gethostbyaddr 3 , .Xr getservbyport 3 , .Xr inet_ntop 3 , +.Xr link_ntoa 3 , .Xr resolver 3 , .Xr hosts 5 , .Xr resolv.conf 5 , @@ -222,7 +215,7 @@ has changed. .Rs .%A Craig Metz .%T Protocol Independence Using the Sockets API -.%B "Proceedings of the FREENIX track: 2000 USENIX annual technical conference" +.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re .Sh STANDARDS @@ -231,7 +224,7 @@ The function is defined by the .St -p1003.1g-2000 draft specification and documented in -.Sy "RFC 2553" , +.Tn "RFC 2553" , .Dq Basic Socket Interface Extensions for IPv6 . .Sh CAVEATS .Fn getnameinfo @@ -260,7 +253,8 @@ To prevent such attacks, the use of .Dv NI_NAMEREQD is recommended when the result of .Fn getnameinfo -is used for access control purposes: +is used +for access control purposes: .Bd -literal -offset indent struct sockaddr *sa; socklen_t salen; @@ -271,10 +265,10 @@ int error; error = getnameinfo(sa, salen, addr, sizeof(addr), NULL, 0, NI_NAMEREQD); if (error == 0) { - memset(\*[Am]hints, 0, sizeof(hints)); + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(addr, "0", \*[Am]hints, \*[Am]res) == 0) { + if (getaddrinfo(addr, "0", &hints, &res) == 0) { /* malicious PTR record */ freeaddrinfo(res); printf("bogus PTR record\en"); diff --git a/lookup.subproj/getnetgrent.3 b/lookup.subproj/getnetgrent.3 index 7124aef..6fe0271 100644 --- a/lookup.subproj/getnetgrent.3 +++ b/lookup.subproj/getnetgrent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,7 +26,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)getnetgrent.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD: src/lib/libc/gen/getnetgrent.3,v 1.10 2001/10/01 16:08:51 ru Exp $ +.\" $FreeBSD: src/lib/libc/gen/getnetgrent.3,v 1.13 2007/01/09 00:27:54 imp Exp $ .\" .Dd June 4, 1993 .Dt GETNETGRENT 3 @@ -85,7 +81,9 @@ If is called with a different netgroup than the previous call, an implicit .Fn endnetgrent is implied. -.Fn Setnetgrent +The +.Fn setnetgrent +function also sets the offset to the first member of the netgroup. .Pp The function @@ -116,14 +114,14 @@ have no return value. .It Pa /etc/netgroup netgroup database file .El -.Sh SEE ALSO -.Xr netgroup 5 .Sh COMPATIBILITY The netgroup members have three string fields to maintain compatibility with other vendor implementations, however it is not obvious what use the .Sy domain string has within .Bx . +.Sh SEE ALSO +.Xr netgroup 5 .Sh BUGS The function .Fn getnetgrent diff --git a/lookup.subproj/getpwent.3 b/lookup.subproj/getpwent.3 index f60d28a..75c99c3 100644 --- a/lookup.subproj/getpwent.3 +++ b/lookup.subproj/getpwent.3 @@ -9,10 +9,6 @@ .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. @@ -30,75 +26,60 @@ .\" SUCH DAMAGE. .\" .\" From: @(#)getpwent.3 8.2 (Berkeley) 12/11/93 -.\" $FreeBSD: src/lib/libc/gen/getpwent.3,v 1.18 2001/10/01 16:08:51 ru Exp $ +.\" $FreeBSD: src/lib/libc/gen/getpwent.3,v 1.30 2007/01/09 00:27:54 imp Exp $ .\" -.Dd September 20, 1994 +.Dd April 16, 2003 .Dt GETPWENT 3 .Os .Sh NAME -.Nm endpwent , .Nm getpwent , +.\".Nm getpwent_r , .Nm getpwnam , .Nm getpwnam_r , .Nm getpwuid , .Nm getpwuid_r , .Nm setpassent , -.Nm setpwent +.Nm setpwent , +.Nm endpwent .Nd password database operations .Sh LIBRARY .Lb libc .Sh SYNOPSIS +.In sys/types.h .In pwd.h -.Ft void -.Fo endpwent -.Fa void -.Fc .Ft struct passwd * -.Fo getpwent -.Fa void -.Fc +.Fn getpwent void +.\".Ft int +.\".Fn getpwent_r "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result" .Ft struct passwd * -.Fo getpwnam -.Fa "const char *login" -.Fc +.Fn getpwnam "const char *login" .Ft int -.Fo getpwnam_r -.Fa "const char *login" -.Fa "struct passwd *pwd" -.Fa "char *buffer" -.Fa "size_t bufsize" -.Fa "struct passwd **result" -.Fc +.Fn getpwnam_r "const char *name" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result" .Ft struct passwd * -.Fo getpwuid -.Fa "uid_t uid" -.Fc +.Fn getpwuid "uid_t uid" .Ft int -.Fo getuid_r -.Fa "uid_t uid" -.Fa "struct passwd *pwd" -.Fa "char *buffer" -.Fa "size_t bufsize" -.Fa "struct passwd **result" -.Fc +.Fn getpwuid_r "uid_t uid" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result" .Ft int -.Fo setpassent -.Fa "int stayopen" -.Fc +.Fn setpassent "int stayopen" .Ft void -.Fo setpwent -.Fa void -.Fc +.Fn setpwent void +.Ft void +.Fn endpwent void .Sh DESCRIPTION These functions -operate on the password database file, +.\"operate on the password database file +obtain information from +.Xr DirectoryService 8 , +including records in +.Pa /etc/passwd which is described in .Xr passwd 5 . Each entry in the database is defined by the structure -.Ar passwd , -found in the include file -.Aq Pa pwd.h : +.Vt passwd +found in the include +file +.In pwd.h : .Bd -literal -offset indent struct passwd { char *pw_name; /* user name */ @@ -122,44 +103,47 @@ and search the password database for the given login name or user uid, respectively, always returning the first one encountered. .Pp -All of these routines are thread-safe. +On Mac OS X, these routines are thread-safe and return a pointer to a +thread-specific data structure. The contents of this data +structure are automatically released by subsequent calls to +any of these routines on the same thread, or when the thread exits. +.Pp The -.Fn getpwent , -.Fn getpwnam , -and -.Fn getpwuid -routines return a pointer to a result managed by the system library in a -thread-specific data structure. -Every thread has space for a pointer to a struct passwd and allocates its own storage for the result. -Neither previously returned values in memory nor a previously returned pointer value should be used -by a thread after calling any one of these three routines. -Memory allocated by a thread is automatically released on subsequent calls by the same thread to any of these -three routines, and when the thread exits. +.Fn getpwent +function +sequentially reads the password database and is intended for programs +that wish to process the complete list of users. .Pp The functions +.\".Fn getpwent_r , +.\".Fn getpwnam_r , .Fn getpwnam_r and .Fn getpwuid_r -take additional arguments which supply storage space for the returned result. -The -.Fa pwd -parameter is a pointer to a struct passwd, which must be allocated by the caller. -The -.Fa buffer -parameter is a pointer to a block of memory with a size specified by -.Pa bufsize . -This buffer is used to hold the values which are pointed to by values filled in +are thread-safe versions of +.\".Fn getpwent , +.\".Fn getpwnam , +.Fn getpwnam +and +.Fn getpwuid , +respectively. +The caller must provide storage for the results of the search in the +.Fa pwd , +.Fa buffer , +.Fa bufsize , +and +.Fa result +arguments. +When these functions are successful, the .Fa pwd -structure. -Zero is returned on success. -If insufficient memory is supplied, these routines return ERANGE. -.Pp -The -.Fn getpwent -function -sequentially reads the password database and is intended for programs -that wish to process the complete list of users. +argument will be filled-in, and a pointer to that argument will be +stored in +.Fa result . +If an entry is not found or an error occurs, +.Fa result +will be set to +.Dv NULL . .Pp The .Fn setpassent @@ -173,11 +157,11 @@ Additionally, if is non-zero, file descriptors are left open, significantly speeding up subsequent accesses for all of the routines. (This latter functionality is unnecessary for -.Fn getpwent , -as it doesn't close its file descriptors by default.) +.Fn getpwent +as it does not close its file descriptors by default.) .Pp It is dangerous for long-running programs to keep the file descriptors -open, as the database will become out of date if it is updated while the +open as the database will become out of date if it is updated while the program is running. .Pp The @@ -185,49 +169,29 @@ The function is identical to .Fn setpassent -with an argument of zero, -save that it does not return a status value. +with an argument of zero. .Pp The .Fn endpwent function closes any open files. .Pp -As of Mac OS X 10.3, there are now different per-user behaviours of -this function, based on the AuthenticationAuthority value -stored for the queried user in DirectoryServices. -.Pp -If the queried user is still a legacy crypt password user or now -has an AuthenticationAuthority value containing ``;basic;'', -these routines will behave in their standard BSD fashion. -These functions will ``shadow'' the password file, e.g.\& -allow only certain programs to have access to the encrypted password. -If the process which calls them has an effective uid of 0, the encrypted -password will be returned, otherwise, the password field of the returned -structure will point to the string -.Ql * . -.Pp -By default in Mac OS X 10.3 and later all users will have an -AuthenticationAuthority with the value ``;ShadowHash;''. -These users will have a visible password value of ``********''. -These functions -will have no access to the encrypted password whatsoever. -Setting or changing -an user password must be done entirely through the DirectoryService APIs -for this default user. -.Pp -There also exists an ``Apple Password Server'' user whose password -value is also ``********'' and with an AuthenticationAuthority that -contains the value ";ApplePasswordServer;" among other data. -There is no getpwnam access to the password for this user either -and again set/change password can be done through the DirectoryService API. -.Pp -Finally in support of local user caching there is a local cached user -whose password is also ``********'' and has an AuthenticationAuthority -value containing ``;LocalCachedUser;'' among other data. -These functions also provide no access to the password for this user -and set/change password functionality is through the DirectoryService API. -.Pp +.\"These routines have been written to ``shadow'' the password file, e.g.\& +.\"allow only certain programs to have access to the encrypted password. +.\"If the process which calls them has an effective uid of 0, the encrypted +.\"password will be returned, otherwise, the password field of the returned +.\"structure will point to the string +These routines have been written to +.Ql shadow +the password of user records created on Mac OS X 10.3 or later, +by returning a structure whose password field points to the string +.Ql ******** . +Legacy crypt passwords are still returned for user records created on +earlier versions of Mac OS X whose +.Xr DirectoryService 8 +.Dt AuthenticationAuthority +attribute contains the value +.Ql ;basic; . .Sh RETURN VALUES The functions .Fn getpwent , @@ -235,7 +199,30 @@ The functions and .Fn getpwuid return a valid pointer to a passwd structure on success -and a null pointer if end-of-file is reached or an error occurs. +or +.Dv NULL +if the entry is not found or if an error occurs. +If an error does occur, +.Va errno +will be set. +Note that programs must explicitly set +.Va errno +to zero before calling any of these functions if they need to +distinguish between a non-existent entry and an error. +The functions +.\".Fn getpwent_r , +.\".Fn getpwnam_r , +.Fn getpwnam_r +and +.Fn getpwuid_r +return 0 if no error occurred, or an error number to indicate failure. +It is not an error if a matching entry is not found. +(Thus, if +.Fa result +is +.Dv NULL +and the return value is 0, no matching entry exists.) +.Pp The .Fn setpassent function returns 0 on failure and 1 on success. @@ -243,47 +230,62 @@ The .Fn endpwent and .Fn setpwent -functions have no return value. +functions +have no return value. .Sh FILES .Bl -tag -width /etc/master.passwd -compact -.It Pa /etc/pwd.db -The insecure password database file -.It Pa /etc/spwd.db +.\".It Pa /etc/pwd.db +.\"The insecure password database file +.\".It Pa /etc/spwd.db The secure password database file .It Pa /etc/master.passwd The current password file .It Pa /etc/passwd A Version 7 format password file .El -.Sh LEGACY SYNOPSIS -.Fd #include -.Fd #include -.Pp -The include file -.In sys/types.h -is necessary for the -.Fa getpwent , -.Fa getpwnam , +.\".Sh COMPATIBILITY +.\"The historic function +.\".Xr setpwfile 3 , +.\"which allowed the specification of alternate password databases, +.\"has been deprecated and is no longer available. +.Sh ERRORS +These routines may fail for any of the errors specified in +.Xr open 2 , +.Xr dbopen 3 , +.Xr socket 2 , and -.Fa getpwuid -functions. -.Pp -.Ft int -.br -.Fo setpwent -.Fa void -.Fc ; -.Pp -The -.Fn setpwent -function returns 0 on failure and 1 on success. +.Xr connect 2 , +in addition to the following: +.Bl -tag -width Er +.It Bq Er ERANGE +The buffer specified by the +.Fa buffer +and +.Fa bufsize +arguments was insufficiently sized to store the result. +The caller should retry with a larger buffer. +.El .Sh SEE ALSO .Xr getlogin 2 , .Xr getgrent 3 , -.Xr yp 8 , +.\".Xr nsswitch.conf 5 , .Xr passwd 5 , -.Xr pwd_mkdb 8 , -.Xr vipw 8 +.\".Xr pwd_mkdb 8 , +.\".Xr vipw 8 , +.Xr DirectoryService 8 , +.Xr yp 8 +.Sh STANDARDS +The +.Fn getpwent , +.Fn getpwnam , +.Fn getpwnam_r , +.Fn getpwuid , +.Fn getpwuid_r , +.Fn setpwent , +and +.Fn endpwent +functions conform to +.St -p1003.1-96 . .Sh HISTORY The .Fn getpwent , @@ -298,18 +300,41 @@ The .Fn setpassent function appeared in .Bx 4.3 Reno . -.Sh COMPATIBILITY -The historic function -.Xr setpwfile 3 , -which allowed the specification of alternate password databases, -has been deprecated and is no longer available. +The +.\".Fn getpwent_r , +.\".Fn getpwnam_r , +.Fn getpwnam_r +and +.Fn getpwuid_r +functions appeared in +.Fx 5.1 . .Sh BUGS The functions .Fn getpwent , .Fn getpwnam , and -.Fn getpwuid -leave their results in internal thread-specific memory and return +.Fn getpwuid , +.\"leave their results in an internal static object and return +leave their results in an internal thread-specific memory and return a pointer to that object. -Subsequent calls to any of these three routines by the same thread will -release the object and return a new pointer value. +Subsequent calls to +the same function +will modify the same object. +.\".Pp +.\"The functions +.\".Fn getpwent , +.\".Fn getpwent_r , +.\".Fn endpwent , +.\".Fn setpassent , +.\"and +.\".Fn setpwent +.\"are fairly useless in a networked environment and should be +.\"avoided, if possible. +.\"The +.\".Fn getpwent +.\"and +.\".Fn getpwent_r +.\"functions +.\"make no attempt to suppress duplicate information if multiple +.\"sources are specified in +.\".Xr nsswitch.conf 5 . diff --git a/lookup.subproj/ils.c b/lookup.subproj/ils.c new file mode 100644 index 0000000..bdf121b --- /dev/null +++ b/lookup.subproj/ils.c @@ -0,0 +1,711 @@ +/* + * Copyright (c) 1999-2009 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif +#include + +#define ILS_MAGIC_SIZE 8 +#define ILS_MAGIC "ILSMAGIC" + +/* GLOBAL */ + +static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 4 }; +static const uint32_t align_64[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 }; + +static uint32_t +padsize(size_t curr, size_t item, const uint32_t *align) +{ + uint32_t na, diff; + + if (item > 8) item = 8; + + na = align[item]; + if (na == 0) return 0; + + diff = curr % na; + if (diff == 0) return 0; + + return na - diff; +} + +/* + * Create a structure using in-line memory (i.e. all one blob). + * This reduces malloc/free workload. + * + * Structure components may be strings, 1, 2, 4, or 8-byte values, + * lists of strings, or lists of 4, 8, or 16-byte values. + * + * Format keys: + * s NUL terminated string + * 1 1 byte value + * 2 2 byte value + * 4 4 byte value + * 8 8 byte value + * S 128 byte value (_SS_MAXSIZE for a sockaddr) + * L long (32 or 64 bits, depending on architecture) + * m mach_port_t + * * NULL-terminated list of strings + * a NULL-terminated list of 4-byte values + * b NULL-terminated list of 8-byte values + * c NULL-terminated list of 16-byte values + * @ length (4 bytes) and buffer (requires two parameters) + * + */ +void * +LI_ils_create(char *fmt, ...) +{ + va_list ap; + char *arg, *f; + char **list; + void *hp, *dp, *lp, *ils; + uint8_t u8; + uint16_t u16; + uint32_t u32, i, pad; + uint64_t u64; + unsigned long l; + mach_port_t m; + socket_data_t sdata; + size_t memsize, hsize, csize, csizep1, csizep2, slen, largest; + const uint32_t *align; + + if (fmt == NULL) return NULL; + + largest = 0; + align = align_32; + if (sizeof(char *) == 8) align = align_64; + + /* first pass: calculate size */ + memsize = ILS_MAGIC_SIZE; + hsize = 0; + + va_start(ap, fmt); + + for (f = fmt; (*f) != '\0'; f++) + { + csize = 0; + slen = 0; + + switch (*f) + { + case 's': + { + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + arg = va_arg(ap, char *); + if (arg != NULL) slen = strlen(arg) + 1; + + break; + } + + case '1': + { + if (largest < 1) largest = 1; + + csize = 1; + u8 = va_arg(ap, int); + + break; + } + + case '2': + { + if (largest < 2) largest = 2; + + csize = 2 + padsize(hsize, 2, align); + u16 = va_arg(ap, int); + + break; + } + + case '4': + { + if (largest < 4) largest = 4; + + csize = 4 + padsize(hsize, 4, align); + u32 = va_arg(ap, uint32_t); + + break; + } + + case '8': + { + if (largest < 8) largest = 8; + + csize = 8 + padsize(hsize, 8, align); + u64 = va_arg(ap, uint64_t); + + break; + } + + case 'S': + { + if (largest < 128) largest = 128; + + /* 4-byte-align since a socket_data_t is really just a buffer */ + csize = 128 + padsize(hsize, 4, align); + sdata = va_arg(ap, socket_data_t); + + break; + } + + case 'L': + { + if (largest < sizeof(unsigned long)) largest = sizeof(unsigned long); + + csize = sizeof(unsigned long) + padsize(hsize, sizeof(unsigned long), align); + l = va_arg(ap, unsigned long); + + break; + } + + case 'm': + { + if (largest < sizeof(mach_port_t)) largest = sizeof(mach_port_t); + + csize = sizeof(mach_port_t) + padsize(hsize, sizeof(mach_port_t), align); + m = va_arg(ap, mach_port_t); + + break; + } + + case '*': + { + /* NULL-terminated list of strings */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += (strlen(list[i]) + 1); + } + + slen += sizeof(char *); + } + + break; + } + + case 'a': + { + /* NULL-terminated list of 4-byte values */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += 4; + } + + slen += sizeof(char *); + } + + break; + } + + case 'b': + { + /* NULL-terminated list of 8-byte values */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += 8; + } + + slen += sizeof(char *); + } + + break; + } + + case 'c': + { + /* NULL-terminated list of 16-byte values */ + if (largest < sizeof(char *)) largest = sizeof(char *); + + csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); + list = va_arg(ap, char **); + if (list != NULL) + { + for (i = 0; list[i] != NULL; i++) + { + slen += sizeof(char *); + slen += 16; + } + + slen += sizeof(char *); + } + + break; + } + + case '@': + { + if (largest < 4) largest = 4; + csizep1 = 4 + padsize(hsize, 4, align); + slen = va_arg(ap, uint32_t); + + if (largest < sizeof(char *)) largest = sizeof(char *); + csizep2 = sizeof(char *) + padsize(hsize + csizep1, sizeof(char *), align); + arg = va_arg(ap, char *); + + csize = csizep1 + csizep2; + + break; + } + + default: return NULL; + } + + memsize += csize; + memsize += slen; + hsize += csize; + } + + va_end(ap); + + pad = padsize(hsize, largest, align); + memsize += pad; + hsize += pad; + + ils = malloc(memsize); + if (ils == NULL) + { + errno = ENOMEM; + return NULL; + } + + /* insert magic cookie */ + dp = ils + hsize; + memcpy(dp, ILS_MAGIC, ILS_MAGIC_SIZE); + dp += ILS_MAGIC_SIZE; + + hp = ils; + hsize = 0; + + /* second pass: copy data */ + va_start(ap, fmt); + for (f = fmt; (*f) != '\0'; f++) + { + switch (*f) + { + case 's': + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + arg = va_arg(ap, char *); + if (arg == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + slen = strlen(arg) + 1; + memcpy(dp, arg, slen); + dp += slen; + } + + hp += sizeof(char *); + hsize += sizeof(char *); + + break; + } + + case '1': + { + u8 = va_arg(ap, int); + memcpy(hp, &u8, sizeof(uint8_t)); + hp += sizeof(uint8_t); + + break; + } + + case '2': + { + pad = padsize(hsize, 2, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + u16 = va_arg(ap, int); + memcpy(hp, &u16, sizeof(uint16_t)); + + hp += sizeof(uint16_t); + hsize += sizeof(uint16_t); + + break; + } + + case '4': + { + pad = padsize(hsize, 4, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + u32 = va_arg(ap, uint32_t); + memcpy(hp, &u32, sizeof(uint32_t)); + + hp += sizeof(uint32_t); + hsize += sizeof(uint32_t); + + break; + } + + case '8': + { + pad = padsize(hsize, 8, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + u64 = va_arg(ap, uint64_t); + memcpy(hp, &u64, sizeof(uint64_t)); + + hp += sizeof(uint64_t); + hsize += sizeof(uint64_t); + + break; + } + + case 'S': + { + pad = padsize(hsize, 4, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + sdata = va_arg(ap, socket_data_t); + memcpy(hp, (char *)(sdata.x), sizeof(socket_data_t)); + + hp += sizeof(socket_data_t); + hsize += sizeof(socket_data_t); + + break; + } + + case 'L': + { + pad = padsize(hsize, sizeof(unsigned long), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + l = va_arg(ap, unsigned long); + memcpy(hp, &l, sizeof(unsigned long)); + + hp += sizeof(unsigned long); + hsize += sizeof(unsigned long); + + break; + } + + case 'm': + { + pad = padsize(hsize, sizeof(mach_port_t), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + m = va_arg(ap, mach_port_t); + memcpy(hp, &m, sizeof(mach_port_t)); + + hp += sizeof(mach_port_t); + hsize += sizeof(mach_port_t); + + break; + } + + case '*': + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = strlen(list[i]) + 1; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + + break; + } + + case 'a': + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = 4; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + + break; + } + + case 'b': + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = 8; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + + break; + } + + case 'c': + { + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + list = va_arg(ap, char **); + + if (list == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + + for (i = 0; list[i] != NULL; i++); + + lp = dp; + dp += ((i + 1) * sizeof(char *)); + + for (i = 0; list[i] != NULL; i++) + { + memcpy(lp, &dp, sizeof(char *)); + lp += sizeof(char *); + slen = 16; + memcpy(dp, list[i], slen); + dp += slen; + } + + memset(lp, 0, sizeof(char *)); + } + + hp += sizeof(char *); + hsize += sizeof(char *); + + break; + } + + case '@': + { + pad = padsize(hsize, 4, align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + slen = va_arg(ap, uint32_t); + memcpy(hp, &slen, sizeof(uint32_t)); + + hp += sizeof(uint32_t); + hsize += sizeof(uint32_t); + + pad = padsize(hsize, sizeof(char *), align); + if (pad != 0) + { + memset(hp, 0, pad); + hp += pad; + hsize += pad; + } + + arg = va_arg(ap, char *); + if (arg == NULL) + { + memset(hp, 0, sizeof(char *)); + } + else + { + memcpy(hp, &dp, sizeof(char *)); + memcpy(dp, arg, slen); + dp += slen; + } + + hp += sizeof(char *); + hsize += sizeof(char *); + } + } + } + + va_end(ap); + + pad = padsize(hsize, largest, align); + if (pad > 0) memset(hp, 0, pad); + + return ils; +} diff --git a/lookup.subproj/lu_bootparam.c b/lookup.subproj/ils.h similarity index 75% rename from lookup.subproj/lu_bootparam.c rename to lookup.subproj/ils.h index ea452e1..7a9eef8 100644 --- a/lookup.subproj/lu_bootparam.c +++ b/lookup.subproj/ils.h @@ -22,33 +22,17 @@ * @APPLE_LICENSE_HEADER_END@ */ /* - * Bootparams lookup - netinfo only + * Useful macros and other stuff for generic lookups * Copyright (C) 1989 by NeXT, Inc. */ -#include -#include -#include -#include -#include -struct bootparamsent * -bootparams_getbyname(const char *name) -{ - return NULL; -} +#ifndef _LU_UTILS_H_ +#define _LU_UTILS_H_ -struct bootparamsent * -bootparams_getent(void) -{ - return NULL; -} +typedef struct { char x[128]; } socket_data_t; -void -bootparams_setent(void) -{ -} +#include -void -bootparams_endent(void) -{ -} +void *LI_ils_create(char *fmt, ...); + +#endif /* ! _LU_UTILS_H_ */ diff --git a/lookup.subproj/kvbuf.c b/lookup.subproj/kvbuf.c new file mode 100644 index 0000000..a32a1ef --- /dev/null +++ b/lookup.subproj/kvbuf.c @@ -0,0 +1,963 @@ +/* + * Copyright (c) 2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include + +#define KVBUF_CHUNK 256 + +/* + * kvbuf_t is a list of key/value dictionaries. + * + * First 4 bytes are the number of dictionaries. + * For each dictionary, first 4 bytes is the key / value list count. + * For each value list, first 4 bytes is the list length. + * Keys and values are a 4-byte length followed by a nul-terminated string + * + * When the databuf needs to grow, we add memory in KVBUF_CHUNK size + * increments to reduce malloc / realloc activity. + * The _size variable stores the actual allocated size. + * The datalen variable stores the used data size. + * + * The _dict variable holds an offset from the start of the buffer + * to the "current" dictionary. kvbuf_reset() resets this, + * and kvbuf_next_dict() bumps the offset so that databuf + _dict + * points to the next dictionary. + * + * The _key variable holds an offset from the start of the buffer + * to the "current" key. kvbuf_reset() resets this, and + * kvbuf_next_key() bumps the offset so that databuf + _key + * points to the next key. + * + * The _val variable holds an offset from the start of the buffer + * to the "current" value. kvbuf_reset() resets this, and + * kvbuf_next_val() bumps the offset so that databuf + _val + * points to the next value. + * + * The cache_entry_list_to_kvbuf() routine contains the only + * code that builds an array. + * + */ + +/* + * kvbuf_query is a simple utility for constructing a + * kvbuf with a single dictionary. The format string may + * contain the chars "k", "s", "i", and "u". "k" denotes a key + * (keys are always strings), "s" denotes a string value, + * "i" denotes a 32 bit signed int, and "u" denotes an unsigned. + */ +__private_extern__ kvbuf_t * +kvbuf_query(char *fmt, ...) +{ + va_list ap; + char *arg, *f, str[32]; + int32_t iarg; + uint32_t uarg; + kvbuf_t *kv; + + if (fmt == NULL) return NULL; + + kv = kvbuf_new(); + if (kv == NULL) return NULL; + + kvbuf_add_dict(kv); + + va_start(ap, fmt); + for (f = fmt; (*f) != '\0'; f++) + { + if (*f == 'k') + { + arg = va_arg(ap, char *); + kvbuf_add_key(kv, arg); + } + else if (*f == 's') + { + arg = va_arg(ap, char *); + kvbuf_add_val(kv, arg); + } + else if (*f == 'i') + { + iarg = va_arg(ap, int32_t); + snprintf(str, sizeof(str), "%d", iarg); + kvbuf_add_val(kv, str); + } + else if (*f == 'u') + { + uarg = va_arg(ap,uint32_t); + snprintf(str, sizeof(str), "%u", uarg); + kvbuf_add_val(kv, str); + } + } + va_end(ap); + + return kv; +} + +kvbuf_t * +kvbuf_query_key_val(const char *key, const char *val) +{ + kvbuf_t *kv; + uint32_t x, kl, vl, vc; + char *p; + + if (key == NULL) return NULL; + + kl = strlen(key) + 1; + + vl = 0; + vc = 0; + + if (val != NULL) + { + vl = strlen(val) + 1; + vc = 1; + } + + kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); + if (kv == NULL) return NULL; + + kv->_size = (5 * sizeof(uint32_t)) + kl + vl; + kv->datalen = kv->_size; + + kv->databuf = calloc(1, kv->_size); + if (kv->databuf == NULL) + { + free(kv); + return NULL; + } + + p = kv->databuf; + + /* 1 dict */ + x = htonl(1); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* 1 key */ + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* key length */ + x = htonl(kl); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* key */ + memcpy(p, key, kl); + p += kl; + + /* number of values */ + x = htonl(vc); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + if (vc > 0) + { + /* value length */ + x = htonl(vl); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + + /* value */ + memcpy(p, val, vl); + } + + return kv; +} + +__private_extern__ kvbuf_t * +kvbuf_query_key_int(const char *key, int32_t i) +{ + char str[32]; + + snprintf(str, sizeof(str), "%d", i); + return kvbuf_query_key_val(key, str); +} + +__private_extern__ kvbuf_t * +kvbuf_query_key_uint(const char *key, uint32_t u) +{ + char str[32]; + + snprintf(str, sizeof(str), "%u", u); + return kvbuf_query_key_val(key, str); +} + +kvbuf_t * +kvbuf_new_zone(malloc_zone_t *zone) +{ + kvbuf_t *kv; + + if (zone == NULL) return NULL; + + kv = (kvbuf_t *)malloc_zone_calloc(zone, 1, sizeof(kvbuf_t)); + if (kv == NULL) return NULL; + + kv->_size = KVBUF_START_SIZE; + kv->databuf = malloc_zone_calloc(zone, 1, kv->_size); + if (kv->databuf == NULL) + { + free(kv); + return NULL; + } + + kv->datalen = sizeof(uint32_t); + kv->_dict = kv->datalen; + + return kv; +} + +kvbuf_t * +kvbuf_new(void) +{ + return kvbuf_new_zone(malloc_default_zone()); +} + +kvbuf_t * +kvbuf_init_zone(malloc_zone_t *zone, char *buffer, uint32_t length) +{ + kvbuf_t *kv; + + if (zone == NULL) return NULL; + + kv = (kvbuf_t *)malloc_zone_calloc(zone, 1, sizeof(kvbuf_t)); + if (kv == NULL) return NULL; + + kv->_size = length; + kv->datalen = length; + kv->databuf = malloc_zone_calloc(zone, 1, length); + if (kv->databuf == NULL) + { + free(kv); + kv = NULL; + } + else + { + memcpy(kv->databuf, buffer, length); + } + + return kv; +} + +kvbuf_t * +kvbuf_init(char *buffer, uint32_t length) +{ + return kvbuf_init_zone(malloc_default_zone(), buffer, length); +} + +static void +kvbuf_grow(kvbuf_t *kv, uint32_t delta) +{ + uint32_t newlen, n; + char *p; + + if (kv == NULL) return; + if (delta == 0) return; + + if (kv->databuf == NULL) delta += sizeof(uint32_t); + + n = (delta + KVBUF_CHUNK - 1) / KVBUF_CHUNK; + newlen = kv->datalen + (n * KVBUF_CHUNK); + + if (newlen <= kv->_size) return; + + kv->_size = newlen; + + if (kv->databuf == NULL) + { + kv->databuf = calloc(1, kv->_size); + if (kv->databuf == NULL) + { + memset(kv, 0, sizeof(kvbuf_t)); + return; + } + + kv->datalen = sizeof(uint32_t); + kv->_dict = sizeof(uint32_t); + } + else + { + kv->databuf = reallocf(kv->databuf, kv->_size); + if (kv->databuf == NULL) + { + memset(kv, 0, sizeof(kvbuf_t)); + return; + } + + p = kv->databuf + kv->datalen; + memset(p, 0, kv->_size - kv->datalen); + } +} + +void +kvbuf_add_dict(kvbuf_t *kv) +{ + char *p; + uint32_t x, dict_count; + + if (kv == NULL) return; + + /* Add a key count */ + kvbuf_grow(kv, sizeof(uint32_t)); + if (kv->databuf == NULL) return; + + kv->_dict = kv->datalen; + kv->datalen += sizeof(uint32_t); + + kv->_key = kv->datalen; + kv->_vlist = 0; + kv->_val = 0; + + /* increment and rewrite the dict count */ + p = kv->databuf; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + dict_count = ntohl(x); + + dict_count++; + x = htonl(dict_count); + memcpy(p, &x, sizeof(uint32_t)); +} + +void +kvbuf_add_key(kvbuf_t *kv, const char *key) +{ + uint32_t kl, x, key_count, delta; + char *p; + + if (kv == NULL) return; + if (key == NULL) return; + + kl = strlen(key) + 1; + + /* Grow to hold key len, key, and value list count. */ + delta = (2 * sizeof(uint32_t)) + kl; + kvbuf_grow(kv, delta); + + if (kv->databuf == NULL) return; + + /* increment and rewrite the key count for the current dictionary */ + p = kv->databuf + kv->_dict; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + key_count = ntohl(x); + + if (key_count == 0) kv->_key = kv->_dict + sizeof(uint32_t); + else kv->_key = kv->datalen; + + key_count++; + x = htonl(key_count); + memcpy(p, &x, sizeof(uint32_t)); + + /* append key to data buffer */ + p = kv->databuf + kv->datalen; + + x = htonl(kl); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + memcpy(p, key, kl); + p += kl; + + kv->_vlist = kv->datalen + sizeof(uint32_t) + kl; + + x = 0; + memcpy(p, &x, sizeof(uint32_t)); + + kv->datalen += delta; + kv->_val = kv->datalen; +} + +void +kvbuf_add_val_len(kvbuf_t *kv, const char *val, uint32_t len) +{ + uint32_t x, val_count, delta; + char *p; + + if (kv == NULL) return; + if (val == NULL) return; + if (len == 0) return; + + /* Grow to hold val len and value. */ + delta = sizeof(uint32_t) + len; + kvbuf_grow(kv, delta); + + if (kv->databuf == NULL) return; + + /* increment and rewrite the value count for the value_list dictionary */ + p = kv->databuf + kv->_vlist; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + val_count = ntohl(x); + val_count++; + x = htonl(val_count); + memcpy(p, &x, sizeof(uint32_t)); + + /* append val to data buffer */ + p = kv->databuf + kv->_val; + + x = htonl(len); + memcpy(p, &x, sizeof(uint32_t)); + p += sizeof(uint32_t); + memcpy(p, val, len); + p += len; + + kv->datalen += delta; + kv->_val = kv->datalen; +} + +/* + * WARNING! Kludge Alert! + * + * This call just looks for the buffer length encoded into a serialized kvbuf_t, + * which preceeds a pointer to a key or value. Obviously, calling it with anything + * other than a pointer value which is embedded in a kvbuf_t is asking for trouble. + */ +uint32_t +kvbuf_get_len(const char *p) +{ + uint32_t x; + + x = 0; + memcpy(&x, p - sizeof(uint32_t), sizeof(uint32_t)); + return ntohl(x); +} + +void +kvbuf_add_val(kvbuf_t *kv, const char *val) +{ + if (kv == NULL) return; + if (val == NULL) return; + + kvbuf_add_val_len(kv, val, strlen(val) + 1); +} + +void +kvbuf_make_purgeable(kvbuf_t *kv) +{ + if (kv == NULL) return; + + if (kv->databuf != NULL) malloc_make_purgeable(kv->databuf); +} + +int +kvbuf_make_nonpurgeable(kvbuf_t *kv) +{ + if (kv == NULL) return 0; + + /* + * malloc_make_nonpurgeable returns 0 even if memory was not + * allocated from the purgeable zone, so this is safe to call. + */ + if ((kv->databuf == NULL) || (malloc_make_nonpurgeable(kv->databuf) == 0)) return 0; + + /* return non-zero since something failed */ + return 1; +} + +void +kvbuf_free(kvbuf_t *kv) +{ + if (kv == NULL) return; + + if (kv->databuf != NULL) free(kv->databuf); + memset(kv, 0, sizeof(kvbuf_t)); + free(kv); +} + +/* appends a kvbuf to an existing kvbuf */ +void +kvbuf_append_kvbuf(kvbuf_t *kv, const kvbuf_t *kv2) +{ + uint32_t curr_count, new_count, temp; + + if (kv == NULL) return; + if (kv2 == NULL) return; + + curr_count = 0; + new_count = 0; + + memcpy(&temp, kv->databuf, sizeof(uint32_t)); + curr_count = ntohl(temp); + + memcpy(&temp, kv2->databuf, sizeof(uint32_t)); + new_count = ntohl(temp); + + /* nothing to do */ + if (new_count == 0) return; + + /* add the dictionary count to the current dictionary counts */ + curr_count += new_count; + + temp = htonl(curr_count); + memcpy(kv->databuf, &temp, sizeof(uint32_t)); + + /* grow the current buffer so we can append the new buffer */ + temp = kv2->datalen - sizeof(uint32_t); + + kvbuf_grow(kv, temp); + + memcpy(kv->databuf + kv->datalen, kv2->databuf + sizeof(uint32_t), temp); + kv->datalen += temp; +} + +/* returns number of dictionaries */ +uint32_t +kvbuf_reset(kvbuf_t *kv) +{ + uint32_t x; + + if (kv == NULL) return 0; + if (kv->databuf == NULL) return 0; + + kv->_dict = 0; + kv->_key = 0; + kv->_vlist = 0; + kv->_val = 0; + + if (kv->datalen < sizeof(uint32_t)) return 0; + + x = 0; + memcpy(&x, kv->databuf, sizeof(uint32_t)); + return ntohl(x); +} + +/* advance to next dictionary, returns key count */ +uint32_t +kvbuf_next_dict(kvbuf_t *kv) +{ + uint32_t x, k, v, kcount, vcount, kl, vl; + char *p; + + if (kv == NULL) return 0; + if (kv->databuf == NULL) return 0; + + kv->_key = 0; + kv->_vlist = 0; + kv->_val = 0; + + if (kv->_dict == 0) + { + /* first dict */ + if (kv->datalen < sizeof(uint32_t)) return 0; + kv->_dict = sizeof(uint32_t); + + if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0; + + p = kv->databuf + kv->_dict; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kcount = ntohl(x); + + return kcount; + } + + p = kv->databuf + kv->_dict; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + kcount = ntohl(x); + + for (k = 0; k < kcount; k++) + { + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + kl = ntohl(x); + p += kl; + kv->_dict += kl; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + vcount = ntohl(x); + + for (v = 0; v < vcount; v++) + { + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_dict += sizeof(uint32_t); + vl = ntohl(x); + p += vl; + kv->_dict += vl; + } + } + + if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0; + + p = kv->databuf + kv->_dict; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kcount = ntohl(x); + + return kcount; +} + +/* advance to next key, returns key and sets val_count */ +char * +kvbuf_next_key(kvbuf_t *kv, uint32_t *val_count) +{ + uint32_t x, kl, v, vl, vc; + char *p, *out; + + if (kv == NULL) return NULL; + if (val_count == NULL) return NULL; + + *val_count = 0; + + if (kv->databuf == NULL) return NULL; + if (kv->_dict == 0) return NULL; + + kv->_vlist = 0; + kv->_val = 0; + + if (kv->_key == 0) + { + /* first key */ + if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return NULL; + kv->_key = kv->_dict + sizeof(uint32_t); + } + else + { + p = kv->databuf + kv->_key; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kl = ntohl(x); + + if (kv->datalen < (kv->_key + sizeof(uint32_t) + kl)) return NULL; + + p += (sizeof(uint32_t) + kl); + kv->_key += (sizeof(uint32_t) + kl); + + /* skip over values */ + if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + vc = ntohl(x); + + p += sizeof(uint32_t); + kv->_key += sizeof(uint32_t); + + for (v = 0; v < vc; v++) + { + if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; + + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + vl = ntohl(x); + + if (kv->datalen < (kv->_key + kl)) return NULL; + + p += (sizeof(uint32_t) + vl); + kv->_key += (sizeof(uint32_t) + vl); + } + } + + if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; + + p = kv->databuf + kv->_key; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + kl = ntohl(x); + + p += sizeof(uint32_t); + out = p; + + kv->_vlist = kv->_key + sizeof(uint32_t) + kl; + if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) + { + kv->_vlist = 0; + return NULL; + } + + p = kv->databuf + kv->_vlist; + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + *val_count = ntohl(x); + + return out; +} + +char * +kvbuf_next_val(kvbuf_t *kv) +{ + return kvbuf_next_val_len(kv, NULL); +} + +char * +kvbuf_next_val_len(kvbuf_t *kv, uint32_t *len) +{ + uint32_t x = 0; + uint32_t vltemp = 0; + char *p; + + if (kv == NULL) return NULL; + if (kv->databuf == NULL) return NULL; + if (kv->_vlist == 0) return NULL; + + if (kv->_val == 0) + { + /* first val */ + if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) return NULL; + kv->_val = kv->_vlist + sizeof(uint32_t); + + p = kv->databuf + kv->_val; + + memcpy(&x, p, sizeof(uint32_t)); + vltemp = ntohl(x); + } + else + { + p = kv->databuf + kv->_val; + + memcpy(&x, p, sizeof(uint32_t)); + vltemp = ntohl(x); + + if (kv->datalen < (kv->_val + sizeof(uint32_t) + vltemp)) return NULL; + + p += (sizeof(uint32_t) + vltemp); + kv->_val += (sizeof(uint32_t) + vltemp); + } + + if (kv->datalen < (kv->_val + sizeof(uint32_t))) return NULL; + + if (len != NULL) (*len) = vltemp; + p = kv->databuf + kv->_val + sizeof(uint32_t); + return p; +} + +/* + * Builds a kvarray_t / kvdict_t structure on top of a kvbuf_t. + * It allocates the appropriate number of kvdict_t structures + * for the array, sets all the counters, and fills in pointers + * for keys and valuse. The pointers are NOT to newly allocated + * strings: they just point into the kvbuf data buffer. + * + * To dispose of the kvarray_t and all of the associated + * memory AND to free the original kvbuf, clients only + * need to call kvarray_free(). + */ +kvarray_t * +kvbuf_decode(kvbuf_t *kv) +{ + kvarray_t *a; + uint32_t x, d, k, v; + char *p; + + if (kv == NULL) return NULL; + if (kv->databuf == NULL) return NULL; + + if (kv->datalen < sizeof(uint32_t)) return NULL; + + p = kv->databuf; + kv->_size = kv->datalen; + + /* array count */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + x = ntohl(x); + + if (x == 0) return NULL; + + a = (kvarray_t *)calloc(1, sizeof(kvarray_t)); + if (a == NULL) return NULL; + + a->count = x; + a->dict = (kvdict_t *)calloc(a->count, sizeof(kvdict_t)); + if (a->dict == NULL) + { + free(a); + return NULL; + } + + for (d = 0; d < a->count; d++) + { + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* key count */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + a->dict[d].kcount = ntohl(x); + + if (a->dict[d].kcount > 0) + { + a->dict[d].key = (const char **)calloc(a->dict[d].kcount, sizeof(const char *)); + if (a->dict[d].key == NULL) + { + kvarray_free(a); + return NULL; + } + + a->dict[d].vcount = (uint32_t *)calloc(a->dict[d].kcount, sizeof(uint32_t)); + if (a->dict[d].vcount == NULL) + { + kvarray_free(a); + return NULL; + } + + a->dict[d].val = (const char ***)calloc(a->dict[d].kcount, sizeof(char **)); + if (a->dict[d].val == NULL) + { + kvarray_free(a); + return NULL; + } + } + + for (k = 0; k < a->dict[d].kcount; k++) + { + /* get key */ + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* key length */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + x = ntohl(x); + + if (kv->_size < x) + { + kvarray_free(a); + return NULL; + } + + /* key data */ + a->dict[d].key[k] = p; + + p += x; + kv->_size -= x; + + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* val count */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + a->dict[d].vcount[k] = ntohl(x); + + if (a->dict[d].vcount[k] > 0) + { + /* N.B. we add a NULL pointer at the end of the list */ + a->dict[d].val[k] = (const char **)calloc(a->dict[d].vcount[k] + 1, sizeof(const char *)); + if (a->dict[d].val[k] == NULL) + { + kvarray_free(a); + return NULL; + } + } + + for (v = 0; v < a->dict[d].vcount[k]; v++) + { + /* get val */ + if (kv->_size < sizeof(uint32_t)) + { + kvarray_free(a); + return NULL; + } + + /* val length */ + x = 0; + memcpy(&x, p, sizeof(uint32_t)); + p += sizeof(uint32_t); + kv->_size -= sizeof(uint32_t); + x = ntohl(x); + + if (kv->_size < x) + { + kvarray_free(a); + return NULL; + } + + /* val data */ + a->dict[d].val[k][v] = p; + + p += x; + kv->_size -= x; + } + } + } + + a->kv = kv; + return a; +} + +void +kvarray_free(kvarray_t *a) +{ + uint32_t d, k; + + if (a == NULL) return; + + for (d = 0; d < a->count; d++) + { + for (k = 0; k < a->dict[d].kcount; k++) + { + if (a->dict[d].val == NULL) continue; + if (a->dict[d].val[k] != NULL) free(a->dict[d].val[k]); + } + + if (a->dict[d].key != NULL) free(a->dict[d].key); + if (a->dict[d].vcount != NULL) free(a->dict[d].vcount); + if (a->dict[d].val != NULL) free(a->dict[d].val); + } + + a->count = 0; + + if (a->dict != NULL) free(a->dict); + a->dict = NULL; + + if (a->kv != NULL) kvbuf_free(a->kv); + a->kv = NULL; + + free(a); +} + diff --git a/lookup.subproj/kvbuf.h b/lookup.subproj/kvbuf.h index 4da841f..93c4f36 100644 --- a/lookup.subproj/kvbuf.h +++ b/lookup.subproj/kvbuf.h @@ -1,9 +1,9 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2006-2008 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights * Reserved. This file contains Original Code and/or Modifications of * Original Code as defined in and that are subject to the Apple Public * Source License Version 1.1 (the "License"). You may not use this file @@ -21,16 +21,15 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * Useful macros and other stuff for generic lookups - * Copyright (C) 1989 by NeXT, Inc. - */ #ifndef _KVBUF_H_ #define _KVBUF_H_ #include #include +#include + +#define KVBUF_START_SIZE 128 /* * kvbuf_t is used to encode requests and replies. @@ -77,13 +76,19 @@ __BEGIN_DECLS * Utilities for creating KV buffers */ kvbuf_t *kvbuf_new(void); +kvbuf_t *kvbuf_new_zone(malloc_zone_t *zone); kvbuf_t *kvbuf_init(char *buffer, uint32_t length); +kvbuf_t *kvbuf_init_zone(malloc_zone_t *zone, char *buffer, uint32_t length); void kvbuf_add_dict(kvbuf_t *kv); void kvbuf_add_key(kvbuf_t *kv, const char *key); void kvbuf_add_val(kvbuf_t *kv, const char *val); void kvbuf_add_val_len(kvbuf_t *kv, const char *val, uint32_t len); uint32_t kvbuf_get_len(const char *p); + +void kvbuf_make_purgeable(kvbuf_t *kv); +int kvbuf_make_nonpurgeable(kvbuf_t *kv); + void kvbuf_free(kvbuf_t *kv); /* @@ -132,6 +137,14 @@ char *kvbuf_next_val(kvbuf_t *kv); */ char *kvbuf_next_val_len(kvbuf_t *kv, uint32_t *vl ); +/* + * kvbuf query support + */ +kvbuf_t *kvbuf_query(char *fmt, ...); +kvbuf_t *kvbuf_query_key_int(const char *key, int32_t i); +kvbuf_t *kvbuf_query_key_uint(const char *key, uint32_t u); +kvbuf_t *kvbuf_query_key_val(const char *key, const char *val); + __END_DECLS #endif /* ! _KVBUF_H_ */ diff --git a/lookup.subproj/libinfo.c b/lookup.subproj/libinfo.c new file mode 100644 index 0000000..30dd71e --- /dev/null +++ b/lookup.subproj/libinfo.c @@ -0,0 +1,3184 @@ +/* + * Copyright (c) 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "si_module.h" +#include "libinfo.h" +#include +#include +#include "netdb_async.h" + +#define SOCK_UNSPEC 0 +#define IPPROTO_UNSPEC 0 +#define IPV6_ADDR_LEN 16 +#define IPV4_ADDR_LEN 4 + +/* SPI from long ago */ +int _proto_stayopen; + +__private_extern__ struct addrinfo *si_list_to_addrinfo(si_list_t *list); + +/* + * Impedence matching for async calls. + * + * This layer holds on to the caller's callback and context in this + * structure, which gets passed to the si_module async routines along + * with a callbac in this layer. When this layer gets a callback, + * it can save the item or list in thread-specific memory and then + * invoke the caller's callback with the appropriate data type. + */ + +typedef struct +{ + void *orig_callback; + void *orig_context; + uint32_t cat; + int32_t key_offset; +} si_context_t; + +__private_extern__ si_mod_t * +si_search(void) +{ + static si_mod_t *search = NULL; + static OSSpinLock spin = OS_SPINLOCK_INIT; + + if (search == NULL) + { + OSSpinLockLock(&spin); + if (search == NULL) search = si_module_with_name("search"); + OSSpinLockUnlock(&spin); + } + + return search; +} + +static void +si_libinfo_general_callback(si_item_t *item, uint32_t status, void *ctx) +{ + si_context_t *sictx; + union + { + char *x; + struct passwd *u; + struct group *g; + struct grouplist_s *l; + struct hostent *h; + struct netent *n; + struct servent *s; + struct protoent *p; + struct rpcent *r; + struct fstab *f; + } res; + + if (ctx == NULL) return; + + sictx = (si_context_t *)ctx; + + if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) + { + free(sictx); + si_item_release(item); + return; + } + + if (sictx->key_offset >= 0) + { + LI_set_thread_item(sictx->cat + sictx->key_offset, item); + } + + res.x = NULL; + if (item != NULL) res.x = (char*)((uintptr_t)item + sizeof(si_item_t)); + + switch (sictx->cat) + { + case CATEGORY_USER: + { + ((si_user_async_callback)(sictx->orig_callback))(res.u, sictx->orig_context); + break; + } + case CATEGORY_GROUP: + { + ((si_group_async_callback)(sictx->orig_callback))(res.g, sictx->orig_context); + break; + } + case CATEGORY_GROUPLIST: + { + ((si_grouplist_async_callback)(sictx->orig_callback))(res.l, sictx->orig_context); + break; + } + case CATEGORY_HOST_IPV4: + case CATEGORY_HOST_IPV6: + { + ((si_host_async_callback)(sictx->orig_callback))(res.h, sictx->orig_context); + break; + } + case CATEGORY_NETWORK: + { + ((si_network_async_callback)(sictx->orig_callback))(res.n, sictx->orig_context); + break; + } + case CATEGORY_SERVICE: + { + ((si_service_async_callback)(sictx->orig_callback))(res.s, sictx->orig_context); + break; + } + case CATEGORY_PROTOCOL: + { + ((si_protocol_async_callback)(sictx->orig_callback))(res.p, sictx->orig_context); + break; + } + case CATEGORY_RPC: + { + ((si_rpc_async_callback)(sictx->orig_callback))(res.r, sictx->orig_context); + break; + } + case CATEGORY_FS: + { + ((si_fs_async_callback)(sictx->orig_callback))(res.f, sictx->orig_context); + break; + } + } + + free(sictx); +} + +/* USER */ + +struct passwd * +getpwnam(const char *name) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + item = si_user_byname(si_search(), name); + LI_set_thread_item(CATEGORY_USER + 100, item); + + if (item == NULL) return NULL; + return (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getpwnam_async_call(const char *name, si_user_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_USER; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_USER_BYNAME, name, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getpwnam_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct passwd * +getpwuid(uid_t uid) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %d\n", __func__, uid); +#endif + + item = si_user_byuid(si_search(), uid); + LI_set_thread_item(CATEGORY_USER + 200, item); + + if (item == NULL) return NULL; + return (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getpwuid_async_call(uid_t uid, si_user_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %d\n", __func__, uid); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_USER; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_USER_BYUID, NULL, NULL, (uint32_t)uid, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getpwuid_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +setpwent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_USER, NULL); +} + +struct passwd * +getpwent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_USER); + if (list == NULL) + { + list = si_user_all(si_search()); + LI_set_thread_list(CATEGORY_USER, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endpwent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_USER, NULL); +} + +int +setpassent(int ignored) +{ + si_list_t *list; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_USER); + si_list_reset(list); + + if (list == NULL) return 0; + return 1; +} + +/* GROUP */ + +struct group * +getgrnam(const char *name) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + item = si_group_byname(si_search(), name); + LI_set_thread_item(CATEGORY_GROUP + 100, item); + + if (item == NULL) return NULL; + return (struct group *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getgrnam_async_call(const char *name, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_GROUP; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_GROUP_BYNAME, name, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getgrnam_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct group * +getgrgid(gid_t gid) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %d\n", __func__, gid); +#endif + + item = si_group_bygid(si_search(), gid); + LI_set_thread_item(CATEGORY_GROUP + 200, item); + + if (item == NULL) return NULL; + return (struct group *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getgrgid_async_call(gid_t gid, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %d\n", __func__, gid); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_GROUP; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_GROUP_BYGID, NULL, NULL, (uint32_t)gid, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getgruid_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +setgrent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_GROUP, NULL); +} + +struct group * +getgrent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_GROUP); + if (list == NULL) + { + list = si_group_all(si_search()); + LI_set_thread_list(CATEGORY_GROUP, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct group *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endgrent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_GROUP, NULL); +} + +int +setgroupent(int ignored) +{ + si_list_t *list; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_GROUP); + si_list_reset(list); + + if (list == NULL) return 0; + return 1; +} + +/* NETGROUP */ +int +innetgr(const char *group, const char *host, const char *user, const char *domain) +{ + int res; +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %s %s %s\n", __func__, group, host, user, domain); +#endif + + res = si_in_netgroup(si_search(), group, host, user, domain); + +#ifdef CALL_TRACE + fprintf(stderr, "<- %s %d\n", __func__, res); +#endif + + return res; +} + +/* N.B. there is no async innetgr */ + +/* + * setnetgrent is really more like a getXXXbyname routine than a + * setXXXent routine, since we are looking up a netgroup by name. + */ +void +setnetgrent(const char *name) +{ + si_list_t *list; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + list = si_netgroup_byname(si_search(), name); + LI_set_thread_list(CATEGORY_NETGROUP, list); +} + +/* N.B. there is no async getnetgrent */ + +int +getnetgrent(char **host, char **user, char **domain) +{ + si_list_t *list; + si_item_t *item; + struct netgrent_s *ng; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_NETGROUP); + item = si_list_next(list); + if (item == NULL) return 0; + + ng = (struct netgrent_s *)((uintptr_t)item + sizeof(si_item_t)); + + *host = ng->ng_host; + *user = ng->ng_user; + *domain = ng->ng_domain; + + return 1; +} + +void +endnetgrent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_NETGROUP, NULL); +} + +/* GROUPLIST */ + +int +getgrouplist(const char *name, int basegid, int *groups, int *ngroups) +{ + int i, j, x, g, add, max; + si_item_t *item; + si_grouplist_t *gl; + + /* + * On input, ngroups specifies the size of the groups array. + * On output, it is set to the number of groups that are being returned. + * Returns -1 if the size is too small to fit all the groups that were found. + */ + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); +#endif + + if (name == NULL) return 0; + if (groups == NULL) return 0; + if (ngroups == NULL) return 0; + + max = *ngroups; + *ngroups = 0; + if (max <= 0) return 0; + + groups[0] = basegid; + *ngroups = 1; + + item = si_grouplist(si_search(), name); + LI_set_thread_item(CATEGORY_GROUPLIST, item); + if (item == NULL) return 0; + + gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t)); + + x = 1; + + if (gl->gl_basegid != basegid) + { + if (x >= max) return -1; + groups[x] = gl->gl_basegid; + x++; + *ngroups = x; + } + + for (i = 0; i < gl->gl_count; i++) + { + g = (int)*(gl->gl_gid[i]); + add = 1; + for (j = 0; (j < x) && (add == 1); j++) if (groups[j] == g) add = 0; + if (add == 0) continue; + + if (x >= max) return -1; + groups[x] = g; + x++; + *ngroups = x; + } + + return 0; +} + +/* XXX to do: async getgrouplist */ + +static int +merge_gid(gid_t **list, gid_t g, int32_t *count) +{ + int i; + + if (list == NULL) return -1; + + if (*count == 0) + { + *list = (gid_t *)calloc(1, sizeof(gid_t)); + if (list == NULL) + { + errno = ENOMEM; + return -1; + } + + (*list)[(*count)++] = g; + return 0; + } + + for (i = 0; i < *count; i++) if ((*list)[i] == g) return 0; + + *list = (gid_t *)reallocf(*list, (*count + 1) * sizeof(gid_t)); + (*list)[(*count)++] = g; + return 0; +} + +int32_t +getgrouplist_2(const char *name, gid_t basegid, gid_t **groups) +{ + int32_t i, status, count; + gid_t g; + si_item_t *item; + si_grouplist_t *gl; + + /* + * Passes back a gid_t list containing all the users groups (and basegid). + * Caller must free the list. + * Returns the number of gids in the list or -1 on failure. + */ + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); +#endif + + if (name == NULL) return 0; + if (groups == NULL) return 0; + + item = si_grouplist(si_search(), name); + LI_set_thread_item(CATEGORY_GROUPLIST, item); + if (item == NULL) return -1; + + gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t)); + + count = 0; + *groups = NULL; + + status = merge_gid(groups, basegid, &count); + if (status != 0) return status; + + status = merge_gid(groups, gl->gl_basegid, &count); + if (status != 0) return status; + + for (i = 0; i < gl->gl_count; i++) + { + g = (gid_t)*(gl->gl_gid[i]); + status = merge_gid(groups, g, &count); + if (status != 0) return status; + } + + return count; +} + +int32_t +getgroupcount(const char *name, gid_t basegid) +{ + int32_t i, status, count; + gid_t g; + si_item_t *item; + si_grouplist_t *gl; + gid_t *groups; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); +#endif + + if (name == NULL) return 0; + + item = si_grouplist(si_search(), name); + LI_set_thread_item(CATEGORY_GROUPLIST, item); + if (item == NULL) return -1; + + gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t)); + + count = 0; + groups = NULL; + + status = merge_gid(&groups, basegid, &count); + if (status != 0) return status; + + status = merge_gid(&groups, gl->gl_basegid, &count); + if (status != 0) return status; + + for (i = 0; i < gl->gl_count; i++) + { + g = (gid_t)*(gl->gl_gid[i]); + status = merge_gid(&groups, g, &count); + if (status != 0) return status; + } + + if (groups != NULL) free(groups); + + return count; +} + +/* XXX to do: async getgrouplist_2 */ + +int +initgroups(const char *name, int basegid) +{ + int status, ngroups, groups[NGROUPS]; + uid_t uid; +#ifdef DS_AVAILABLE + si_item_t *item; + struct passwd *p; +#endif + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid); +#endif + + /* KAUTH_UID_NONE tells the kernel not to fetch supplementary groups from DirectoryService */ + uid = KAUTH_UID_NONE; + +#ifdef DS_AVAILABLE + /* get the UID for this user */ + item = si_user_byname(si_search(), name); + if (item != NULL) + { + p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); + uid = p->pw_uid; + + si_item_release(item); + } +#endif + + ngroups = NGROUPS; + + status = getgrouplist(name, basegid, groups, &ngroups); + /* + * Ignore status. + * A failure either means that user belongs to more than NGROUPS groups + * or no groups at all. + */ + + status = syscall(SYS_initgroups, ngroups, groups, uid); + if (status < 0) return -1; + + return 0; +} + +/* ALIAS */ + +struct aliasent * +alias_getbyname(const char *name) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + item = si_alias_byname(si_search(), name); + LI_set_thread_item(CATEGORY_ALIAS + 100, item); + if (item == NULL) return NULL; + + return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +alias_getbyname_async_call(const char *name, si_alias_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_ALIAS; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_ALIAS_BYNAME, name, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +alias_getbyname_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +alias_setent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_ALIAS, NULL); +} + +struct aliasent * +alias_getent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_ALIAS); + if (list == NULL) + { + list = si_alias_all(si_search()); + LI_set_thread_list(CATEGORY_ALIAS, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct aliasent *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +alias_endent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_ALIAS, NULL); +} + +/* HOST */ + +void +freehostent(struct hostent *h) +{ + if (h == NULL) return; + + si_item_t *item = (si_item_t *)((uintptr_t)h - sizeof(si_item_t)); + si_item_release(item); +} + +struct hostent * +gethostbynameerrno(const char *name, int *err) +{ + si_item_t *item; + uint32_t status; + struct in_addr addr4; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + memset(&addr4, 0, sizeof(struct in_addr)); + status = SI_STATUS_NO_ERROR; + item = NULL; + + if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, &status); + else item = si_host_byname(si_search(), name, AF_INET, &status); + + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; + if (err != NULL) *err = status; + + LI_set_thread_item(CATEGORY_HOST + 100, item); + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +struct hostent * +gethostbyname(const char *name) +{ + si_item_t *item; + uint32_t status; + struct in_addr addr4; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + memset(&addr4, 0, sizeof(struct in_addr)); + status = SI_STATUS_NO_ERROR; + item = NULL; + + if (inet_aton(name, &addr4) == 1) item = si_ipnode_byname(si_search(), name, AF_INET, 0, &status); + else item = si_host_byname(si_search(), name, AF_INET, &status); + + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; + h_errno = status; + + LI_set_thread_item(CATEGORY_HOST + 100, item); + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +gethostbyname_async_call(const char *name, si_host_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_HOST; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_HOST_BYNAME, name, NULL, AF_INET, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +mach_port_t +gethostbyname_async_start(const char *name, si_host_async_callback callback, void *context) +{ + return gethostbyname_async_call(name, callback, context); +} + +void +gethostbyname_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +#if 0 +void +gethostbyname_async_handle_reply(void *param) +{ + mach_msg_header_t *msg; + +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + msg = (mach_msg_header_t *)param; + si_async_handle_reply(msg); +} +#endif + +void +gethostbyname_async_handleReply(void *param) +{ + mach_msg_header_t *msg; + +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + msg = (mach_msg_header_t *)param; + si_async_handle_reply(msg); +} + +struct hostent * +gethostbyname2(const char *name, int af) +{ + si_item_t *item; + uint32_t status; + struct in_addr addr4; + struct in6_addr addr6; + si_mod_t *search = si_search(); + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %d\n", __func__, name, af); +#endif + + memset(&addr4, 0, sizeof(struct in_addr)); + memset(&addr6, 0, sizeof(struct in6_addr)); + status = SI_STATUS_NO_ERROR; + item = NULL; + + if (((af == AF_INET) && (inet_aton(name, &addr4) == 1)) || ((af == AF_INET6) && (inet_pton(af, name, &addr6) == 1))) + { + item = si_ipnode_byname(search, name, (uint32_t)af, 0, &status); + } + else + { + item = si_host_byname(search, name, (uint32_t)af, &status); + } + + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; + h_errno = status; + + LI_set_thread_item(CATEGORY_HOST + 100, item); + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +gethostbyname2_async_call(const char *name, int af, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s %d\n", __func__, name, af); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_HOST; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_HOST_BYNAME, name, NULL, (uint32_t)af, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +gethostbyname2_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +void +gethostbyname2_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct hostent * +gethostbyaddr(const void *addr, socklen_t len, int type) +{ + si_item_t *item; + uint32_t status; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-"); +#endif + + status = SI_STATUS_NO_ERROR; + + item = si_host_byaddr(si_search(), addr, (uint32_t)type, &status); + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; + h_errno = status; + + LI_set_thread_item(CATEGORY_HOST + 200, item); + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +gethostbyaddr_async_call(const void *addr, socklen_t len, int type, si_host_async_callback callback, void *context) +{ + si_context_t *sictx; + uint32_t addrlen; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, (type == AF_INET) ? inet_ntoa(*(struct in_addr *)addr) : "-IPv6-"); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_HOST; + sictx->key_offset = 200; + + /* addr is not a C string - pass length in num3 */ + addrlen = len; + return si_async_call(si_search(), SI_CALL_HOST_BYADDR, addr, NULL, (uint32_t)type, 0, addrlen, 0, (void *)si_libinfo_general_callback, sictx); +} + +mach_port_t +gethostbyaddr_async_start(const char *addr, int len, int family, si_host_async_callback callback, void *context) +{ + socklen_t slen = len; + + return gethostbyaddr_async_call(addr, slen, family, callback, context); +} + +void +gethostbyaddr_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +#if 0 +void +gethostbyaddr_async_handle_reply(void *param) +{ + + mach_msg_header_t *msg; + +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + msg = (mach_msg_header_t *)param; + si_async_handle_reply(msg); +} +#endif + +void +gethostbyaddr_async_handleReply(void *param) +{ + mach_msg_header_t *msg; + +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + msg = (mach_msg_header_t *)param; + si_async_handle_reply(msg); +} + +struct hostent * +getipnodebyname(const char *name, int family, int flags, int *err) +{ + si_item_t *item; + uint32_t status; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %d 0x%08x\n", __func__, name, family, flags); +#endif + + status = SI_STATUS_NO_ERROR; + + item = si_ipnode_byname(si_search(), name, family, flags, &status); + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; + if (err != NULL) *err = status; + + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +#if 0 +mach_port_t +getipnodebyname_async_call(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s %d 0x%08x\n", __func__, name, family, flags); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_HOST; + sictx->key_offset = -1; + + return si_async_call(si_search(), SI_CALL_IPNODE_BYNAME, name, NULL, (uint32_t)family, (uint32_t)flags, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +mach_port_t +getipnodebyname_async_start(const char *name, int family, int flags, int *err, si_host_async_callback callback, void *context) +{ + return getipnodebyname_async_call(name, family, flags, err, callback, context); +} + +void +getipnodebyname_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +void +getipnodebyname_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +getipnodebyname_async_handleReply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} +#endif + +static int +is_a4_mapped(const char *s) +{ + int i; + u_int8_t c; + + if (s == NULL) return 0; + + for (i = 0; i < 10; i++) + { + c = s[i]; + if (c != 0x0) return 0; + } + + for (i = 10; i < 12; i++) + { + c = s[i]; + if (c != 0xff) return 0; + } + + return 1; +} + +static int +is_a4_compat(const char *s) +{ + int i; + u_int8_t c; + + if (s == NULL) return 0; + + for (i = 0; i < 12; i++) + { + c = s[i]; + if (c != 0x0) return 0; + } + + /* Check for :: and ::1 */ + for (i = 13; i < 15; i++) + { + /* anything non-zero in these 3 bytes means it's a V4 address */ + c = s[i]; + if (c != 0x0) return 1; + } + + /* Leading 15 bytes are all zero */ + c = s[15]; + if (c == 0x0) return 0; + if (c == 0x1) return 0; + + return 1; +} + +struct hostent * +getipnodebyaddr(const void *src, size_t len, int family, int *err) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-"); +#endif + + if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src))) + { + src += 12; + len = 4; + family = AF_INET; + } + + item = si_host_byaddr(si_search(), src, family, (uint32_t *)err); + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +#if 0 +static void +si_libinfo_ipnode_callback(si_item_t *item, uint32_t status, void *ctx) +{ + si_context_t *sictx; + struct hostent *h; + + if (ctx == NULL) return; + + sictx = (si_context_t *)ctx; + + if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) + { + free(sictx); + si_item_release(item); + return; + } + + if (status >= SI_STATUS_INTERNAL) status = NO_RECOVERY; + + if (item == NULL) + { + ((si_ipnode_async_callback)(sictx->orig_callback))(NULL, status, sictx->orig_context); + return; + } + + h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); + ((si_ipnode_async_callback)(sictx->orig_callback))(h, status, sictx->orig_context); + + free(sictx); +} + +mach_port_t +getipnodebyaddr_async_call(const void *src, socklen_t len, int family, int *err, si_ipnode_async_callback callback, void *context) +{ + si_context_t *sictx; + uint32_t srclen; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, (family == AF_INET) ? inet_ntoa(*(struct in_addr *)src) : "-IPv6-"); +#endif + + if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)src) || is_a4_compat((const char *)src))) + { + src += 12; + len = 4; + family = AF_INET; + } + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_HOST; + sictx->key_offset = -1; + + /* src is not a C string - pass length in num3 */ + srclen = len; + return si_async_call(si_search(), SI_CALL_HOST_BYADDR, src, NULL, (uint32_t)family, 0, srclen, 0, (void *)si_libinfo_ipnode_callback, sictx); +} + +mach_port_t +getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, si_ipnode_async_callback callback, void *context) +{ + socklen_t slen = len; + + return getipnodebyaddr_async_call(addr, slen, family, error, callback, context); +} + +void +getipnodebyaddr_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +void +getipnodebyaddr_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +getipnodebyaddr_async_handleReply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} +#endif + +void +sethostent(int ignored) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_HOST, NULL); +} + +struct hostent * +gethostent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_HOST); + if (list == NULL) + { + list = si_host_all(si_search()); + LI_set_thread_list(CATEGORY_HOST, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endhostent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_HOST, NULL); +} + +/* MAC ADDRESS */ + +int +ether_hostton(const char *name, struct ether_addr *e) +{ + si_item_t *item; + char *cmac; + uint32_t t[6]; + int i; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + if (name == NULL) return -1; + if (e == NULL) return -1; + + item = si_mac_byname(si_search(), name); + LI_set_thread_item(CATEGORY_MAC + 100, item); + if (item == NULL) return -1; + + cmac = (char *)((uintptr_t)item + sizeof(si_item_t)); + + i = sscanf(cmac, " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]); + if (i != 6) return -1; + + for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i]; + return 0; +} + +/* XXX to do? async ether_hostton */ + +int ether_ntohost(char *name, const struct ether_addr *e) +{ + si_item_t *item; + char *cname; + uint32_t i, x[6]; + char str[256]; + + if (name == NULL) return -1; + if (e == NULL) return -1; + + for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i]; + snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]); + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, str); +#endif + + item = si_mac_bymac(si_search(), str); + LI_set_thread_item(CATEGORY_MAC + 200, item); + if (item == NULL) return -1; + + cname = (char *)((uintptr_t)item + sizeof(si_item_t)); + + memcpy(name, cname, strlen(cname) + 1); + return 0; +} + +/* XXX to do? async ether_ntohost */ + +/* NETWORK */ + +struct netent * +getnetbyname(const char *name) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + item = si_network_byname(si_search(), name); + LI_set_thread_item(CATEGORY_NETWORK + 100, item); + if (item == NULL) return NULL; + + return (struct netent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getnetbyname_async_call(const char *name, si_network_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_NETWORK; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_NETWORK_BYNAME, name, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getnetbyname_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct netent * +getnetbyaddr(uint32_t net, int type) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s 0x%08x\n", __func__, net); +#endif + + if (type != AF_INET) return NULL; + + item = si_network_byaddr(si_search(), net); + LI_set_thread_item(CATEGORY_NETWORK + 200, item); + if (item == NULL) return NULL; + + return (struct netent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getnetbyaddr_async_call(uint32_t net, int type, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s 0x%08x\n", __func__, net); +#endif + + if (type != AF_INET) return MACH_PORT_NULL; + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_NETWORK; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_NETWORK_BYADDR, NULL, NULL, net, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getnetbyaddr_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +setnetent(int ignored) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_NETWORK, NULL); +} + +struct netent * +getnetent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_NETWORK); + if (list == NULL) + { + list = si_network_all(si_search()); + LI_set_thread_list(CATEGORY_NETWORK, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct netent *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endnetent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_NETWORK, NULL); +} + +/* SERVICE */ + +struct servent * +getservbyname(const char *name, const char *proto) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %s\n", __func__, name, proto); +#endif + + item = si_service_byname(si_search(), name, proto); + LI_set_thread_item(CATEGORY_SERVICE + 100, item); + if (item == NULL) return NULL; + + return (struct servent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getservbyname_async_call(const char *name, const char *proto, si_service_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s %s\n", __func__, name, proto); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_SERVICE; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_SERVICE_BYNAME, name, proto, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getservbyname_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct servent * +getservbyport(int port, const char *proto) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %d %s\n", __func__, ntohs((uint16_t)port), proto); +#endif + + item = si_service_byport(si_search(), port, proto); + LI_set_thread_item(CATEGORY_SERVICE + 200, item); + if (item == NULL) return NULL; + + return (struct servent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getservbyport_async_call(int port, const char *proto, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %d %s\n", __func__, port, proto); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_SERVICE; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_SERVICE_BYPORT, NULL, proto, port, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getservbyport_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +setservent(int ignored) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_SERVICE, NULL); +} + +struct servent * +getservent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_SERVICE); + if (list == NULL) + { + list = si_service_all(si_search()); + LI_set_thread_list(CATEGORY_SERVICE, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct servent *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endservent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_SERVICE, NULL); +} + +/* PROTOCOL */ + +struct protoent * +getprotobyname(const char *name) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + item = si_protocol_byname(si_search(), name); + LI_set_thread_item(CATEGORY_PROTOCOL + 100, item); + if (item == NULL) return NULL; + + return (struct protoent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getprotobyname_async_call(const char *name, si_protocol_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_PROTOCOL; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNAME, name, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getprotobyname_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct protoent * +getprotobynumber(int number) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %d\n", __func__, number); +#endif + + item = si_protocol_bynumber(si_search(), number); + LI_set_thread_item(CATEGORY_PROTOCOL + 200, item); + if (item == NULL) return NULL; + + return (struct protoent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getprotobynumber_async_call(int number, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %d\n", __func__, number); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_PROTOCOL; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_PROTOCOL_BYNUMBER, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getprotobynumber_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +setprotoent(int ignored) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_PROTOCOL, NULL); +} + +struct protoent * +getprotoent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_PROTOCOL); + if (list == NULL) + { + list = si_protocol_all(si_search()); + LI_set_thread_list(CATEGORY_PROTOCOL, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct protoent *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endprotoent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_PROTOCOL, NULL); +} + +/* RPC */ + +struct rpcent * +getrpcbyname(const char *name) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + item = si_rpc_byname(si_search(), name); + LI_set_thread_item(CATEGORY_RPC + 100, item); + if (item == NULL) return NULL; + + return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getrpcbyname_async_call(const char *name, si_rpc_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, name); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_RPC; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_RPC_BYNAME, name, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getrpcbyname_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct rpcent * +getrpcbynumber +( +#ifdef __LP64__ + int number +#else + long number +#endif +) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %ld\n", __func__, (long int)number); +#endif + + item = si_rpc_bynumber(si_search(), number); + LI_set_thread_item(CATEGORY_RPC + 200, item); + if (item == NULL) return NULL; + + return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getrpcbynumber_async_call(int number, si_group_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %d\n", __func__, number); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_RPC; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_RPC_BYNUMBER, NULL, NULL, number, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getrpcbynumber_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +void +setrpcent(int ignored) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_RPC, NULL); +} + +struct rpcent * +getrpcent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_RPC); + if (list == NULL) + { + list = si_rpc_all(si_search()); + LI_set_thread_list(CATEGORY_RPC, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct rpcent *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endrpcent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_RPC, NULL); +} + +/* FS */ + +struct fstab * +getfsspec(const char *spec) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, spec); +#endif + + item = si_fs_byspec(si_search(), spec); + LI_set_thread_item(CATEGORY_FS + 100, item); + if (item == NULL) return NULL; + + return (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); +} + +struct fstab * +getfsbyname(const char *name) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + return getfsspec(name); +} + +mach_port_t +getfsspec_async_call(const char *spec, si_fs_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, spec); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_FS; + sictx->key_offset = 100; + + return si_async_call(si_search(), SI_CALL_FS_BYSPEC, spec, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getfsspec_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +struct fstab * +getfsfile(const char *file) +{ + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, file); +#endif + + item = si_fs_byfile(si_search(), file); + LI_set_thread_item(CATEGORY_FS + 200, item); + if (item == NULL) return NULL; + + return (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); +} + +mach_port_t +getfsfile_async_call(const char *file, si_fs_async_callback callback, void *context) +{ + si_context_t *sictx; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s\n", __func__, file); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_FS; + sictx->key_offset = 200; + + return si_async_call(si_search(), SI_CALL_FS_BYFILE, file, NULL, 0, 0, 0, 0, (void *)si_libinfo_general_callback, sictx); +} + +void +getfsfile_async_handle_reply(mach_msg_header_t *msg) +{ +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + si_async_handle_reply(msg); +} + +int +setfsent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_FS, NULL); + return 1; +} + +struct fstab * +getfsent(void) +{ + si_list_t *list; + si_item_t *item; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + list = LI_get_thread_list(CATEGORY_FS); + if (list == NULL) + { + list = si_fs_all(si_search()); + LI_set_thread_list(CATEGORY_FS, list); + } + + item = si_list_next(list); + if (item == NULL) return NULL; + + return (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); +} + +void +endfsent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + LI_set_thread_list(CATEGORY_FS, NULL); +} + +/* GETADDRINFO */ + +int +getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res) +{ + si_list_t *list; + uint32_t family, socktype, protocol, flags, status; + struct addrinfo *ai; + + family = AF_UNSPEC; + socktype = SOCK_UNSPEC; + protocol = IPPROTO_UNSPEC; + flags = 0; + status = SI_STATUS_NO_ERROR; + + if (res == NULL) return 0; + *res = NULL; + + if (hints != NULL) + { + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + } + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags); +#endif + + list = si_addrinfo(si_search(), nodename, servname, family, socktype, protocol, flags, &status); + if ((status != SI_STATUS_NO_ERROR) || (list == NULL)) + { + si_list_release(list); + + if (status == SI_STATUS_NO_ERROR) return EAI_NONAME; + else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; + else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; + else status = status - SI_STATUS_EAI_PLUS_100; + return status; + } + + *res = si_list_to_addrinfo(list); + si_list_release(list); + if (*res == NULL) status = EAI_MEMORY; + + /* don't return the canonical name unless asked */ + if ((flags & AI_CANONNAME) == 0) + { + for (ai = *res; ai != NULL; ai = ai->ai_next) + { + free(ai->ai_canonname); + ai->ai_canonname = NULL; + } + } + + return status; +} + +#ifdef CALL_TRACE + +static char * +socket_name(int sock) +{ + static char str[16]; + + switch(sock) + { + case SOCK_UNSPEC: return "SOCK_UNSPEC"; + case SOCK_STREAM: return "SOCK_STREAM"; + case SOCK_DGRAM: return "SOCK_DGRAM"; + } + + sprintf(str, "%d", sock); + return str; +} + +static char * +family_name(int pf) +{ + static char str[16]; + + switch(pf) + { + case PF_UNSPEC: return "PF_UNSPEC"; + case PF_INET: return "PF_INET"; + case PF_INET6: return "PF_INET6"; + }; + + sprintf(str, "%d", pf); + return str; +} + +static char * +protocol_name(int p) +{ + static char str[16]; + + switch(p) + { + case IPPROTO_UNSPEC: return "IPPROTO_UNSPEC"; + case IPPROTO_TCP: return "IPPROTO_TCP"; + case IPPROTO_UDP: return "IPPROTO_UDP"; + } + + sprintf(str, "%d", p); + return str; +} + +static char * +_gai_inet_ntop(struct in6_addr a) +{ + static char buf[128]; + char t[32]; + unsigned short x; + char *p; + int i; + + memset(buf, 0, 128); + + p = (char *)&a.__u6_addr.__u6_addr32; + for (i = 0; i < 8; i++, x += 1) + { + memmove(&x, p, 2); + p += 2; + sprintf(t, "%hx", x); + strcat(buf, t); + if (i < 7) strcat(buf, ":"); + } + + return buf; +} + +static void +fprint_addrinfo(FILE *f, struct addrinfo *a) +{ + int i; + unsigned char v; + struct sockaddr_in *s4; + struct sockaddr_in6 *s6; + + if (a == NULL) return; + + if (a->ai_flags != 0) + { + fprintf(f, "flags ="); + if (a->ai_flags & AI_PASSIVE) fprintf(f, " AI_PASSIVE"); + if (a->ai_flags & AI_CANONNAME) fprintf(f, " AI_CANONNAME"); + if (a->ai_flags & AI_NUMERICHOST) fprintf(f, " AI_NUMERICHOST"); + if (a->ai_flags & AI_NUMERICSERV) fprintf(f, " AI_NUMERICSERV"); + fprintf(f, "\n"); + } + + fprintf(f, "family = %s\n", family_name(a->ai_family)); + fprintf(f, "socktype = %s\n", socket_name(a->ai_socktype)); + fprintf(f, "protocol = %s\n", protocol_name(a->ai_protocol)); + + fprintf(f, "canonical name = "); + if (a->ai_canonname == NULL) fprintf(f, "NULL\n"); + else fprintf(f, "\"%s\"\n", a->ai_canonname); + + fprintf(f, "addrlen = %ld\n", (long int)a->ai_addrlen); + + if (a->ai_addr == NULL) fprintf(f, "sockaddr = NULL\n"); + else + { + if (a->ai_family == PF_INET) + { + s4 = (struct sockaddr_in *)a->ai_addr; + + fprintf(f, "sockaddr_in len = %d\n", s4->sin_len); + fprintf(f, "sockaddr_in family = %s\n", family_name(s4->sin_family)); + fprintf(f, "sockaddr_in port = %hu\n", ntohs(s4->sin_port)); + fprintf(f, "sockaddr_in address = %s\n", inet_ntoa(s4->sin_addr)); + } + else if (a->ai_family == PF_INET6) + { + s6 = (struct sockaddr_in6 *)a->ai_addr; + + fprintf(f, "sockaddr_in6 len = %d\n", s6->sin6_len); + fprintf(f, "sockaddr_in6 family = %s\n", family_name(s6->sin6_family)); + fprintf(f, "sockaddr_in6 port = %hu\n", ntohs(s6->sin6_port)); + fprintf(f, "sockaddr_in6 flowinfo = %d\n", s6->sin6_flowinfo); + fprintf(f, "sockaddr_in6 address = %s\n", _gai_inet_ntop(s6->sin6_addr)); + fprintf(f, "sockaddr_in6 scope_id = %d\n", s6->sin6_scope_id); + } + else + { + fprintf(f, "sockaddr len = %d\n", a->ai_addr->sa_len); + fprintf(f, "sockaddr family = %s\n", family_name(a->ai_addr->sa_family)); + fprintf(f, "sockaddr data = "); + for (i = 0; i < a->ai_addr->sa_len - 2; i++) + { + v = a->ai_addr->sa_data[i]; + fprintf(f, "%02x", v); + } + fprintf(f, "\n"); + } + } + + if (a->ai_next != NULL) + { + fprintf(f, "NEXT --->\n"); + fprint_addrinfo(f, a->ai_next); + } +} + +#endif + +static void +si_libinfo_addrinfo_callback(si_list_t *list, uint32_t status, void *ctx) +{ + si_context_t *sictx; + struct addrinfo *out; + + if (ctx == NULL) + { +#ifdef CALL_TRACE + fprintf(stderr, " %s error no context\n", __func__); +#endif + si_list_release(list); + return; + } + + sictx = (si_context_t *)ctx; + + if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) + { +#ifdef CALL_TRACE + fprintf(stderr, " %s error no callback\n", __func__); +#endif + si_list_release(list); + free(sictx); + return; + } + + if (status != SI_STATUS_NO_ERROR) + { +#ifdef CALL_TRACE + fprintf(stderr, " %s original status %d\n", __func__, status); +#endif + if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; + else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; + else status = status - SI_STATUS_EAI_PLUS_100; + } + + if (list == NULL) + { +#ifdef CALL_TRACE + fprintf(stderr, " %s result NULL status %d (returning EAI_NONAME)\n", __func__, status); +#endif + ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_NONAME, NULL, sictx->orig_context); + free(sictx); + return; + } + + out = si_list_to_addrinfo(list); + si_list_release(list); + if (out == NULL) + { +#ifdef CALL_TRACE + fprintf(stderr, " %s result conversion failed returning NULL status %d (returning EAI_MEMORY)\n", __func__, status); +#endif + ((si_addrinfo_async_callback)(sictx->orig_callback))(EAI_MEMORY, NULL, sictx->orig_context); + free(sictx); + return; + } + +#ifdef CALL_TRACE + fprintf(stderr, " %s %d\n", __func__, status); + fprint_addrinfo(stderr, out); +#endif + ((si_addrinfo_async_callback)(sictx->orig_callback))(status, out, sictx->orig_context); + + free(sictx); +} + +mach_port_t +getaddrinfo_async_call(const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context) +{ + si_context_t *sictx; + uint32_t family, socktype, protocol, flags; + + family = AF_UNSPEC; + socktype = SOCK_UNSPEC; + protocol = IPPROTO_UNSPEC; + flags = 0; + + if (hints != NULL) + { + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + } + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s %s %s %u %u %u 0x%08x\n", __func__, nodename, servname, family, socktype, protocol, flags); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_ADDRINFO; + sictx->key_offset = 0; + + return si_async_call(si_search(), SI_CALL_ADDRINFO, nodename, servname, family, socktype, protocol, flags, (void *)si_libinfo_addrinfo_callback, sictx); +} + +int32_t +getaddrinfo_async_start(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints, si_addrinfo_async_callback callback, void *context) +{ + if (p == NULL) return EAI_SYSTEM; + + *p = getaddrinfo_async_call(nodename, servname, hints, callback, context); + + if (*p == MACH_PORT_NULL) return EAI_SYSTEM; + return 0; +} + +int32_t +getaddrinfo_async_send(mach_port_t *p, const char *nodename, const char *servname, const struct addrinfo *hints) +{ + return getaddrinfo_async_start(p, nodename, servname, hints, NULL, NULL); +} + +int32_t +getaddrinfo_async_receive(mach_port_t p, struct addrinfo **res) +{ + /* unsupported Leopard SPI */ + return EAI_SYSTEM; +} + +void +getaddrinfo_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +int32_t +getaddrinfo_async_handle_reply(void *param) +{ + mach_msg_header_t *msg; + +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + msg = (mach_msg_header_t *)param; + si_async_handle_reply(msg); + + return 0; +} + +/* GETNAMEINFO */ + +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags) +{ + si_item_t *item; + si_nameinfo_t *ni; + uint32_t status, len, wantn, wants; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s\n", __func__); +#endif + + status = SI_STATUS_NO_ERROR; + + wantn = 0; + if ((node != NULL) && (nodelen > 0)) wantn = 1; + + wants = 0; + if ((service != NULL) && (servicelen > 0)) wants = 1; + + if ((wantn == 0) && (wants == 0)) return status; + + if (wantn == 0) flags |= NI_NUMERICHOST; + if (wants == 0) flags |= NI_NUMERICSERV; + + item = si_nameinfo(si_search(), sa, flags, &status); + if ((status != SI_STATUS_NO_ERROR) || (item == NULL)) + { + si_item_release(item); + + if (status == SI_STATUS_NO_ERROR) status = EAI_NONAME; + else if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; + else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; + else status = status - SI_STATUS_EAI_PLUS_100; + return status; + } + + ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t)); + + len = 0; + if (ni->ni_node != NULL) len = strlen(ni->ni_node) + 1; + if ((wantn == 1) && (len > 0)) + { + if (len > nodelen) + { + si_item_release(item); + return EAI_OVERFLOW; + } + + memset(node, 0, nodelen); + memcpy(node, ni->ni_node, len); + } + + len = 0; + if (ni->ni_serv != NULL) len = strlen(ni->ni_serv) + 1; + if ((wants == 1) && (len > 0)) + { + if (len > servicelen) + { + si_item_release(item); + return EAI_OVERFLOW; + } + + memset(service, 0, servicelen); + memcpy(service, ni->ni_serv, len); + } + + si_item_release(item); + return 0; +} + +static void +si_libinfo_nameinfo_callback(si_item_t *item, uint32_t status, void *ctx) +{ + si_context_t *sictx; + si_nameinfo_t *ni; + char *node, *serv; + + if (ctx == NULL) return; + + sictx = (si_context_t *)ctx; + + if ((sictx->orig_callback == NULL) || (status == SI_STATUS_CALL_CANCELLED)) + { + si_item_release(item); + free(sictx); + return; + } + + if (status != SI_STATUS_NO_ERROR) + { + if (status <= SI_STATUS_EAI_PLUS_100) status = EAI_FAIL; + else if (status >= SI_STATUS_ERRNO_PLUS_200) status = EAI_FAIL; + else status = status - SI_STATUS_EAI_PLUS_100; + } + + if (item == NULL) + { + ((si_nameinfo_async_callback)(sictx->orig_callback))(status, NULL, NULL, sictx->orig_context); + free(sictx); + return; + } + + LI_set_thread_item(CATEGORY_NAMEINFO, item); + + node = NULL; + serv = NULL; + + ni = (si_nameinfo_t *)((uintptr_t)item + sizeof(si_item_t)); + if (ni->ni_node != NULL) node = strdup(ni->ni_node); + if (ni->ni_serv != NULL) serv = strdup(ni->ni_serv); + + ((si_nameinfo_async_callback)(sictx->orig_callback))(status, node, serv, sictx->orig_context); + free(sictx); +} + +mach_port_t +getnameinfo_async_call(const struct sockaddr *sa, size_t len, int flags, si_nameinfo_async_callback callback, void *context) +{ + si_context_t *sictx; + uint32_t salen; + +#ifdef CALL_TRACE + fprintf(stderr, ">> %s\n", __func__); +#endif + + sictx = (si_context_t *)calloc(1, sizeof(si_context_t)); + if (sictx == NULL) return MACH_PORT_NULL; + + sictx->orig_callback = callback; + sictx->orig_context = context; + sictx->cat = CATEGORY_ADDRINFO; + sictx->key_offset = 0; + + /* sa is not a C string - pass length in num3 */ + salen = len; + return si_async_call(si_search(), SI_CALL_NAMEINFO, (const char *)sa, NULL, flags, 0, salen, 0, (void *)si_libinfo_nameinfo_callback, sictx); +} + +int32_t +getnameinfo_async_start(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags, si_nameinfo_async_callback callback, void *context) +{ + if (p == NULL) return EAI_SYSTEM; + *p = getnameinfo_async_call(sa, salen, flags, callback, context); + + if (*p == MACH_PORT_NULL) return EAI_SYSTEM; + return 0; +} + +int32_t +getnameinfo_async_send(mach_port_t *p, const struct sockaddr *sa, size_t salen, int flags) +{ + return getnameinfo_async_start(p, sa, salen, flags, NULL, NULL); +} + +void +getnameinfo_async_cancel(mach_port_t p) +{ +#ifdef CALL_TRACE + fprintf(stderr, "-- %s\n", __func__); +#endif + + si_async_cancel(p); +} + +int32_t +getnameinfo_async_handle_reply(void *param) +{ + mach_msg_header_t *msg; + +#ifdef CALL_TRACE + fprintf(stderr, "<< %s\n", __func__); +#endif + + msg = (mach_msg_header_t *)param; + si_async_handle_reply(msg); + + return 0; +} + +/* getpwXXX_r and getgrXXX_r */ + +static int +copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen) +{ + int hsize; + char *bp; + + if (in == NULL) return -1; + if (out == NULL) return -1; + + if (buffer == NULL) buflen = 0; + + /* Calculate size of input */ + hsize = 0; + if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1); + if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1); + if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1); + if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1); + if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1); + if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1); + + /* Check buffer space */ + if (hsize > buflen) return -1; + + /* Copy result into caller's struct passwd, using buffer for memory */ + bp = buffer; + + out->pw_name = NULL; + if (in->pw_name != NULL) + { + out->pw_name = bp; + hsize = strlen(in->pw_name) + 1; + memmove(bp, in->pw_name, hsize); + bp += hsize; + } + + out->pw_passwd = NULL; + if (in->pw_passwd != NULL) + { + out->pw_passwd = bp; + hsize = strlen(in->pw_passwd) + 1; + memmove(bp, in->pw_passwd, hsize); + bp += hsize; + } + + out->pw_uid = in->pw_uid; + + out->pw_gid = in->pw_gid; + + out->pw_change = in->pw_change; + + out->pw_class = NULL; + if (in->pw_class != NULL) + { + out->pw_class = bp; + hsize = strlen(in->pw_class) + 1; + memmove(bp, in->pw_class, hsize); + bp += hsize; + } + + out->pw_gecos = NULL; + if (in->pw_gecos != NULL) + { + out->pw_gecos = bp; + hsize = strlen(in->pw_gecos) + 1; + memmove(bp, in->pw_gecos, hsize); + bp += hsize; + } + + out->pw_dir = NULL; + if (in->pw_dir != NULL) + { + out->pw_dir = bp; + hsize = strlen(in->pw_dir) + 1; + memmove(bp, in->pw_dir, hsize); + bp += hsize; + } + + out->pw_shell = NULL; + if (in->pw_shell != NULL) + { + out->pw_shell = bp; + hsize = strlen(in->pw_shell) + 1; + memmove(bp, in->pw_shell, hsize); + bp += hsize; + } + + out->pw_expire = in->pw_expire; + + return 0; +} + +static int +copy_group_r(struct group *in, struct group *out, char *buffer, int buflen) +{ + int i, len, hsize; + unsigned long addr; + char *bp, *ap; + + if (in == NULL) return -1; + if (out == NULL) return -1; + + if (buffer == NULL) buflen = 0; + + /* Calculate size of input */ + hsize = 0; + if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1); + if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1); + + /* NULL pointer at end of list */ + hsize += sizeof(char *); + + len = 0; + if (in->gr_mem != NULL) + { + for (len = 0; in->gr_mem[len] != NULL; len++) + { + hsize += sizeof(char *); + hsize += (strlen(in->gr_mem[len]) + 1); + } + } + + /* Check buffer space */ + if (hsize > buflen) return -1; + + /* Copy result into caller's struct group, using buffer for memory */ + bp = buffer; + + out->gr_name = NULL; + if (in->gr_name != NULL) + { + out->gr_name = bp; + hsize = strlen(in->gr_name) + 1; + memmove(bp, in->gr_name, hsize); + bp += hsize; + } + + out->gr_passwd = NULL; + if (in->gr_passwd != NULL) + { + out->gr_passwd = bp; + hsize = strlen(in->gr_passwd) + 1; + memmove(bp, in->gr_passwd, hsize); + bp += hsize; + } + + out->gr_gid = in->gr_gid; + + out->gr_mem = NULL; + ap = bp + ((len + 1) * sizeof(char *)); + + if (in->gr_mem != NULL) + { + out->gr_mem = (char **)bp; + for (i = 0; i < len; i++) + { + addr = (unsigned long)ap; + memmove(bp, &addr, sizeof(unsigned long)); + bp += sizeof(unsigned long); + + hsize = strlen(in->gr_mem[i]) + 1; + memmove(ap, in->gr_mem[i], hsize); + ap += hsize; + } + } + + memset(bp, 0, sizeof(unsigned long)); + bp = ap; + + return 0; +} + +int +getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result) +{ + si_item_t *item; + struct group *g; + int status; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + if (result != NULL) *result = NULL; + + if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; + + item = si_group_byname(si_search(), name); + if (item == NULL) return 0; + + g = (struct group *)((uintptr_t)item + sizeof(si_item_t)); + + status = copy_group_r(g, grp, buffer, bufsize); + si_item_release(item); + + if (status != 0) return ERANGE; + + *result = grp; + return 0; +} + +int +getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result) +{ + si_item_t *item; + struct group *g; + int status; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %d\n", __func__, gid); +#endif + + if (result != NULL) *result = NULL; + + if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; + + item = si_group_bygid(si_search(), gid); + if (item == NULL) return 0; + + g = (struct group *)((uintptr_t)item + sizeof(si_item_t)); + + status = copy_group_r(g, grp, buffer, bufsize); + si_item_release(item); + + if (status != 0) return ERANGE; + + *result = grp; + return 0; +} + +int +getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result) +{ + si_item_t *item; + struct passwd *p; + int status; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %s\n", __func__, name); +#endif + + if (result != NULL) *result = NULL; + + if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; + + item = si_user_byname(si_search(), name); + if (item == NULL) return 0; + + p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); + + status = copy_user_r(p, pw, buffer, bufsize); + si_item_release(item); + + if (status != 0) return ERANGE; + + *result = pw; + return 0; +} + +int +getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result) +{ + si_item_t *item; + struct passwd *p; + int status; + +#ifdef CALL_TRACE + fprintf(stderr, "-> %s %d\n", __func__, uid); +#endif + + if (result != NULL) *result = NULL; + + if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE; + + item = si_user_byuid(si_search(), uid); + if (item == NULL) return 0; + + p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); + + status = copy_user_r(p, pw, buffer, bufsize); + si_item_release(item); + + if (status != 0) return ERANGE; + + *result = pw; + return 0; +} + +/* misc */ + +char * +user_from_uid(uid_t uid, int nouser) +{ + struct passwd *pw; + static char buf[16]; + + pw = getpwuid(uid); + if (pw != NULL) return pw->pw_name; + + if (nouser) return NULL; + + snprintf(buf, sizeof(buf), "%u", uid); + return buf; +} + +char * +group_from_gid(gid_t gid, int nogroup) +{ + struct group *gr; + static char buf[16]; + + gr = getgrgid(gid); + if (gr != NULL) return gr->gr_name; + + if (nogroup) return NULL; + + snprintf(buf, sizeof(buf), "%u", gid); + return buf; +} + +/* no longer supported */ + +const prdb_ent * +prdb_getbyname(const char *name) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif + return NULL; +} + +const prdb_ent * +prdb_get(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif + return NULL; +} + +void +prdb_set(const char *name) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif +} + +void +prdb_end(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif +} + +struct bootparamsent * +bootparams_getbyname(const char *name) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif + return NULL; +} + +struct bootparamsent * +bootparams_getent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif + return NULL; +} + +void +bootparams_setent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif +} + +void +bootparams_endent(void) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif +} + +int +bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif + return 0; +} + +int +bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile) +{ +#ifdef CALL_TRACE + fprintf(stderr, "~~ %s\n", __func__); +#endif + return 0; +} + diff --git a/lookup.subproj/libinfo.h b/lookup.subproj/libinfo.h new file mode 100644 index 0000000..a2ae50b --- /dev/null +++ b/lookup.subproj/libinfo.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + +/* + * Most of these async callbacks get data that's held in thread-specific + * memory (specific to the callback thread) that will be re-used by that + * thread automatically on the next call - synchronous or asynchronous - + * of the same routine. For example, an async getpwnam call will use a + * slot in the caller's thread-specifc data to save the returned struct passwd. + * A subsequent call to getpwnam will release the previous entry + * + * Callers of getaddrinfo must free the returned addrinfo list using freeaddrinfo. + * Callbacks for async getaddrinfo lookups must also free the returned addrinfo list. + * + * Callers of getnameinfo supply their own memory for the node and serv names. + * Callbacks for async getnameinfo lookups get node and serv names that reside in + * thread-specific memory that is reclaimed by the libraray. The results must not be freed. + */ +typedef void (*si_user_async_callback)(struct passwd *, void *context); +typedef void (*si_group_async_callback)(struct group *, void *context); +typedef void (*si_grouplist_async_callback)(struct grouplist_s *, void *context); +typedef void (*si_alias_async_callback)(struct aliasent *, void *context); +typedef void (*si_host_async_callback)(struct hostent *, void *context); +typedef void (*si_ipnode_async_callback)(struct hostent *, int32_t status, void *context); +typedef void (*si_network_async_callback)(struct netent *, void *context); +typedef void (*si_service_async_callback)(struct servent *, void *context); +typedef void (*si_protocol_async_callback)(struct protoent *, void *context); +typedef void (*si_rpc_async_callback)(struct rpcent *, void *context); +typedef void (*si_fs_async_callback)(struct fstab *, void *context); +typedef void (*si_addrinfo_async_callback)(int32_t status, struct addrinfo *res, void *context); +typedef void (*si_nameinfo_async_callback)(int32_t status, char *node, char *serv, void *context); +typedef void (*si_setent_async_callback)(void *context); diff --git a/lookup.subproj/lookup.defs b/lookup.subproj/lookup.defs deleted file mode 100644 index 430e2b4..0000000 --- a/lookup.subproj/lookup.defs +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Lookup protocol specification - internal to NeXT - * Copyright (C) 1989 by NeXT, Inc. - * - * History: - * 25-Jun-1998 Umesh Vaishampayan (umeshv@apple.com) - * Ported to MacOSX. - */ - -subsystem lookup 4241775; -serverprefix _; - -import ; - -#include -#include - -type lookup_name = array [256] of MACH_MSG_TYPE_CHAR; -type unit = array [4] of MACH_MSG_TYPE_CHAR; - -/* - * Can't reduce the size of the following without blowing binary compatibility - * with libc (but not libsys, since it is always shared). - */ -type inline_data = array [ * : 4096 ] of unit; -type ooline_data = ^ array [] of unit; - -routine _lookup_link_secure -( - server : mach_port_t; - name : lookup_name; - out procno : int; - UserSecToken token : security_token_t -); - -routine _lookup_all_secure -( - server : mach_port_t; - proc : int; - indata : inline_data; - out outdata : ooline_data; - UserSecToken token : security_token_t -); - -routine _lookup_one_secure -( - server : mach_port_t; - proc : int; - indata : inline_data; - out outdata : inline_data; - UserSecToken token : security_token_t -); - -routine _lookup_ooall_secure -( - server : mach_port_t; - proc : int; - indata : ooline_data; - out outdata : ooline_data; - UserSecToken token : security_token_t -); diff --git a/lookup.subproj/lookup_types.h b/lookup.subproj/lookup_types.h deleted file mode 100644 index 7d8fcd2..0000000 --- a/lookup.subproj/lookup_types.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Lookup protocol definitions - internal to NeXT - * Copyright (C) 1989 by NeXT, Inc. - */ - -/* - * the port to lookupd is obtained through the (internal) - * _lookupd_port() syscall instead of through the nameserver - * with LOOKUP_SERVER_NAME as "C Library Lookup" - */ - -#define UNIT_SIZE 4 - -typedef struct unit { - char data[UNIT_SIZE]; -} unit; - -#define MAX_INLINE_UNITS 4095 -#define MAX_LOOKUP_NAMELEN 256 -#define MAX_INLINE_DATA (MAX_INLINE_UNITS * sizeof(unit)) - -typedef char lookup_name[MAX_LOOKUP_NAMELEN]; -typedef unit inline_data[MAX_INLINE_UNITS]; -typedef char *ooline_data; diff --git a/lookup.subproj/lu_alias.c b/lookup.subproj/lu_alias.c deleted file mode 100644 index 5c7d28a..0000000 --- a/lookup.subproj/lu_alias.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Alias lookup - * Copyright (C) 1989 by NeXT, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "lu_overrides.h" - -#define ENTRY_SIZE sizeof(struct aliasent) -#define ENTRY_KEY _li_data_key_alias - -static pthread_mutex_t _alias_lock = PTHREAD_MUTEX_INITIALIZER; - -static struct aliasent * -copy_alias(struct aliasent *in) -{ - if (in == NULL) return NULL; - - return (struct aliasent *)LI_ils_create("s4*4", in->alias_name, in->alias_members_len, in->alias_members, in->alias_local); -} - -/* - * Extract the next alias entry from a kvarray. - */ -static void * -extract_alias(kvarray_t *in) -{ - struct aliasent tmp; - uint32_t d, k, kcount; - char *empty[1]; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "alias_name")) - { - if (tmp.alias_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.alias_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "alias_members")) - { - if (tmp.alias_members != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.alias_members_len = in->dict[d].vcount[k]; - tmp.alias_members = (char **)in->dict[d].val[k]; - } - else if (!strcmp(in->dict[d].key[k], "alias_local")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.alias_local = atoi(in->dict[d].val[k][0]); - } - } - - if (tmp.alias_name == NULL) tmp.alias_name = ""; - if (tmp.alias_members == NULL) tmp.alias_members = empty; - - return copy_alias(&tmp); -} - -/* - * Send a query to the system information daemon. - */ -static struct aliasent * -ds_alias_getbyname(const char *name) -{ - static int proc = -1; - - return (struct aliasent *)LI_getone("alias_getbyname", &proc, extract_alias, "name", name); -} - -/* - * Clean up / initialize / reinitialize the kvarray used to hold a list of all rpc entries. - */ -static void -ds_alias_endent(void) -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_alias_setent(void) -{ - ds_alias_endent(); -} - -/* - * Get an entry from the getrpcent kvarray. - * Calls the system information daemon if the list doesn't exist (first call), - * or extracts the next entry if the list has been fetched. - */ -static struct aliasent * -ds_alias_getent(void) -{ - static int proc = -1; - - return (struct aliasent *)LI_getent("alias_getent", &proc, extract_alias, ENTRY_KEY, ENTRY_SIZE); -} - -struct aliasent * -alias_getbyname(const char *name) -{ - struct aliasent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - res = ds_alias_getbyname(name); - } - else - { - pthread_mutex_lock(&_alias_lock); - res = copy_alias(_old_alias_getbyname(name)); - pthread_mutex_unlock(&_alias_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct aliasent *)tdata->li_entry; - -} - -struct aliasent * -alias_getent(void) -{ - struct aliasent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - res = ds_alias_getent(); - } - else - { - pthread_mutex_lock(&_alias_lock); - res = copy_alias(_old_alias_getent()); - pthread_mutex_unlock(&_alias_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct aliasent *)tdata->li_entry; - -} - -void -alias_setent(void) -{ - if (_ds_running()) ds_alias_setent(); - else _old_alias_setent(); -} - -void -alias_endent(void) -{ - if (_ds_running()) ds_alias_endent(); - else _old_alias_endent(); -} diff --git a/lookup.subproj/lu_bootp.c b/lookup.subproj/lu_bootp.c deleted file mode 100644 index 90b0ac3..0000000 --- a/lookup.subproj/lu_bootp.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Bootp lookup - netinfo only - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int -bootp_getbyether(struct ether_addr *enaddr, char **name,struct in_addr *ipaddr, char **bootfile) -{ - return 0; -} - -int -bootp_getbyip(struct ether_addr *enaddr, char **name, struct in_addr *ipaddr, char **bootfile) -{ - return 0; -} - diff --git a/lookup.subproj/lu_fstab.c b/lookup.subproj/lu_fstab.c deleted file mode 100644 index 05f7624..0000000 --- a/lookup.subproj/lu_fstab.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * fstab entry lookup - * Copyright (C) 1989 by NeXT, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "lu_overrides.h" - -#define ENTRY_SIZE sizeof(struct fstab) -#define ENTRY_KEY _li_data_key_fstab - -static pthread_mutex_t _fstab_lock = PTHREAD_MUTEX_INITIALIZER; - -#define FS_GET_SPEC 1 -#define FS_GET_FILE 2 -#define FS_GET_ENT 3 - -static struct fstab * -copy_fstab(struct fstab *in) -{ - if (in == NULL) return NULL; - - return (struct fstab *)LI_ils_create("sssss44", in->fs_spec, in->fs_file, in->fs_vfstype, in->fs_mntops, in->fs_type, in->fs_freq, in->fs_passno); -} - -/* - * Extract the next fstab entry from a kvarray. - */ -static void * -extract_fstab(kvarray_t *in) -{ - struct fstab tmp; - uint32_t d, k, kcount; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - memset(&tmp, 0, ENTRY_SIZE); - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "fs_spec")) - { - if (tmp.fs_spec != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.fs_spec = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "fs_file")) - { - if (tmp.fs_file != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.fs_file = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "fs_vfstype")) - { - if (tmp.fs_vfstype != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.fs_vfstype = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "fs_mntops")) - { - if (tmp.fs_mntops != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.fs_mntops = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "fs_type")) - { - if (tmp.fs_type != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.fs_type = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "fs_freq")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.fs_freq = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "fs_passno")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.fs_passno = atoi(in->dict[d].val[k][0]); - } - } - - if (tmp.fs_spec == NULL) tmp.fs_spec = ""; - if (tmp.fs_file == NULL) tmp.fs_file = ""; - if (tmp.fs_vfstype == NULL) tmp.fs_vfstype = ""; - if (tmp.fs_mntops == NULL) tmp.fs_mntops = ""; - if (tmp.fs_type == NULL) tmp.fs_type = ""; - - return copy_fstab(&tmp); -} - -static struct fstab * -ds_getfsspec(const char *name) -{ - static int proc = -1; - - return (struct fstab *)LI_getone("getfsbyname", &proc, extract_fstab, "name", name); -} - -static void -ds_endfsent(void) -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static int -ds_setfsent(void) -{ - ds_endfsent(); - return 1; -} - -static struct fstab * -ds_getfsent() -{ - static int proc = -1; - - return (struct fstab *)LI_getent("getfsent", &proc, extract_fstab, ENTRY_KEY, ENTRY_SIZE); -} - -static struct fstab * -ds_getfsfile(const char *name) -{ - struct fstab *fs; - - if (name == NULL) return NULL; - - ds_setfsent(); - - for (fs = ds_getfsent(); fs != NULL; fs = ds_getfsent()) - { - if (!strcmp(fs->fs_file, name)) return fs; - } - - ds_endfsent(); - - return NULL; -} - -static struct fstab * -getfs(const char *spec, const char *file, int source) -{ - struct fstab *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - switch (source) - { - case FS_GET_SPEC: - res = ds_getfsspec(spec); - break; - case FS_GET_FILE: - res = ds_getfsfile(file); - break; - case FS_GET_ENT: - res = ds_getfsent(); - break; - default: res = NULL; - } - } - else - { - pthread_mutex_lock(&_fstab_lock); - - switch (source) - { - case FS_GET_SPEC: - res = copy_fstab(_old_getfsspec(spec)); - break; - case FS_GET_FILE: - res = copy_fstab(_old_getfsfile(file)); - break; - case FS_GET_ENT: - res = copy_fstab(_old_getfsent()); - break; - default: res = NULL; - } - - pthread_mutex_unlock(&_fstab_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct fstab *)tdata->li_entry; -} - - -struct fstab * -getfsbyname(const char *name) -{ - return getfs(name, NULL, FS_GET_SPEC); -} - -struct fstab * -getfsspec(const char *name) -{ - return getfs(name, NULL, FS_GET_SPEC); -} - -struct fstab * -getfsfile(const char *name) -{ - return getfs(NULL, name, FS_GET_FILE); -} - -struct fstab * -getfsent(void) -{ - return getfs(NULL, NULL, FS_GET_ENT); -} - -int -setfsent(void) -{ - if (_ds_running()) return (ds_setfsent()); - return (_old_setfsent()); -} - -void -endfsent(void) -{ - if (_ds_running()) ds_endfsent(); - else _old_endfsent(); -} diff --git a/lookup.subproj/lu_group.c b/lookup.subproj/lu_group.c deleted file mode 100644 index 5b0e700..0000000 --- a/lookup.subproj/lu_group.c +++ /dev/null @@ -1,904 +0,0 @@ -/* - * Copyright (c) 1999-2007 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Unix group lookup - * Copyright (C) 1989 by NeXT, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "lu_overrides.h" - -#define ENTRY_SIZE sizeof(struct group) -#define ENTRY_KEY _li_data_key_group -#define GROUP_CACHE_SIZE 10 - -static pthread_mutex_t _group_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static void *_group_cache[GROUP_CACHE_SIZE] = { NULL }; -static unsigned int _group_cache_index = 0; -static unsigned int _group_cache_init = 0; - -static pthread_mutex_t _group_lock = PTHREAD_MUTEX_INITIALIZER; - -/* - * Note that we don't include grp.h and define struct group privately in here - * to avoid needing to produce a variant version of setgrent, which changed - * for UXIX03 conformance. - */ -struct group -{ - char *gr_name; - char *gr_passwd; - gid_t gr_gid; - char **gr_mem; -}; - -/* forward */ -int setgrent(void); -struct group *getgrent(void); -void endgrent(void); - -/* - * Support for memberd calls - */ -#define MEMBERD_NAME "com.apple.memberd" -typedef uint32_t GIDArray[16]; -extern kern_return_t memberdDSmig_GetGroups(mach_port_t server, uint32_t uid, uint32_t *numGroups, GIDArray gids, audit_token_t *token); -extern kern_return_t memberdDSmig_GetAllGroups(mach_port_t server, uint32_t uid, uint32_t *numGroups, gid_t **gids, uint32_t *gidsCnt, audit_token_t *token); -__private_extern__ uid_t audit_token_uid(audit_token_t a); - -#define GR_GET_NAME 1 -#define GR_GET_GID 2 -#define GR_GET_ENT 3 - -static struct group * -copy_group(struct group *in) -{ - if (in == NULL) return NULL; - - return (struct group *)LI_ils_create("ss4*", in->gr_name, in->gr_passwd, in->gr_gid, in->gr_mem); -} - -/* - * Extract the next group entry from a kvarray. - */ -static void * -extract_group(kvarray_t *in) -{ - struct group tmp; - uint32_t d, k, kcount; - char *empty[1]; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - tmp.gr_gid = -2; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "gr_name")) - { - if (tmp.gr_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.gr_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "gr_passwd")) - { - if (tmp.gr_passwd != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.gr_passwd = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "gr_gid")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.gr_gid = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "gr_mem")) - { - if (tmp.gr_mem != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.gr_mem = (char **)in->dict[d].val[k]; - } - } - - if (tmp.gr_name == NULL) tmp.gr_name = ""; - if (tmp.gr_passwd == NULL) tmp.gr_passwd = ""; - if (tmp.gr_mem == NULL) tmp.gr_mem = empty; - - return copy_group(&tmp); -} - -static int -copy_group_r(struct group *in, struct group *out, char *buffer, int buflen) -{ - int i, len, hsize; - unsigned long addr; - char *bp, *ap; - - if (in == NULL) return -1; - if (out == NULL) return -1; - - if (buffer == NULL) buflen = 0; - - /* Calculate size of input */ - hsize = 0; - if (in->gr_name != NULL) hsize += (strlen(in->gr_name) + 1); - if (in->gr_passwd != NULL) hsize += (strlen(in->gr_passwd) + 1); - - /* NULL pointer at end of list */ - hsize += sizeof(char *); - - len = 0; - if (in->gr_mem != NULL) - { - for (len = 0; in->gr_mem[len] != NULL; len++) - { - hsize += sizeof(char *); - hsize += (strlen(in->gr_mem[len]) + 1); - } - } - - /* Check buffer space */ - if (hsize > buflen) return -1; - - /* Copy result into caller's struct group, using buffer for memory */ - bp = buffer; - - out->gr_name = NULL; - if (in->gr_name != NULL) - { - out->gr_name = bp; - hsize = strlen(in->gr_name) + 1; - memmove(bp, in->gr_name, hsize); - bp += hsize; - } - - out->gr_passwd = NULL; - if (in->gr_passwd != NULL) - { - out->gr_passwd = bp; - hsize = strlen(in->gr_passwd) + 1; - memmove(bp, in->gr_passwd, hsize); - bp += hsize; - } - - out->gr_gid = in->gr_gid; - - out->gr_mem = NULL; - ap = bp + ((len + 1) * sizeof(char *)); - - if (in->gr_mem != NULL) - { - out->gr_mem = (char **)bp; - for (i = 0; i < len; i++) - { - addr = (unsigned long)ap; - memmove(bp, &addr, sizeof(unsigned long)); - bp += sizeof(unsigned long); - - hsize = strlen(in->gr_mem[i]) + 1; - memmove(ap, in->gr_mem[i], hsize); - ap += hsize; - } - } - - memset(bp, 0, sizeof(unsigned long)); - bp = ap; - - return 0; -} - -static void -cache_group(struct group *gr) -{ - struct group *grcache; - - if (gr == NULL) return; - - pthread_mutex_lock(&_group_cache_lock); - - grcache = copy_group(gr); - - if (_group_cache[_group_cache_index] != NULL) LI_ils_free(_group_cache[_group_cache_index], ENTRY_SIZE); - - _group_cache[_group_cache_index] = grcache; - _group_cache_index = (_group_cache_index + 1) % GROUP_CACHE_SIZE; - - _group_cache_init = 1; - - pthread_mutex_unlock(&_group_cache_lock); -} - -static int -group_cache_check() -{ - uint32_t i, status; - - /* don't consult cache if it has not been initialized */ - if (_group_cache_init == 0) return 1; - - status = LI_L1_cache_check(ENTRY_KEY); - - /* don't consult cache if it is disabled or if we can't validate */ - if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - - /* return 0 if cache is OK */ - if (status == LI_L1_CACHE_OK) return 0; - - /* flush cache */ - pthread_mutex_lock(&_group_cache_lock); - - for (i = 0; i < GROUP_CACHE_SIZE; i++) - { - LI_ils_free(_group_cache[i], ENTRY_SIZE); - _group_cache[i] = NULL; - } - - _group_cache_index = 0; - - pthread_mutex_unlock(&_group_cache_lock); - - /* don't consult cache - it's now empty */ - return 1; -} - - -static struct group * -cache_getgrnam(const char *name) -{ - int i; - struct group *gr, *res; - - if (name == NULL) return NULL; - if (group_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_group_cache_lock); - - for (i = 0; i < GROUP_CACHE_SIZE; i++) - { - gr = (struct group *)_group_cache[i]; - if (gr == NULL) continue; - - if (gr->gr_name == NULL) continue; - - if (!strcmp(name, gr->gr_name)) - { - res = copy_group(gr); - pthread_mutex_unlock(&_group_cache_lock); - return res; - } - } - - pthread_mutex_unlock(&_group_cache_lock); - return NULL; -} - -static struct group * -cache_getgrgid(int gid) -{ - int i; - struct group *gr, *res; - - if (group_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_group_cache_lock); - - for (i = 0; i < GROUP_CACHE_SIZE; i++) - { - gr = (struct group *)_group_cache[i]; - if (gr == NULL) continue; - - if ((gid_t)gid == gr->gr_gid) - { - res = copy_group(gr); - pthread_mutex_unlock(&_group_cache_lock); - return res; - } - } - - pthread_mutex_unlock(&_group_cache_lock); - return NULL; -} - -static struct group * -ds_getgrgid(int gid) -{ - static int proc = -1; - char val[16]; - - snprintf(val, sizeof(val), "%d", gid); - return (struct group *)LI_getone("getgrgid", &proc, extract_group, "gid", val); -} - -static struct group * -ds_getgrnam(const char *name) -{ - static int proc = -1; - - return (struct group *)LI_getone("getgrnam", &proc, extract_group, "name", name); -} - -/* - * add a group to a list - * - * if dupok is non-zero, it's OK to add a duplicate entry - * if dupok is zero, we only add the gid if it is new - * (*listcount) is incremented if the gid was added - * returns -1 if adding the gid would overflow the list - * - */ -static void -_add_group(gid_t g, gid_t **list, uint32_t *count, int dupok) -{ - uint32_t i, n, addit; - - addit = 1; - - if (list == NULL) return; - if (*list == NULL) *count = 0; - - n = *count; - - if (dupok == 0) - { - for (i = 0; (i < n) && (addit == 1); i++) - { - if ((*list)[i] == g) addit = 0; - } - } - - if (addit == 0) return; - - if (*list == NULL) *list = (gid_t *)calloc(1, sizeof(gid_t)); - else *list = (gid_t *)realloc(*list, (n + 1) * sizeof(gid_t)); - - if (*list == NULL) - { - *count = 0; - return; - } - - (*list)[n] = g; - *count = n + 1; -} - -int -_old_getgrouplist(const char *uname, int basegid, int *groups, int *grpcnt) -{ - struct group *grp; - int i, status; - uint32_t maxgroups, gg_count; - gid_t *gg_list; - - status = 0; - maxgroups = (uint32_t)*grpcnt; - *grpcnt = 0; - - gg_list = NULL; - gg_count = 0; - - /* - * When installing primary group, duplicate it; - * the first element of groups is the effective gid - * and will be overwritten when a setgid file is executed. - */ - _add_group(basegid, &gg_list, &gg_count, 0); - _add_group(basegid, &gg_list, &gg_count, 1); - - if (gg_list == NULL) - { - errno = ENOMEM; - return 0; - } - - /* - * Scan the group file to find additional groups. - */ - setgrent(); - - while ((grp = getgrent())) - { - if (grp->gr_gid == (gid_t)basegid) continue; - for (i = 0; grp->gr_mem[i]; i++) - { - if (!strcmp(grp->gr_mem[i], uname)) - { - _add_group(grp->gr_gid, &gg_list, &gg_count, 0); - break; - } - } - } - - endgrent(); - - if (gg_list == NULL) - { - errno = ENOMEM; - return 0; - } - - /* return -1 if the user-supplied list is too short */ - status = 0; - if (gg_count > maxgroups) status = -1; - - /* copy at most maxgroups gids from gg_list to groups */ - for (i = 0; (i < maxgroups) && (i < gg_count); i++) groups[i] = gg_list[i]; - - *grpcnt = gg_count; - free(gg_list); - - return status; -} - -/* - * Guess at the size of a password buffer for getpwnam_r - * pw_name can be MAXLOGNAME + 1 256 - sys/param.h - * pw_passwd can be _PASSWORD_LEN + 1 129 - pwd.h - * pw_dir can be MAXPATHLEN + 1 1025 - sys/syslimits.h - * pw_shell can be MAXPATHLEN + 1025 - sys/syslimits.h - * We allow pw_class and pw_gecos to take a maximum of 4098 bytes (there's no limit on these). - * This adds to 6533 bytes (until one of the constants changes) - */ -#define MAXPWBUF (MAXLOGNAME + 1 + _PASSWORD_LEN + 1 + MAXPATHLEN + 1 + MAXPATHLEN + 1 + 4098) - -/* - * This is the "old" client side routine from memberd. - * It now talks to DirectoryService, but it retains the old style where - * the caller provides an array for the output gids. It fetches the - * user's gids from DS, then copies as many as possible into the - * caller-supplied array. - */ -static int -mbr_getgrouplist(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) -{ - struct passwd p, *res; - char buf[MAXPWBUF]; - kern_return_t kstatus; - uint32_t i, maxgroups, count, gg_count; - int pwstatus; - GIDArray gids; - gid_t *gidptr, *gg_list; - size_t gidptrsz; - int status, do_dealloc; - audit_token_t token; - - if (_ds_port == MACH_PORT_NULL) return 0; - if (name == NULL) return 0; - if (groups == NULL) return 0; - if (grpcnt == NULL) return 0; - - maxgroups = (uint32_t)(*grpcnt); - do_dealloc = 0; - *grpcnt = 0; - gidptr = NULL; - gidptrsz = 0; - gg_list = NULL; - gg_count = 0; - - _add_group(basegid, &gg_list, &gg_count, 0); - if (dupbase != 0) _add_group(basegid, &gg_list, &gg_count, 1); - - if (gg_list == NULL) - { - errno = ENOMEM; - return 0; - } - - memset(&p, 0, sizeof(struct passwd)); - memset(buf, 0, sizeof(buf)); - res = NULL; - - pwstatus = getpwnam_r(name, &p, buf, MAXPWBUF, &res); - if (pwstatus != 0) return 0; - if (res == NULL) return 0; - - count = 0; - memset(&token, 0, sizeof(audit_token_t)); - - kstatus = 0; - if (maxgroups > 16) - { - uint32_t gidptrCnt = 0; - kstatus = memberdDSmig_GetAllGroups(_ds_port, p.pw_uid, &count, &gidptr, &gidptrCnt, &token); - gidptrsz = gidptrCnt * sizeof(gid_t); - do_dealloc = 1; - } - else - { - kstatus = memberdDSmig_GetGroups(_ds_port, p.pw_uid, &count, gids, &token); - gidptr = (gid_t *)gids; - } - - if (kstatus != KERN_SUCCESS) return 0; - if (audit_token_uid(token) != 0) - { - if (gg_list != NULL) free(gg_list); - return 0; - } - - for (i = 0; i < count; i++) _add_group(gidptr[i], &gg_list, &gg_count, 0); - - if ((do_dealloc == 1) && (gidptr != NULL)) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); - - if (gg_list == NULL) - { - errno = ENOMEM; - return 0; - } - - /* return -1 if the user-supplied list is too short */ - status = 0; - if (gg_count > maxgroups) status = -1; - - /* copy at most maxgroups gids from gg_list to groups */ - for (i = 0; (i < maxgroups) && (i < gg_count); i++) groups[i] = gg_list[i]; - - *grpcnt = gg_count; - free(gg_list); - - return status; -} - -/* - * This is the "modern" routine for fetching the group list for a user. - * The grplist output parameter is allocated and filled with the gids - * of the specified user's groups. Returns the number of gids in the - * list or -1 on failure. Caller must free() the returns grplist. - */ -static int32_t -ds_getgrouplist(const char *name, gid_t basegid, gid_t **grplist, int dupbase) -{ - struct passwd p, *res; - char buf[MAXPWBUF]; - kern_return_t kstatus; - uint32_t i, count, gidptrCnt, out_count; - int pwstatus; - gid_t *gidptr, *out_list; - size_t gidptrsz; - audit_token_t token; - - if (_ds_port == MACH_PORT_NULL) return -1; - if (name == NULL) return -1; - if (grplist == NULL) return -1; - - gidptr = NULL; - gidptrCnt = 0; - gidptrsz = 0; - out_list = NULL; - out_count = 0; - - _add_group(basegid, &out_list, &out_count, 0); - if (dupbase != 0) _add_group(basegid, &out_list, &out_count, 1); - - if (out_list == NULL) return -1; - - memset(&p, 0, sizeof(struct passwd)); - memset(buf, 0, sizeof(buf)); - res = NULL; - - pwstatus = getpwnam_r(name, &p, buf, MAXPWBUF, &res); - if (pwstatus != 0) return -1; - if (res == NULL) return -1; - - count = 0; - memset(&token, 0, sizeof(audit_token_t)); - - kstatus = memberdDSmig_GetAllGroups(_ds_port, p.pw_uid, &count, &gidptr, &gidptrCnt, &token); - if (kstatus != KERN_SUCCESS) - { - if (out_list != NULL) free(out_list); - return -1; - } - gidptrsz = gidptrCnt * sizeof(gid_t); - - if (audit_token_uid(token) != 0) - { - if (out_list != NULL) free(out_list); - if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); - return -1; - } - - for (i = 0; i < count; i++) _add_group(gidptr[i], &out_list, &out_count, 0); - - if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz); - - *grplist = out_list; - return out_count; -} - -static int -getgrouplist_internal(const char *name, int basegid, int *groups, int *grpcnt, int dupbase) -{ - int status, in_grpcnt; - - /* - * The man page says that the grpcnt parameter will be set to the actual number - * of groups that were found. Unfortunately, older impementations of this API - * have always set grpcnt to the number of groups that are being returned. - * To prevent regressions in callers of this API, we respect the old and - * incorrect implementation. - */ - - in_grpcnt = *grpcnt; - status = 0; - - if (_ds_running()) status = mbr_getgrouplist(name, basegid, groups, grpcnt, dupbase); - else status = _old_getgrouplist(name, basegid, groups, grpcnt); - - if ((status < 0) && (*grpcnt > in_grpcnt)) *grpcnt = in_grpcnt; - return status; -} - -static int32_t -getgrouplist_internal_2(const char *name, gid_t basegid, gid_t **gid_list, int dupbase) -{ - int status; - uint32_t gid_count; - - if (name == NULL) return -1; - if (gid_list == NULL) return -1; - - *gid_list = NULL; - - if (_ds_running()) return ds_getgrouplist(name, basegid, gid_list, dupbase); - - gid_count = NGROUPS + 1; - *gid_list = (gid_t *)calloc(gid_count, sizeof(gid_t)); - if (*gid_list == NULL) return -1; - - status = _old_getgrouplist(name, basegid, (int *)gid_list, (int *)&gid_count); - if (status < 0) return -1; - return gid_count; -} - -int -getgrouplist(const char *uname, int agroup, int *groups, int *grpcnt) -{ - return getgrouplist_internal(uname, agroup, groups, grpcnt, 0); -} - -int32_t -getgrouplist_2(const char *uname, gid_t agroup, gid_t **groups) -{ - return getgrouplist_internal_2(uname, agroup, groups, 0); -} - -static void -ds_endgrent(void) -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_setgrent(void) -{ - ds_endgrent(); -} - -static struct group * -ds_getgrent() -{ - static int proc = -1; - - return (struct group *)LI_getent("getgrent", &proc, extract_group, ENTRY_KEY, ENTRY_SIZE); -} - -static struct group * -getgr_internal(const char *name, gid_t gid, int source) -{ - struct group *res = NULL; - int add_to_cache; - - add_to_cache = 0; - res = NULL; - - switch (source) - { - case GR_GET_NAME: - res = cache_getgrnam(name); - break; - case GR_GET_GID: - res = cache_getgrgid(gid); - break; - default: res = NULL; - } - - if (res != NULL) - { - } - else if (_ds_running()) - { - switch (source) - { - case GR_GET_NAME: - res = ds_getgrnam(name); - break; - case GR_GET_GID: - res = ds_getgrgid(gid); - break; - case GR_GET_ENT: - res = ds_getgrent(); - break; - default: res = NULL; - } - - if (res != NULL) add_to_cache = 1; - } - else - { - pthread_mutex_lock(&_group_lock); - - switch (source) - { - case GR_GET_NAME: - res = copy_group(_old_getgrnam(name)); - break; - case GR_GET_GID: - res = copy_group(_old_getgrgid(gid)); - break; - case GR_GET_ENT: - res = copy_group(_old_getgrent()); - break; - default: res = NULL; - } - - pthread_mutex_unlock(&_group_lock); - } - - if (add_to_cache == 1) cache_group(res); - - return res; -} - -static struct group * -getgr(const char *name, gid_t gid, int source) -{ - struct group *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - res = getgr_internal(name, gid, source); - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct group *)tdata->li_entry; -} - -static int -getgr_r(const char *name, gid_t gid, int source, struct group *grp, char *buffer, size_t bufsize, struct group **result) -{ - struct group *res = NULL; - int status; - - *result = NULL; - - res = getgr_internal(name, gid, source); - if (res == NULL) return 0; - - status = copy_group_r(res, grp, buffer, bufsize); - - LI_ils_free(res, ENTRY_SIZE); - - if (status != 0) return ERANGE; - - *result = grp; - return 0; -} - -int -initgroups(const char *name, int basegid) -{ - int status, pwstatus, ngroups, groups[NGROUPS]; - struct passwd p, *res; - char buf[MAXPWBUF]; - - /* get the UID for this user */ - memset(&p, 0, sizeof(struct passwd)); - memset(buf, 0, sizeof(buf)); - res = NULL; - - pwstatus = getpwnam_r(name, &p, buf, MAXPWBUF, &res); - if (pwstatus != 0) return -1; - if (res == NULL) return -1; - - ngroups = NGROUPS; - - status = getgrouplist_internal(name, basegid, groups, &ngroups, 0); - if (status < 0) return status; - - status = syscall(SYS_initgroups, ngroups, groups, p.pw_uid); - if (status < 0) return -1; - - return 0; -} - -struct group * -getgrnam(const char *name) -{ - return getgr(name, -2, GR_GET_NAME); -} - -struct group * -getgrgid(gid_t gid) -{ - return getgr(NULL, gid, GR_GET_GID); -} - -struct group * -getgrent(void) -{ - return getgr(NULL, -2, GR_GET_ENT); -} - -int -setgrent(void) -{ - if (_ds_running()) ds_setgrent(); - else _old_setgrent(); - return 1; -} - -void -endgrent(void) -{ - if (_ds_running()) ds_endgrent(); - else _old_endgrent(); -} - -int -getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize, struct group **result) -{ - return getgr_r(name, -2, GR_GET_NAME, grp, buffer, bufsize, result); -} - -int -getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct group **result) -{ - return getgr_r(NULL, gid, GR_GET_GID, grp, buffer, bufsize, result); -} diff --git a/lookup.subproj/lu_host.c b/lookup.subproj/lu_host.c deleted file mode 100644 index d671afa..0000000 --- a/lookup.subproj/lu_host.c +++ /dev/null @@ -1,1404 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lu_host.h" - -#define ENTRY_SIZE sizeof(struct hostent) -#define ENTRY_KEY _li_data_key_host -#define HOST_CACHE_SIZE 20 - -#define CACHE_BYNAME 0 -#define CACHE_BYADDR 1 - -static pthread_mutex_t _host_cache_lock = PTHREAD_MUTEX_INITIALIZER; - -static void *_host_byname_cache[HOST_CACHE_SIZE] = { NULL }; -static int _host_byname_cache_flavor[HOST_CACHE_SIZE] = { WANT_NOTHING }; -static unsigned int _host_byname_cache_index = 0; - -static void *_host_byaddr_cache[HOST_CACHE_SIZE] = { NULL }; -static int _host_byaddr_cache_flavor[HOST_CACHE_SIZE] = { WANT_NOTHING }; -static unsigned int _host_byaddr_cache_index = 0; - -static unsigned int _host_cache_init = 0; - -static pthread_mutex_t _host_lock = PTHREAD_MUTEX_INITIALIZER; - -__private_extern__ struct hostent *LI_files_gethostbyname(const char *name); -__private_extern__ struct hostent *LI_files_gethostbyname2(const char *name, int af); -__private_extern__ struct hostent *LI_files_gethostbyaddr(const void *addr, socklen_t len, int type); -__private_extern__ struct hostent *LI_files_gethostent(); -__private_extern__ void LI_files_sethostent(int stayopen); -__private_extern__ void LI_files_endhostent(); - -extern int _old_ether_hostton(const char *, struct ether_addr *); -extern int _old_ether_ntohost(char *, const struct ether_addr *); - -extern int h_errno; - -#define IPV6_ADDR_LEN 16 -#define IPV4_ADDR_LEN 4 - -void -freehostent(struct hostent *h) -{ - char **aliases; - int i; - - if (LI_ils_free(h, ENTRY_SIZE) == 0) return; - - if (h->h_name != NULL) free(h->h_name); - - aliases = h->h_aliases; - if (aliases != NULL) - { - while (*aliases != NULL) free(*aliases++); - free(h->h_aliases); - } - - if (h->h_addr_list != NULL) - { - for (i = 0; h->h_addr_list[i] != NULL; i++) free(h->h_addr_list[i]); - free(h->h_addr_list); - } - free(h); -} - -static struct hostent * -copy_host(struct hostent *in) -{ - if (in == NULL) return NULL; - - if (in->h_addrtype == AF_INET) - return (struct hostent *)LI_ils_create("s*44a", in->h_name, in->h_aliases, in->h_addrtype, in->h_length, in->h_addr_list); - - if (in->h_addrtype == AF_INET6) - return (struct hostent *)LI_ils_create("s*44c", in->h_name, in->h_aliases, in->h_addrtype, in->h_length, in->h_addr_list); - - return NULL; -} - -static void -_free_addr_list(char **l) -{ - int i; - - if (l == NULL) return; - for (i = 0; l[i] != NULL; i++) free(l[i]); - free(l); -} - -/* map ipv4 addresses and append to v6 list */ -static int -_map_v4(char ***v6, uint32_t n6, char **v4, uint32_t n4) -{ - struct in6_addr a6; - uint32_t i; - - a6.__u6_addr.__u6_addr32[0] = 0x00000000; - a6.__u6_addr.__u6_addr32[1] = 0x00000000; - a6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); - - if (*v6 == NULL) - { - *v6 = (char **)calloc(n4 + 1, sizeof(char *)); - } - else - { - *v6 = (char **)reallocf(*v6, (n6 + n4 + 1) * sizeof(char *)); - } - - if (*v6 == NULL) return -1; - - for (i = 0; i < n4; i++) - { - (*v6)[n6] = (char *)calloc(1, IPV6_ADDR_LEN); - if ((*v6)[n6] == NULL) return -1; - - memcpy(&(a6.__u6_addr.__u6_addr32[3]), v4[i], IPV4_ADDR_LEN); - memcpy((*v6)[n6], &(a6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN); - - n6++; - } - - return 0; -} - -__private_extern__ struct hostent * -extract_host(kvarray_t *in, int want) -{ - struct hostent tmp, *out; - uint32_t i, d, k, kcount, vcount, v4count, v6count; - int status, addr_len; - int family, addr_count; - struct in_addr a4; - struct in6_addr a6; - char **v4addrs, **v6addrs; - char *empty[1]; - - v4addrs = NULL; - v6addrs = NULL; - v4count = 0; - v6count = 0; - addr_count = 0; - addr_len = sizeof(void *); - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - family = AF_INET; - tmp.h_length = IPV4_ADDR_LEN; - - if (want != WANT_A4_ONLY) - { - family = AF_INET6; - tmp.h_length = IPV6_ADDR_LEN; - } - - tmp.h_addrtype = family; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "h_name")) - { - if (tmp.h_name != NULL) continue; - - vcount = in->dict[d].vcount[k]; - if (vcount == 0) continue; - - tmp.h_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "h_aliases")) - { - if (tmp.h_aliases != NULL) continue; - - vcount = in->dict[d].vcount[k]; - if (vcount == 0) continue; - - tmp.h_aliases = (char **)in->dict[d].val[k]; - } - else if (!strcmp(in->dict[d].key[k], "h_ipv4_addr_list")) - { - if (v4addrs != NULL) continue; - - v4count = in->dict[d].vcount[k]; - if (v4count == 0) continue; - - v4addrs = (char **)calloc(v4count + 1, sizeof(char *)); - if (v4addrs == NULL) - { - _free_addr_list(v6addrs); - return NULL; - } - - for (i = 0; i < v4count; i++) - { - v4addrs[i] = calloc(1, IPV4_ADDR_LEN); - if (v4addrs[i] == NULL) - { - _free_addr_list(v4addrs); - _free_addr_list(v6addrs); - return NULL; - } - - memset(&a4, 0, sizeof(struct in_addr)); - status = inet_pton(AF_INET, in->dict[d].val[k][i], &a4); - if (status != 1) - { - _free_addr_list(v4addrs); - _free_addr_list(v6addrs); - return NULL; - } - - memcpy(v4addrs[i], &a4, IPV4_ADDR_LEN); - } - } - else if (!strcmp(in->dict[d].key[k], "h_ipv6_addr_list")) - { - if (v6addrs != NULL) continue; - - v6count = in->dict[d].vcount[k]; - if (v6count == 0) continue; - - v6addrs = (char **)calloc(v6count + 1, sizeof(char *)); - if (v6addrs == NULL) - { - _free_addr_list(v4addrs); - return NULL; - } - - for (i = 0; i < v6count; i++) - { - v6addrs[i] = calloc(1, IPV6_ADDR_LEN); - if (v6addrs[i] == NULL) - { - _free_addr_list(v4addrs); - _free_addr_list(v6addrs); - return NULL; - } - - memset(&a6, 0, sizeof(struct in6_addr)); - status = inet_pton(AF_INET6, in->dict[d].val[k][i], &a6); - if (status != 1) - { - _free_addr_list(v4addrs); - _free_addr_list(v6addrs); - return NULL; - } - - memcpy(v6addrs[i], &(a6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN); - } - } - } - - if (tmp.h_name == NULL) tmp.h_name = ""; - if (tmp.h_aliases == NULL) tmp.h_aliases = empty; - - if (want == WANT_A4_ONLY) - { - _free_addr_list(v6addrs); - if (v4addrs == NULL) return NULL; - - tmp.h_addr_list = v4addrs; - out = copy_host(&tmp); - _free_addr_list(v4addrs); - - return out; - } - else if ((want == WANT_A6_ONLY) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (v6count > 0))) - { - _free_addr_list(v4addrs); - if (v6addrs == NULL) return NULL; - - tmp.h_addr_list = v6addrs; - out = copy_host(&tmp); - _free_addr_list(v6addrs); - - return out; - } - - /* - * At this point, want is WANT_A6_PLUS_MAPPED_A4, WANT_MAPPED_A4_ONLY, - * or WANT_A6_OR_MAPPED_A4_IF_NO_A6. In the last case, there are no ipv6 - * addresses, so that case degenerates into WANT_MAPPED_A4_ONLY. - */ - if (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) want = WANT_MAPPED_A4_ONLY; - - if (want == WANT_MAPPED_A4_ONLY) - { - _free_addr_list(v6addrs); - v6addrs = NULL; - v6count = 0; - } - - status = _map_v4(&v6addrs, v6count, v4addrs, v4count); - _free_addr_list(v4addrs); - if (status != 0) - { - _free_addr_list(v6addrs); - return NULL; - } - - if (v6addrs == NULL) return NULL; - - tmp.h_addr_list = v6addrs; - out = copy_host(&tmp); - _free_addr_list(v6addrs); - - return out; -} - -__private_extern__ struct hostent * -fake_hostent(const char *name, struct in_addr addr) -{ - struct hostent tmp; - char *addrs[2]; - char *aliases[1]; - - if (name == NULL) return NULL; - - memset(&tmp, 0, ENTRY_SIZE); - - tmp.h_name = (char *)name; - tmp.h_addrtype = AF_INET; - tmp.h_length = IPV4_ADDR_LEN; - tmp.h_addr_list = addrs; - addrs[0] = (char *)&(addr.s_addr); - addrs[1] = NULL; - tmp.h_aliases = aliases; - aliases[0] = NULL; - - return copy_host(&tmp); -} - -__private_extern__ struct hostent * -fake_hostent6(const char *name, struct in6_addr addr) -{ - struct hostent tmp; - char *addrs[2]; - char *aliases[1]; - - if (name == NULL) return NULL; - - memset(&tmp, 0, ENTRY_SIZE); - - tmp.h_name = (char *)name; - tmp.h_addrtype = AF_INET6; - tmp.h_length = IPV6_ADDR_LEN; - tmp.h_addr_list = addrs; - addrs[0] = (char *)&(addr.__u6_addr.__u6_addr32[0]); - addrs[1] = NULL; - tmp.h_aliases = aliases; - aliases[0] = NULL; - - return copy_host(&tmp); -} - -static void -cache_host(struct hostent *h, int want, int how) -{ - struct hostent *hcache; - - if (h == NULL) return; - - pthread_mutex_lock(&_host_cache_lock); - - hcache = copy_host(h); - - if (how == CACHE_BYNAME) - { - if (_host_byname_cache[_host_byname_cache_index] != NULL) LI_ils_free(_host_byname_cache[_host_byname_cache_index], ENTRY_SIZE); - - _host_byname_cache[_host_byname_cache_index] = hcache; - _host_byname_cache_flavor[_host_byname_cache_index] = want; - _host_byname_cache_index = (_host_byname_cache_index + 1) % HOST_CACHE_SIZE; - } - else - { - if (_host_byaddr_cache[_host_byaddr_cache_index] != NULL) LI_ils_free(_host_byaddr_cache[_host_byaddr_cache_index], ENTRY_SIZE); - - _host_byaddr_cache[_host_byaddr_cache_index] = hcache; - _host_byaddr_cache_flavor[_host_byaddr_cache_index] = want; - _host_byaddr_cache_index = (_host_byaddr_cache_index + 1) % HOST_CACHE_SIZE; - } - - _host_cache_init = 1; - - pthread_mutex_unlock(&_host_cache_lock); -} - -static int -host_cache_check() -{ - uint32_t i, status; - - /* don't consult cache if it has not been initialized */ - if (_host_cache_init == 0) return 1; - - status = LI_L1_cache_check(ENTRY_KEY); - - /* don't consult cache if it is disabled or if we can't validate */ - if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - - /* return 0 if cache is OK */ - if (status == LI_L1_CACHE_OK) return 0; - - /* flush cache */ - pthread_mutex_lock(&_host_cache_lock); - - for (i = 0; i < HOST_CACHE_SIZE; i++) - { - LI_ils_free(_host_byname_cache[i], ENTRY_SIZE); - _host_byname_cache[i] = NULL; - _host_byname_cache_flavor[i] = WANT_NOTHING; - - LI_ils_free(_host_byaddr_cache[i], ENTRY_SIZE); - _host_byaddr_cache[i] = NULL; - _host_byaddr_cache_flavor[i] = WANT_NOTHING; - } - - _host_byname_cache_index = 0; - _host_byaddr_cache_index = 0; - - pthread_mutex_unlock(&_host_cache_lock); - - /* don't consult cache - it's now empty */ - return 1; -} - - -static struct hostent * -cache_gethostbyname(const char *name, int want) -{ - int i; - struct hostent *h, *res; - char **aliases; - - if (name == NULL) return NULL; - if (host_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_host_cache_lock); - - for (i = 0; i < HOST_CACHE_SIZE; i++) - { - if (_host_byname_cache_flavor[i] != want) continue; - - h = (struct hostent *)_host_byname_cache[i]; - if (h == NULL) continue; - - if (h->h_name != NULL) - { - if (!strcmp(name, h->h_name)) - { - res = copy_host(h); - pthread_mutex_unlock(&_host_cache_lock); - return res; - } - } - - aliases = h->h_aliases; - if (aliases == NULL) - { - pthread_mutex_unlock(&_host_cache_lock); - return NULL; - } - - for (; *aliases != NULL; *aliases++) - { - if (!strcmp(name, *aliases)) - { - res = copy_host(h); - pthread_mutex_unlock(&_host_cache_lock); - return res; - } - } - } - - pthread_mutex_unlock(&_host_cache_lock); - return NULL; -} - -static struct hostent * -cache_gethostbyaddr(const char *addr, int want) -{ - int i, j, len; - struct hostent *h, *res; - - if (addr == NULL) return NULL; - if (host_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_host_cache_lock); - - len = IPV4_ADDR_LEN; - if (want > WANT_A4_ONLY) len = IPV6_ADDR_LEN; - - for (i = 0; i < HOST_CACHE_SIZE; i++) - { - if (_host_byaddr_cache_flavor[i] != want) continue; - - h = (struct hostent *)_host_byaddr_cache[i]; - if (h == NULL) continue; - - if (h->h_addr_list == NULL) continue; - - for (j = 0; h->h_addr_list[j] != NULL; j++) - { - if (memcmp(addr, h->h_addr_list[j], len) == 0) - { - res = copy_host(h); - pthread_mutex_unlock(&_host_cache_lock); - return res; - } - } - } - - pthread_mutex_unlock(&_host_cache_lock); - return NULL; -} - -static struct hostent * -ds_gethostbyaddr(const char *paddr, uint32_t family, int *err) -{ - struct hostent *entry; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - static int proc = -1; - struct in_addr addr4; - struct in6_addr addr6; - char tmp[64]; - int want; - - if (paddr == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc); - if (status != KERN_SUCCESS) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - } - - memset(&addr4, 0, sizeof(struct in_addr)); - memset(&addr6, 0, sizeof(struct in6_addr)); - memset(tmp, 0, sizeof(tmp)); - want = WANT_A4_ONLY; - - if (family == AF_INET) - { - want = WANT_A4_ONLY; - memcpy(&(addr4.s_addr), paddr, IPV4_ADDR_LEN); - if (inet_ntop(family, &addr4, tmp, sizeof(tmp)) == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - } - else if (family == AF_INET6) - { - want = WANT_A6_ONLY; - memcpy(addr6.s6_addr, paddr, IPV6_ADDR_LEN); - if (inet_ntop(family, &addr6, tmp, sizeof(tmp)) == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - } - else - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - request = kvbuf_query("ksku", "address", tmp, "family", family); - if (request == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - if (err != NULL) *err = 0; - entry = extract_host(reply, want); - - if ((entry == NULL) && (err != NULL)) *err = HOST_NOT_FOUND; - kvarray_free(reply); - - return entry; -} - -static struct hostent * -ds_gethostbyname(const char *name, uint32_t want, int *err) -{ - struct hostent *entry; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - static int proc = -1; - uint32_t want4, want6; - - want4 = 1; - want6 = 1; - - if (want == WANT_A4_ONLY) want6 = 0; - else if (want == WANT_A6_ONLY) want4 = 0; - else if (WANT_MAPPED_A4_ONLY) want6 = 0; - - if (name == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc); - if (status != KERN_SUCCESS) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - } - - request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6); - if (request == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - if (err != NULL) *err = 0; - entry = extract_host(reply, want); - if ((entry == NULL) && (err != NULL)) *err = HOST_NOT_FOUND; - kvarray_free(reply); - - return entry; -} - -static void -ds_endhostent() -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_sethostent() -{ - ds_endhostent(); -} - -static struct hostent * -ds_gethostent(int *err) -{ - struct hostent *entry; - struct li_thread_info *tdata; - kvarray_t *reply, *vma; - kern_return_t status; - static int proc = -1; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - if (tdata->li_vm == NULL) - { - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostent", &proc); - if (status != KERN_SUCCESS) - { - if (err != NULL) *err = NO_RECOVERY; - LI_data_free_kvarray(tdata); - tdata->li_vm = NULL; - return NULL; - } - } - - reply = NULL; - status = LI_DSLookupQuery(proc, NULL, &reply); - - if (status != KERN_SUCCESS) - { - if (err != NULL) *err = NO_RECOVERY; - LI_data_free_kvarray(tdata); - tdata->li_vm = NULL; - return NULL; - } - - tdata->li_vm = (char *)reply; - } - - if (err != NULL) *err = 0; - - vma = (kvarray_t *)(tdata->li_vm); - if (vma == NULL) - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - - /* - * gethostent only returns IPv4 addresses, but the reply - * from Directory Service may contain a mix of IPv4 and Ipv6 - * entries. extract_host will return NULL if the current - * dictionary is not the family we want, so we loop until - * we get the next IPv4 entry or we run out of entries. - */ - entry = NULL; - while ((vma->curr < vma->count) && (entry == NULL)) - { - entry = extract_host(vma, WANT_A4_ONLY); - } - - if (entry == NULL) - { - if (err != NULL) *err = HOST_NOT_FOUND; - LI_data_free_kvarray(tdata); - tdata->li_vm = NULL; - return NULL; - } - - return entry; -} - -static struct hostent * -gethostbyaddrerrno(const char *addr, int len, uint32_t family, int *err) -{ - struct hostent *res = NULL; - int want, add_to_cache; - - if (err != NULL) *err = 0; - - want = WANT_A4_ONLY; - if (family == AF_INET6) want = WANT_A6_ONLY; - - if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) - { - addr += 12; - len = 4; - family = AF_INET; - want = WANT_MAPPED_A4_ONLY; - } - - add_to_cache = 0; - res = cache_gethostbyaddr(addr, want); - - if (res != NULL) - { - } - else if (_ds_running()) - { - res = ds_gethostbyaddr(addr, family, err); - if (res != NULL) add_to_cache = 1; - } - else - { - pthread_mutex_lock(&_host_lock); - res = copy_host(LI_files_gethostbyaddr(addr, len, family)); - if (err != NULL) *err = h_errno; - pthread_mutex_unlock(&_host_lock); - } - - if (add_to_cache == 1) cache_host(res, want, CACHE_BYADDR); - - return res; -} - -struct hostent * -gethostbyaddr(const void *addr, socklen_t len, int type) -{ - struct hostent *res; - struct li_thread_info *tdata; - - res = gethostbyaddrerrno(addr, len, type, &h_errno); - if (res == NULL) return NULL; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct hostent *)tdata->li_entry; -} - -struct hostent * -gethostbynameerrno(const char *name, int *err) -{ - struct hostent *res = NULL; - struct in_addr addr; - int i, is_addr, add_to_cache; - - if (err != NULL) *err = 0; - - /* - * If name is all dots and digits without a trailing dot, - * call inet_aton. If it's OK, return a fake entry. - * Otherwise, return an error. - * - * If name has alpha or ends with a dot, proceed as usual... - */ - if (name == NULL) - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - - if (name[0] == '\0') - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - - is_addr = 1; - for (i = 0; name[i] != '\0'; i++) - { - if (name[i] == '.') continue; - if ((name[i] >= '0') && (name[i] <= '9')) continue; - is_addr = 0; - break; - } - - if ((is_addr == 1) && (name[i-1] == '.')) is_addr = 0; - - res = NULL; - add_to_cache = 0; - - if (is_addr == 1) - { - if (inet_aton(name, &addr) == 0) - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - res = fake_hostent(name, addr); - } - - if (res == NULL) - { - res = cache_gethostbyname(name, WANT_A4_ONLY); - } - - if (res != NULL) - { - } - else if (_ds_running()) - { - res = ds_gethostbyname(name, WANT_A4_ONLY, err); - if (res != NULL) add_to_cache = 1; - } - else - { - pthread_mutex_lock(&_host_lock); - res = copy_host(LI_files_gethostbyname(name)); - if (err != NULL) *err = h_errno; - pthread_mutex_unlock(&_host_lock); - } - - if (res == NULL) - { - if (inet_aton(name, &addr) == 0) - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - - res = gethostbyaddrerrno((char *)&addr, sizeof(addr), AF_INET, err); - if (res == NULL) - { - res = fake_hostent(name, addr); - } - } - - if (add_to_cache == 1) cache_host(res, WANT_A4_ONLY, CACHE_BYNAME); - - return res; -} - -struct hostent * -gethostbyname(const char *name) -{ - struct hostent *res; - struct li_thread_info *tdata; - - res = gethostbynameerrno(name, &h_errno); - if (res == NULL) return NULL; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct hostent *)tdata->li_entry; -} - -struct hostent * -gethostbyname2(const char *name, int family) -{ - struct hostent *res; - struct li_thread_info *tdata; - - res = getipnodebyname(name, family, 0, &h_errno); - if (res == NULL) - { - errno = EAFNOSUPPORT; - return NULL; - } - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct hostent *)tdata->li_entry; -} - -struct hostent * -gethostent(void) -{ - struct hostent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - res = ds_gethostent(&h_errno); - } - else - { - pthread_mutex_lock(&_host_lock); - res = copy_host(LI_files_gethostent()); - pthread_mutex_unlock(&_host_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct hostent *)tdata->li_entry; -} - -void -sethostent(int stayopen) -{ - if (_ds_running()) ds_sethostent(); - else LI_files_sethostent(stayopen); -} - -void -endhostent(void) -{ - if (_ds_running()) ds_endhostent(); - else LI_files_endhostent(); -} - -__private_extern__ int -is_a4_mapped(const char *s) -{ - int i; - u_int8_t c; - - if (s == NULL) return 0; - - for (i = 0; i < 10; i++) - { - c = s[i]; - if (c != 0x0) return 0; - } - - for (i = 10; i < 12; i++) - { - c = s[i]; - if (c != 0xff) return 0; - } - - return 1; -} - -__private_extern__ int -is_a4_compat(const char *s) -{ - int i; - u_int8_t c; - - if (s == NULL) return 0; - - for (i = 0; i < 12; i++) - { - c = s[i]; - if (c != 0x0) return 0; - } - - /* Check for :: and ::1 */ - for (i = 13; i < 15; i++) - { - /* anything non-zero in these 3 bytes means it's a V4 address */ - c = s[i]; - if (c != 0x0) return 1; - } - - /* Leading 15 bytes are all zero */ - c = s[15]; - if (c == 0x0) return 0; - if (c == 0x1) return 0; - - return 1; -} - -struct hostent * -getipnodebyaddr(const void *src, size_t len, int family, int *err) -{ - struct hostent *res; - - if (err != NULL) *err = 0; - - res = gethostbyaddrerrno((const char *)src, len, family, err); - if (res == NULL) return NULL; - - if (res->h_name == NULL) - { - freehostent(res); - return NULL; - } - - return res; -} - -struct hostent * -getipnodebyname(const char *name, int family, int flags, int *err) -{ - int status, want, if4, if6, add_to_cache; - struct hostent *res; - struct ifaddrs *ifa, *ifap; - struct in_addr addr4; - struct in6_addr addr6; - - memset(&addr4, 0, sizeof(struct in_addr)); - memset(&addr6, 0, sizeof(struct in6_addr)); - - if (err != NULL) *err = 0; - - if (family == AF_INET) - { - status = inet_aton(name, &addr4); - if (status == 1) - { - /* return a fake hostent */ - res = fake_hostent(name, addr4); - return res; - } - } - else if (family == AF_INET6) - { - status = inet_pton(family, name, &addr6); - if (status == 1) - { - /* return a fake hostent */ - res = fake_hostent6(name, addr6); - return res; - } - - status = inet_aton(name, &addr4); - if (status == 1) - { - if (!(flags & (AI_V4MAPPED|AI_V4MAPPED_CFG))) - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - - addr6.__u6_addr.__u6_addr32[0] = 0x00000000; - addr6.__u6_addr.__u6_addr32[1] = 0x00000000; - addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); - memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr4.s_addr), IPV4_ADDR_LEN); - - /* return a fake hostent */ - res = fake_hostent6(name, addr6); - return res; - } - } - else - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - /* - * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have. - */ - - if4 = 0; - if6 = 0; - - if (flags & AI_ADDRCONFIG) - { - if (getifaddrs(&ifa) < 0) - { - if (err != NULL) *err = NO_RECOVERY; - return NULL; - } - - for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) - { - if (ifap->ifa_addr == NULL) continue; - if ((ifap->ifa_flags & IFF_UP) == 0) continue; - if (ifap->ifa_addr->sa_family == AF_INET) if4++; - else if (ifap->ifa_addr->sa_family == AF_INET6) if6++; - } - - freeifaddrs(ifa); - - /* Bail out if there are no interfaces */ - if ((if4 == 0) && (if6 == 0)) - { - if (err != NULL) *err = NO_ADDRESS; - return NULL; - } - } - - /* - * Figure out what we want. - * If user asked for AF_INET, we only want V4 addresses. - */ - want = WANT_A4_ONLY; - - if (family == AF_INET) - { - if ((flags & AI_ADDRCONFIG) && (if4 == 0)) - { - if (err != NULL) *err = NO_ADDRESS; - return NULL; - } - } - else - { - /* family == AF_INET6 */ - want = WANT_A6_ONLY; - - if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)) - { - if (flags & AI_ALL) - { - want = WANT_A6_PLUS_MAPPED_A4; - } - else - { - want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; - } - } - else - { - if ((flags & AI_ADDRCONFIG) && (if6 == 0)) - { - if (err != NULL) *err = NO_ADDRESS; - return NULL; - } - } - } - - add_to_cache = 0; - res = cache_gethostbyname(name, want); - - if (res != NULL) - { - } - else if (_ds_running()) - { - res = ds_gethostbyname(name, want, err); - if (res != NULL) add_to_cache = 1; - } - else - { - pthread_mutex_lock(&_host_lock); - res = copy_host(LI_files_gethostbyname2(name, family)); - if (err != NULL) *err = h_errno; - pthread_mutex_unlock(&_host_lock); - } - - if (res == NULL) - { - if (err != NULL) *err = HOST_NOT_FOUND; - return NULL; - } - - if (add_to_cache == 1) cache_host(res, want, CACHE_BYNAME); - - return res; -} - -static int -ether_extract_mac(kvarray_t *in, struct ether_addr *e) -{ - uint32_t d, k, kcount, t[6]; - int i; - - if (in == NULL) return -1; - if (e == NULL) return -1; - - d = in->curr; - in->curr++; - - if (d >= in->count) return -1; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "mac")) - { - if (in->dict[d].vcount[k] == 0) continue; - i = sscanf(in->dict[d].val[k][0], " %x:%x:%x:%x:%x:%x", &t[0], &t[1], &t[2], &t[3], &t[4], &t[5]); - if (i != 6) return -1; - for (i = 0; i < 6; i++) e->ether_addr_octet[i] = t[i]; - return 0; - } - } - - return -1; -} - -/* - * Given a host's name, this routine returns its 48 bit ethernet address. - * Returns zero if successful, non-zero otherwise. - */ -static int -ds_ether_hostton(const char *host, struct ether_addr *e) -{ - static int proc = -1; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - - if (host == NULL) return -1; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getmacbyname", &proc); - if (status != KERN_SUCCESS) return -1; - } - - request = kvbuf_query_key_val("name", host); - if (request == NULL) return -1; - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) return -1; - - status = ether_extract_mac(reply, e); - kvarray_free(reply); - - return status; -} - -static int -ether_extract_name(kvarray_t *in, char *name) -{ - uint32_t d, k, kcount; - - if (in == NULL) return -1; - if (name == NULL) return -1; - - d = in->curr; - in->curr++; - - if (d >= in->count) return -1; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "name")) - { - memcpy(name, in->dict[d].val[k][0], strlen(in->dict[d].val[k][0]) + 1); - return 0; - } - } - - return -1; -} - -/* - * Given a 48 bit ethernet address, this routine return its host name. - * Returns zero if successful, non-zero otherwise. - */ -static int -ds_ether_ntohost(char *host, const struct ether_addr *e) -{ - uint32_t i, x[6]; - char str[256]; - static int proc = -1; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - - if (host == NULL) return -1; - if (e == NULL) return -1; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbymac", &proc); - if (status != KERN_SUCCESS) return -1; - } - - for (i = 0; i < 6; i++) x[i] = e->ether_addr_octet[i]; - sprintf(str, "%x:%x:%x:%x:%x:%x", x[0], x[1], x[2], x[3], x[4], x[5]); - - request = kvbuf_query_key_val("mac", str); - if (request == NULL) return -1; - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) return -1; - - status = ether_extract_name(reply, host); - kvarray_free(reply); - - return status; -} - -int -ether_hostton(const char *host, struct ether_addr *e) -{ - if (_ds_running()) return ds_ether_hostton(host, e); - return _old_ether_hostton(host, e); -} - -int -ether_ntohost(char *host, const struct ether_addr *e) -{ - if (_ds_running()) return ds_ether_ntohost(host, e); - return _old_ether_ntohost(host, e); -} diff --git a/lookup.subproj/lu_host.h b/lookup.subproj/lu_host.h deleted file mode 100644 index 109fb71..0000000 --- a/lookup.subproj/lu_host.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 2002 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _LU_HOST_H_ -#define _LU_HOST_H_ - -#include -#include "lu_utils.h" - -#define WANT_NOTHING 0 -#define WANT_A4_ONLY 1 -#define WANT_A6_ONLY 2 -#define WANT_A6_PLUS_MAPPED_A4 3 -#define WANT_MAPPED_A4_ONLY 4 - -/* ONLY TO BE USED BY getipv6nodebyaddr */ -#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 5 - - -__BEGIN_DECLS - -void free_host_data(struct hostent *h); -struct hostent *extract_host(kvarray_t *in, int want); -struct hostent *fake_hostent(const char *name, struct in_addr addr); -struct hostent *fake_hostent6(const char *name, struct in6_addr addr); -int is_a4_mapped(const char *s); -int is_a4_compat(const char *s); - -__END_DECLS - -#endif /* ! _LU_HOST_H_ */ diff --git a/lookup.subproj/lu_host_async.c b/lookup.subproj/lu_host_async.c deleted file mode 100644 index 14a0eca..0000000 --- a/lookup.subproj/lu_host_async.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 2002 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lu_host.h" -#include "lu_utils.h" - -#define IPV6_ADDR_LEN 16 -#define IPV4_ADDR_LEN 4 - -typedef struct -{ - void *user_context; - int want; -} my_context_t; - -mach_port_t -gethostbyaddr_async_start(const char *addr, int len, int family, gethostbyaddr_async_callback callback, void *context) -{ - static int proc = 1; - int32_t want, status; - kvbuf_t *request; - mach_port_t mp; - my_context_t *my_context; - - mp = MACH_PORT_NULL; - - if (addr == NULL) return MACH_PORT_NULL; - if (len == 0) return MACH_PORT_NULL; - if ((family != AF_INET) && (family != AF_INET6)) return MACH_PORT_NULL; - - want = WANT_A4_ONLY; - if (family == AF_INET6) want = WANT_A6_ONLY; - - if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) - { - addr += 12; - len = 4; - family = AF_INET; - want = WANT_MAPPED_A4_ONLY; - } - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc); - if (status != KERN_SUCCESS) return MACH_PORT_NULL; - } - - request = kvbuf_query("ksku", "address", addr, "family", want); - if (request == NULL) return MACH_PORT_NULL; - - my_context = (my_context_t *)calloc(1, sizeof(my_context_t)); - if (my_context == NULL) return MACH_PORT_NULL; - - my_context->user_context = context; - my_context->want = want; - - status = LI_async_start(&mp, proc, request, (void *)callback, my_context); - - kvbuf_free(request); - return mp; -} - -void -gethostbyaddr_async_cancel(mach_port_t port) -{ - my_context_t *my_context; - - my_context = NULL; - - LI_async_call_cancel(port, (void **)&my_context); - - if (my_context != NULL) free(my_context); -} - -void -gethostbyaddr_async_handleReply(void *msg) -{ - gethostbyaddr_async_callback callback; - struct hostent *out; - uint32_t len, want; - int status; - kvarray_t *reply; - my_context_t *my_context; - void *context; - - callback = (gethostbyaddr_async_callback)NULL; - my_context = NULL; - context = NULL; - len = 0; - reply = NULL; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context); - if ((status != KERN_SUCCESS) || (reply == NULL)) - { - if (status == MIG_REPLY_MISMATCH) return; - if (callback != NULL) - { - if (my_context != NULL) context = my_context->user_context; - callback(NULL, context); - free(my_context); - return; - } - } - - want = WANT_A4_ONLY; - if (my_context != NULL) - { - context = my_context->user_context; - want = my_context->want; - free(my_context); - } - - out = extract_host(reply, want); - kvarray_free(reply); - - callback(out, context); -} - -mach_port_t -getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, getipnodebyaddr_async_callback callback, void *context) -{ - static int proc = 1; - int32_t want, status; - kvbuf_t *request; - mach_port_t mp; - my_context_t *my_context; - - mp = MACH_PORT_NULL; - - if (addr == NULL) return MACH_PORT_NULL; - if (len == 0) return MACH_PORT_NULL; - if ((family != AF_INET) && (family != AF_INET6)) return MACH_PORT_NULL; - - want = WANT_A4_ONLY; - if (family == AF_INET6) want = WANT_A6_ONLY; - - if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr))) - { - addr += 12; - len = 4; - family = AF_INET; - want = WANT_MAPPED_A4_ONLY; - } - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc); - if (status != KERN_SUCCESS) return MACH_PORT_NULL; - } - - request = kvbuf_query("ksku", "address", addr, "family", want); - if (request == NULL) return MACH_PORT_NULL; - - my_context = (my_context_t *)calloc(1, sizeof(my_context_t)); - if (my_context == NULL) return MACH_PORT_NULL; - - my_context->user_context = context; - my_context->want = want; - - status = LI_async_start(&mp, proc, request, (void *)callback, my_context); - - kvbuf_free(request); - return mp; -} - -void -getipnodebyaddr_async_cancel(mach_port_t port) -{ - my_context_t *my_context; - - my_context = NULL; - - LI_async_call_cancel(port, (void **)&my_context); - - if (my_context != NULL) free(my_context); -} - -void -getipnodebyaddr_async_handleReply(void *msg) -{ - getipnodebyaddr_async_callback callback; - struct hostent *out; - uint32_t len, want; - int status; - kvarray_t *reply; - my_context_t *my_context; - void *context; - - callback = (getipnodebyaddr_async_callback)NULL; - my_context = NULL; - context = NULL; - len = 0; - reply = NULL; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context); - if ((status != KERN_SUCCESS) || (reply == NULL)) - { - if (status == MIG_REPLY_MISMATCH) return; - if (callback != NULL) - { - if (my_context != NULL) context = my_context->user_context; - callback(NULL, NO_RECOVERY, context); - free(my_context); - return; - } - } - - want = WANT_A4_ONLY; - if (my_context != NULL) - { - context = my_context->user_context; - want = my_context->want; - free(my_context); - } - - out = extract_host(reply, want); - kvarray_free(reply); - - if (out == NULL) - { - callback(NULL, HOST_NOT_FOUND, context); - return; - } - - callback(out, 0, context); -} - -mach_port_t -gethostbyname_async_start(const char *name, gethostbyname_async_callback callback, void *context) -{ - static int proc = 1; - int32_t status; - kvbuf_t *request; - mach_port_t mp; - - mp = MACH_PORT_NULL; - - if (name == NULL) return MACH_PORT_NULL; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc); - if (status != KERN_SUCCESS) return MACH_PORT_NULL; - } - - request = kvbuf_query("ksksks", "name", name, "ipv4", "1", "ipv6", "0"); - if (request == NULL) return MACH_PORT_NULL; - - status = LI_async_start(&mp, proc, request, (void *)callback, context); - - kvbuf_free(request); - return mp; -} - -void -gethostbyname_async_cancel(mach_port_t port) -{ - LI_async_call_cancel(port, NULL); -} - -void -gethostbyname_async_handleReply(void *msg) -{ - gethostbyname_async_callback callback; - struct hostent *out; - uint32_t len; - int status; - kvarray_t *reply; - void *context; - - callback = (gethostbyname_async_callback)NULL; - context = NULL; - len = 0; - reply = NULL; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&context); - if ((status != KERN_SUCCESS) || (reply == NULL)) - { - if (status == MIG_REPLY_MISMATCH) return; - if (callback != NULL) - { - callback(NULL, context); - return; - } - } - - out = extract_host(reply, AF_INET); - kvarray_free(reply); - - callback(out, context); -} - -mach_port_t -getipnodebyname_async_start(const char *name, int family, int flags, int *err, getipnodebyname_async_callback callback, void *context) -{ - static int proc = 1; - int32_t status, want, want4, want6, if4, if6; - kvbuf_t *request; - mach_port_t mp; - struct ifaddrs *ifa, *ifap; - struct in_addr addr4; - struct in6_addr addr6; - my_context_t *my_context; - - if (name == NULL) return MACH_PORT_NULL; - - if (err != NULL) *err = 0; - - if4 = 0; - if6 = 0; - mp = MACH_PORT_NULL; - memset(&addr4, 0, sizeof(struct in_addr)); - memset(&addr6, 0, sizeof(struct in6_addr)); - - if (flags & AI_ADDRCONFIG) - { - if (getifaddrs(&ifa) < 0) - { - if (err != NULL) *err = NO_RECOVERY; - return MACH_PORT_NULL; - } - - for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) - { - if (ifap->ifa_addr == NULL) continue; - if ((ifap->ifa_flags & IFF_UP) == 0) continue; - if (ifap->ifa_addr->sa_family == AF_INET) if4++; - else if (ifap->ifa_addr->sa_family == AF_INET6) if6++; - } - - freeifaddrs(ifa); - - /* Bail out if there are no interfaces */ - if ((if4 == 0) && (if6 == 0)) - { - if (err != NULL) *err = NO_RECOVERY; - return MACH_PORT_NULL; - } - } - - /* - * Figure out what we want. - * If user asked for AF_INET, we only want V4 addresses. - */ - want = WANT_A4_ONLY; - - if (family == AF_INET) - { - if ((flags & AI_ADDRCONFIG) && (if4 == 0)) - { - if (err != NULL) *err = NO_RECOVERY; - return MACH_PORT_NULL; - } - } - else - { - /* family == AF_INET6 */ - want = WANT_A6_ONLY; - - if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)) - { - if (flags & AI_ALL) - { - want = WANT_A6_PLUS_MAPPED_A4; - } - else - { - want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; - } - } - else - { - if ((flags & AI_ADDRCONFIG) && (if6 == 0)) - { - if (err != NULL) *err = NO_RECOVERY; - return MACH_PORT_NULL; - } - } - } - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc); - if (status != KERN_SUCCESS) return MACH_PORT_NULL; - } - - my_context = (my_context_t *)calloc(1, sizeof(my_context_t)); - if (my_context == NULL) - { - *err = NO_RECOVERY; - return MACH_PORT_NULL; - } - - my_context->user_context = context; - my_context->want = want; - - want4 = 1; - want6 = 1; - - if (want == WANT_A4_ONLY) want6 = 0; - else if (want == WANT_A6_ONLY) want4 = 0; - else if (WANT_MAPPED_A4_ONLY) want6 = 0; - - request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6); - if (request == NULL) return MACH_PORT_NULL; - - status = LI_async_start(&mp, proc, request, (void *)callback, my_context); - - kvbuf_free(request); - return mp; -} - -void -getipnodebyname_async_cancel(mach_port_t port) -{ - my_context_t *my_context; - - my_context = NULL; - - LI_async_call_cancel(port, (void **)&my_context); - - if (my_context != NULL) free(my_context); -} - -void -getipnodebyname_async_handleReply(void *msg) -{ - getipnodebyname_async_callback callback; - struct hostent *out; - uint32_t len, want; - int status, err; - kvarray_t *reply; - my_context_t *my_context; - void *context; - - callback = (getipnodebyname_async_callback)NULL; - my_context = NULL; - context = NULL; - len = 0; - reply = NULL; - - status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context); - if ((status != KERN_SUCCESS) || (reply == NULL)) - { - if (status == MIG_REPLY_MISMATCH) return; - if (callback != NULL) - { - if (my_context != NULL) context = my_context->user_context; - callback(NULL, NO_RECOVERY, context); - free(my_context); - return; - } - } - - want = WANT_A4_ONLY; - if (my_context != NULL) - { - context = my_context->user_context; - want = my_context->want; - free(my_context); - } - - out = extract_host(reply, want); - kvarray_free(reply); - - if (out == NULL) - { - err = HOST_NOT_FOUND; - callback(NULL, err, context); - return; - } - - callback(out, 0, context); -} diff --git a/lookup.subproj/lu_netgroup.c b/lookup.subproj/lu_netgroup.c deleted file mode 100644 index f140a03..0000000 --- a/lookup.subproj/lu_netgroup.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Netgroup lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "lu_overrides.h" - -struct li_netgrent -{ - char *ng_host; - char *ng_user; - char *ng_domain; -}; - -#define ENTRY_SIZE sizeof(struct li_netgrent) -#define ENTRY_KEY _li_data_key_netgroup - -static struct li_netgrent * -copy_netgroup(struct li_netgrent *in) -{ - if (in == NULL) return NULL; - - return (struct li_netgrent *)LI_ils_create("sss", in->ng_host, in->ng_user, in->ng_domain); -} - -/* - * Extract the next netgroup entry from a kvarray. - */ -static struct li_netgrent * -extract_netgroup(kvarray_t *in) -{ - struct li_netgrent tmp; - uint32_t d, k, kcount; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - memset(&tmp, 0, ENTRY_SIZE); - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "user")) - { - if (tmp.ng_user != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.ng_user = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "host")) - { - if (tmp.ng_host != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.ng_host = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "domain")) - { - if (tmp.ng_domain != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.ng_domain = (char *)in->dict[d].val[k][0]; - } - } - - if (tmp.ng_user == NULL) tmp.ng_user = ""; - if (tmp.ng_host == NULL) tmp.ng_host = ""; - if (tmp.ng_domain == NULL) tmp.ng_domain = ""; - - return copy_netgroup(&tmp); -} - -static int -check_innetgr(kvarray_t *in) -{ - uint32_t d, k, kcount; - - if (in == NULL) return 0; - - d = in->curr; - if (d >= in->count) return 0; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "result")) - { - if (in->dict[d].vcount[k] == 0) continue; - return atoi(in->dict[d].val[k][0]); - } - } - - return 0; -} - -static int -ds_innetgr(const char *group, const char *host, const char *user, const char *domain) -{ - int is_innetgr; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - static int proc = -1; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("innetgr", &proc); - if (status != KERN_SUCCESS) return 0; - } - - /* Encode NULL */ - if (group == NULL) group = ""; - if (host == NULL) host = ""; - if (user == NULL) user = ""; - if (domain == NULL) domain = ""; - - request = kvbuf_query("ksksksks", "netgroup", group, "host", host, "user", user, "domain", domain); - if (request == NULL) return 0; - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) return 0; - - is_innetgr = check_innetgr(reply); - kvarray_free(reply); - - return is_innetgr; -} - -static void -ds_endnetgrent(void) -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -/* - * This is different than the other setXXXent routines - * since this is really more like getnetgrbyname() than - * getnetgrent(). - */ -static void -ds_setnetgrent(const char *name) -{ - struct li_thread_info *tdata; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - static int proc = -1; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return; - - if (tdata->li_vm != NULL) return; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getnetgrent", &proc); - if (status != KERN_SUCCESS) - { - LI_data_free_kvarray(tdata); - return; - } - } - - request = kvbuf_query_key_val("netgroup", name); - if (request == NULL) return; - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) - { - LI_data_free_kvarray(tdata); - return; - } - - tdata->li_vm = (char *)reply; -} - - -static struct li_netgrent * -ds_getnetgrent(void) -{ - struct li_netgrent *entry; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - entry = extract_netgroup((kvarray_t *)(tdata->li_vm)); - if (entry == NULL) - { - ds_endnetgrent(); - return NULL; - } - - return entry; -} - -int -innetgr(const char *group, const char *host, const char *user, - const char *domain) -{ - if (_ds_running()) return (ds_innetgr(group, host, user, domain)); - return 0; -} - -int -getnetgrent(char **host, char **user, char **domain) -{ - struct li_netgrent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return 0; - - res = NULL; - if (_ds_running()) res = ds_getnetgrent(); - - LI_data_recycle(tdata, res, ENTRY_SIZE); - if (res == NULL) return 0; - - if (host != NULL) *host = res->ng_host; - if (user != NULL) *user = res->ng_user; - if (domain != NULL) *domain = res->ng_domain; - - return 1; -} - -void -setnetgrent(const char *name) -{ - if (_ds_running()) ds_setnetgrent(name); -} - -void -endnetgrent(void) -{ - if (_ds_running()) ds_endnetgrent(); -} diff --git a/lookup.subproj/lu_network.c b/lookup.subproj/lu_network.c deleted file mode 100644 index 4f74394..0000000 --- a/lookup.subproj/lu_network.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * network lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" - -static pthread_mutex_t _network_lock = PTHREAD_MUTEX_INITIALIZER; - -#define N_GET_NAME 1 -#define N_GET_ADDR 2 -#define N_GET_ENT 3 - -extern struct netent *_res_getnetbyaddr(); -extern struct netent *_res_getnetbyname(); -extern struct netent *_old_getnetbyaddr(); -extern struct netent *_old_getnetbyname(); -extern struct netent *_old_getnetent(); -extern void _old_setnetent(); -extern void _old_endnetent(); - -#define ENTRY_SIZE sizeof(struct netent) -#define ENTRY_KEY _li_data_key_network - -static struct netent * -copy_network(struct netent *in) -{ - if (in == NULL) return NULL; - - return (struct netent *)LI_ils_create("s*44", in->n_name, in->n_aliases, in->n_addrtype, in->n_net); -} - -/* - * Extract the next network entry from a kvarray. - */ -static void * -extract_network(kvarray_t *in) -{ - struct netent tmp; - uint32_t d, k, kcount; - char *empty[1]; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - tmp.n_addrtype = AF_INET; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "n_name")) - { - if (tmp.n_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.n_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "n_net")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.n_net = inet_network(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "n_addrtype")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.n_addrtype = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "n_aliases")) - { - if (tmp.n_aliases != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.n_aliases = (char **)in->dict[d].val[k]; - } - } - - if (tmp.n_name == NULL) tmp.n_name = ""; - if (tmp.n_aliases == NULL) tmp.n_aliases = empty; - - return copy_network(&tmp); -} - -static struct netent * -ds_getnetbyaddr(uint32_t addr, int type) -{ - static int proc = -1; - unsigned char f1, f2, f3; - char val[64]; - - if (type != AF_INET) return NULL; - - f1 = addr & 0xff; - addr >>= 8; - f2 = addr & 0xff; - addr >>= 8; - f3 = addr & 0xff; - - if (f3 != 0) snprintf(val, sizeof(val), "%u.%u.%u", f3, f2, f1); - else if (f2 != 0) snprintf(val, sizeof(val), "%u.%u", f2, f1); - else snprintf(val, sizeof(val), "%u", f1); - - return (struct netent *)LI_getone("getnetbyaddr", &proc, extract_network, "net", val); -} - -static struct netent * -ds_getnetbyname(const char *name) -{ - static int proc = -1; - - return (struct netent *)LI_getone("getnetbyname", &proc, extract_network, "name", name); -} - -static void -ds_endnetent() -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_setnetent() -{ - ds_endnetent(); -} - -static struct netent * -ds_getnetent() -{ - static int proc = -1; - - return (struct netent *)LI_getent("getnetent", &proc, extract_network, ENTRY_KEY, ENTRY_SIZE); -} - -static struct netent * -getnet(const char *name, uint32_t addr, int type, int source) -{ - struct netent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - switch (source) - { - case N_GET_NAME: - res = ds_getnetbyname(name); - break; - case N_GET_ADDR: - res = ds_getnetbyaddr(addr, type); - break; - case N_GET_ENT: - res = ds_getnetent(); - break; - default: res = NULL; - } - } - else - { - pthread_mutex_lock(&_network_lock); - - switch (source) - { - case N_GET_NAME: - res = copy_network(_old_getnetbyname(name)); - break; - case N_GET_ADDR: - res = copy_network(_old_getnetbyaddr(addr, type)); - break; - case N_GET_ENT: - res = copy_network(_old_getnetent()); - break; - default: res = NULL; - } - - pthread_mutex_unlock(&_network_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct netent *)tdata->li_entry; -} - -struct netent * -getnetbyaddr(uint32_t addr, int type) -{ - return getnet(NULL, addr, type, N_GET_ADDR); -} - -struct netent * -getnetbyname(const char *name) -{ - return getnet(name, 0, 0, N_GET_NAME); -} - -struct netent * -getnetent(void) -{ - return getnet(NULL, 0, 0, N_GET_ENT); -} - -void -setnetent(int stayopen) -{ - if (_ds_running()) ds_setnetent(); - else _old_setnetent(stayopen); -} - -void -endnetent(void) -{ - if (_ds_running()) ds_endnetent(); - else _old_endnetent(); -} diff --git a/lookup.subproj/lu_overrides.h b/lookup.subproj/lu_overrides.h deleted file mode 100644 index a83713e..0000000 --- a/lookup.subproj/lu_overrides.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * These are routines typically defined in libc - * that are replaced by NetInfo. - * - * Copyright (c) 1995, NeXT Computer Inc. - */ - -#ifndef _LU_OVERRIDES_H_ -#define _LU_OVERRIDES_H_ - -#include -#include - -__BEGIN_DECLS -struct group *_old_getgrnam __P((const char *)); -struct group *_old_getgrgid __P((gid_t)); -int _old_setgrent __P((void)); -struct group *_old_getgrent __P((void)); -void _old_endgrent __P((void)); - -struct netent *_old_getnetbyname(); -struct netent *_old_getnetbyaddr(); -void _old_setnetent(); -struct netent *_old_getnetent(); -void _old_endnetent(); - -struct servent *_old_getservbyname __P((const char *, const char *)); -struct servent *_old_getservbyport __P((int, const char *)); -void _old_setservent __P((int)); -struct servent *_old_getservent __P((void)); -void _old_endservent __P((void)); - -struct protoent *_old_getprotobyname __P((const char *)); -struct protoent *_old_getprotobynumber __P((int)); -void _old_setprotoent __P((int)); -struct protoent *_old_getprotoent __P((void)); -void _old_endprotoent __P((void));; - -struct rpcent *_old_getrpcbyname(); -struct rpcent *_old_getrpcbynumber(); -void _old_setrpcent(); -struct rpcent *_old_getrpcent(); -void _old_endrpcent(); - -struct fstab *_old_getfsent __P((void)); -struct fstab *_old_getfsspec __P((const char *)); -struct fstab *_old_getfsfile __P((const char *)); -int _old_setfsent __P((void)); -void _old_endfsent __P((void)); - -struct prdb_ent *_old_prdb_getbyname __P((const char *)); -void _old_prdb_set __P((void)); -struct prdb_ent *_old_prdb_get __P((void)); -void _old_prdb_end __P((void)); - -struct aliasent *_old_alias_getbyname __P((const char *)); -void _old_alias_setent __P((void)); -struct aliasent *_old_alias_getent __P((void)); -void _old_alias_endent __P((void)); - -int _old_innetgr __P((const char *,const char *,const char *,const char *)); -void _old_setnetgrent __P((const char *)); -struct netgrent *_old_getnetgrent __P((void)); -void _old_endnetgrent __P((void)); - -int _old_initgroups(); -__END_DECLS - -#endif /* !_LU_OVERRIDES_H_ */ diff --git a/lookup.subproj/lu_protocol.c b/lookup.subproj/lu_protocol.c deleted file mode 100644 index ac78109..0000000 --- a/lookup.subproj/lu_protocol.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Protocol lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" - -extern struct protoent *_old_getprotobynumber(); -extern struct protoent *_old_getprotobyname(); -extern struct protoent *_old_getprotoent(); -extern void _old_setprotoent(); -extern void _old_endprotoent(); - -static pthread_mutex_t _protocol_lock = PTHREAD_MUTEX_INITIALIZER; - -#define PROTO_GET_NAME 1 -#define PROTO_GET_NUM 2 -#define PROTO_GET_ENT 3 - -#define ENTRY_SIZE sizeof(struct protoent) -#define ENTRY_KEY _li_data_key_protocol - -static struct protoent * -copy_protocol(struct protoent *in) -{ - if (in == NULL) return NULL; - - return (struct protoent *)LI_ils_create("s*4", in->p_name, in->p_aliases, in->p_proto); -} - -/* - * Extract the next protocol entry from a kvarray. - */ -static void * -extract_protocol(kvarray_t *in) -{ - struct protoent tmp; - uint32_t d, k, kcount; - char *empty[1]; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "p_name")) - { - if (tmp.p_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.p_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "p_proto")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.p_proto = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "p_aliases")) - { - if (tmp.p_aliases != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.p_aliases = (char **)in->dict[d].val[k]; - } - } - - if (tmp.p_name == NULL) tmp.p_name = ""; - if (tmp.p_aliases == NULL) tmp.p_aliases = empty; - - return copy_protocol(&tmp); -} - -/* - * Send a query to the system information daemon. - */ -static struct protoent * -ds_getprotobynumber(uint32_t number) -{ - static int proc = -1; - char val[16]; - - snprintf(val, sizeof(val), "%u", number); - return (struct protoent *)LI_getone("getprotobynumber", &proc, extract_protocol, "number", val); -} - -/* - * Send a query to the system information daemon. - */ -static struct protoent * -ds_getprotobyname(const char *name) -{ - static int proc = -1; - - return (struct protoent *)LI_getone("getprotobyname", &proc, extract_protocol, "name", name); -} - -/* - * Clean up / initialize / reinitialize the kvarray used to hold a list of all protocol entries. - */ -static void -ds_endprotoent() -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_setprotoent() -{ - ds_endprotoent(); -} - -static struct protoent * -ds_getprotoent() -{ - static int proc = -1; - - return (struct protoent *)LI_getent("getprotoent", &proc, extract_protocol, ENTRY_KEY, ENTRY_SIZE); -} - -static struct protoent * -getproto(const char *name, int number, int source) -{ - struct protoent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - switch (source) - { - case PROTO_GET_NAME: - res = ds_getprotobyname(name); - break; - case PROTO_GET_NUM: - res = ds_getprotobynumber(number); - break; - case PROTO_GET_ENT: - res = ds_getprotoent(); - break; - default: res = NULL; - } - } - else - { - pthread_mutex_lock(&_protocol_lock); - - switch (source) - { - case PROTO_GET_NAME: - res = copy_protocol(_old_getprotobyname(name)); - break; - case PROTO_GET_NUM: - res = copy_protocol(_old_getprotobynumber(number)); - break; - case PROTO_GET_ENT: - res = copy_protocol(_old_getprotoent()); - break; - default: res = NULL; - } - - pthread_mutex_unlock(&_protocol_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct protoent *)tdata->li_entry; -} - -struct protoent * -getprotobyname(const char *name) -{ - return getproto(name, -2, PROTO_GET_NAME); -} - -struct protoent * -getprotobynumber(int number) -{ - return getproto(NULL, number, PROTO_GET_NUM); -} - -struct protoent * -getprotoent(void) -{ - return getproto(NULL, -2, PROTO_GET_ENT); -} - -void -setprotoent(int stayopen) -{ - if (_ds_running()) ds_setprotoent(); - else _old_setprotoent(stayopen); -} - -void -endprotoent(void) -{ - if (_ds_running()) ds_endprotoent(); - else _old_endprotoent(); -} diff --git a/lookup.subproj/lu_rpc.c b/lookup.subproj/lu_rpc.c deleted file mode 100644 index 5919e09..0000000 --- a/lookup.subproj/lu_rpc.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * RPC lookup - * Copyright (C) 1989 by NeXT, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "lu_overrides.h" - -static pthread_mutex_t _rpc_lock = PTHREAD_MUTEX_INITIALIZER; - -#define RPC_GET_NAME 1 -#define RPC_GET_NUM 2 -#define RPC_GET_ENT 3 - -#define ENTRY_SIZE sizeof(struct rpcent) -#define ENTRY_KEY _li_data_key_rpc - -static struct rpcent * -copy_rpc(struct rpcent *in) -{ - if (in == NULL) return NULL; - - return (struct rpcent *)LI_ils_create("s*4", in->r_name, in->r_aliases, in->r_number); -} - -/* - * Extract the next rpc entry from a kvarray. - */ -static void * -extract_rpc(kvarray_t *in) -{ - struct rpcent tmp; - uint32_t d, k, kcount; - char *empty[1]; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "r_name")) - { - if (tmp.r_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.r_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "r_number")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.r_number = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "r_aliases")) - { - if (tmp.r_aliases != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.r_aliases = (char **)in->dict[d].val[k]; - } - } - - if (tmp.r_name == NULL) tmp.r_name = ""; - if (tmp.r_aliases == NULL) tmp.r_aliases = empty; - - return copy_rpc(&tmp); -} - -/* - * Send a query to the system information daemon. - */ -static struct rpcent * -ds_getrpcbynumber(uint32_t number) -{ - static int proc = -1; - char val[16]; - - snprintf(val, sizeof(val), "%u", number); - return (struct rpcent *)LI_getone("getrpcbynumber", &proc, extract_rpc, "number", val); -} - -/* - * Send a query to the system information daemon. - */ -static struct rpcent * -ds_getrpcbyname(const char *name) -{ - static int proc = -1; - - return (struct rpcent *)LI_getone("getrpcbyname", &proc, extract_rpc, "name", name); -} - -/* - * Clean up / initialize / reinitialize the kvarray used to hold a list of all rpc entries. - */ -static void -ds_endrpcent(void) -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_setrpcent(void) -{ - ds_endrpcent(); -} - -/* - * Get an entry from the getrpcent kvarray. - * Calls the system information daemon if the list doesn't exist (first call), - * or extracts the next entry if the list has been fetched. - */ -static struct rpcent * -ds_getrpcent(void) -{ - static int proc = -1; - - return (struct rpcent *)LI_getent("getrpcent", &proc, extract_rpc, ENTRY_KEY, ENTRY_SIZE); -} - -/* - * Checks if the system information daemon is running. - * If so, calls the appropriate fetch routine. - * If not, calls the appropriate "_old" routine. - * Places the result in thread-specific memory. - */ -static struct rpcent * -getrpc(const char *name, uint32_t number, int source) -{ - struct rpcent *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - if (_ds_running()) - { - switch (source) - { - case RPC_GET_NAME: - res = ds_getrpcbyname(name); - break; - case RPC_GET_NUM: - res = ds_getrpcbynumber(number); - break; - case RPC_GET_ENT: - res = ds_getrpcent(); - break; - default: res = NULL; - } - } - else - { - pthread_mutex_lock(&_rpc_lock); - - switch (source) - { - case RPC_GET_NAME: - res = copy_rpc(_old_getrpcbyname(name)); - break; - case RPC_GET_NUM: - res = copy_rpc(_old_getrpcbynumber(number)); - break; - case RPC_GET_ENT: - res = copy_rpc(_old_getrpcent()); - break; - default: res = NULL; - } - - pthread_mutex_unlock(&_rpc_lock); - } - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct rpcent *)tdata->li_entry; -} - -struct rpcent * -getrpcbyname(const char *name) -{ - return getrpc(name, -2, RPC_GET_NAME); -} - -struct rpcent * -#ifdef __LP64__ -getrpcbynumber(int number) -#else -getrpcbynumber(long number) -#endif -{ - uint32_t n; - - n = number; - return getrpc(NULL, n, RPC_GET_NUM); -} - -struct rpcent * -getrpcent(void) -{ - return getrpc(NULL, -2, RPC_GET_ENT); -} - -void -setrpcent(int stayopen) -{ - if (_ds_running()) ds_setrpcent(); - else _old_setrpcent(stayopen); -} - -void -endrpcent(void) -{ - if (_ds_running()) ds_endrpcent(); - else _old_endrpcent(); -} diff --git a/lookup.subproj/lu_service.c b/lookup.subproj/lu_service.c deleted file mode 100644 index f249e96..0000000 --- a/lookup.subproj/lu_service.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Services file lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" - -#define SERVICE_CACHE_SIZE 10 - -static pthread_mutex_t _service_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static void *_service_cache[SERVICE_CACHE_SIZE] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static unsigned int _service_cache_index = 0; -static unsigned int _service_cache_init = 0; - -static pthread_mutex_t _service_lock = PTHREAD_MUTEX_INITIALIZER; - -#define S_GET_NAME 1 -#define S_GET_PORT 2 -#define S_GET_ENT 3 - -extern struct servent *_old_getservbyport(); -extern struct servent *_old_getservbyname(); -extern struct servent *_old_getservent(); -extern void _old_setservent(); -extern void _old_endservent(); -extern void _old_setservfile(); - -#define ENTRY_SIZE sizeof(struct servent) -#define ENTRY_KEY _li_data_key_service - -static struct servent * -copy_service(struct servent *in) -{ - if (in == NULL) return NULL; - - return LI_ils_create("s*4s", in->s_name, in->s_aliases, in->s_port, in->s_proto); -} - -/* - * Extract the next service entry from a kvarray. - */ -static void * -extract_service(kvarray_t *in) -{ - struct servent tmp; - uint32_t d, k, kcount; - char *empty[1]; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - empty[0] = NULL; - memset(&tmp, 0, ENTRY_SIZE); - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "s_name")) - { - if (tmp.s_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.s_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "s_aliases")) - { - if (tmp.s_aliases != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.s_aliases = (char **)in->dict[d].val[k]; - } - else if (!strcmp(in->dict[d].key[k], "s_port")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.s_port = htons(atoi(in->dict[d].val[k][0])); - } - else if (!strcmp(in->dict[d].key[k], "s_proto")) - { - if (tmp.s_proto != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.s_proto = (char *)in->dict[d].val[k][0]; - } - } - - if (tmp.s_name == NULL) tmp.s_name = ""; - if (tmp.s_proto == NULL) tmp.s_proto = ""; - if (tmp.s_aliases == NULL) tmp.s_aliases = empty; - - return copy_service(&tmp); -} - -static void -cache_service(struct servent *s) -{ - struct servent *scache; - - if (s == NULL) return; - - pthread_mutex_lock(&_service_cache_lock); - - scache = copy_service(s); - - if (_service_cache[_service_cache_index] != NULL) LI_ils_free(_service_cache[_service_cache_index], ENTRY_SIZE); - _service_cache[_service_cache_index] = scache; - _service_cache_index = (_service_cache_index + 1) % SERVICE_CACHE_SIZE; - - _service_cache_init = 1; - - pthread_mutex_unlock(&_service_cache_lock); -} - -static int -service_cache_check() -{ - uint32_t i, status; - - /* don't consult cache if it has not been initialized */ - if (_service_cache_init == 0) return 1; - - status = LI_L1_cache_check(ENTRY_KEY); - - /* don't consult cache if it is disabled or if we can't validate */ - if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - - /* return 0 if cache is OK */ - if (status == LI_L1_CACHE_OK) return 0; - - /* flush cache */ - pthread_mutex_lock(&_service_cache_lock); - - for (i = 0; i < SERVICE_CACHE_SIZE; i++) - { - LI_ils_free(_service_cache[i], ENTRY_SIZE); - _service_cache[i] = NULL; - } - - _service_cache_index = 0; - - pthread_mutex_unlock(&_service_cache_lock); - - /* don't consult cache - it's now empty */ - return 1; -} - - -static struct servent * -cache_getservbyname(const char *name, const char *proto) -{ - int i; - struct servent *s, *res; - char **aliases; - - if (name == NULL) return NULL; - if (service_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_service_cache_lock); - - for (i = 0; i < SERVICE_CACHE_SIZE; i++) - { - s = (struct servent *)_service_cache[i]; - if (s == NULL) continue; - - if (s->s_name != NULL) - { - if (!strcmp(name, s->s_name)) - { - if ((proto == NULL) || ((s->s_proto != NULL) && (!strcmp(proto, s->s_proto)))) - { - res = copy_service(s); - pthread_mutex_unlock(&_service_cache_lock); - return res; - } - } - } - - aliases = s->s_aliases; - if (aliases == NULL) - { - pthread_mutex_unlock(&_service_cache_lock); - return NULL; - } - - for (; *aliases != NULL; *aliases++) - { - if (!strcmp(name, *aliases)) - { - if ((proto == NULL) || ((s->s_proto != NULL) && (!strcmp(proto, s->s_proto)))) - { - res = copy_service(s); - pthread_mutex_unlock(&_service_cache_lock); - return res; - } - } - } - } - - pthread_mutex_unlock(&_service_cache_lock); - return NULL; -} - -static struct servent * -cache_getservbyport(int port, const char *proto) -{ - int i; - struct servent *s, *res; - - if (service_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_service_cache_lock); - - for (i = 0; i < SERVICE_CACHE_SIZE; i++) - { - s = (struct servent *)_service_cache[i]; - if (s == NULL) continue; - - if (port == s->s_port) - { - if ((proto == NULL) || ((s->s_proto != NULL) && (!strcmp(proto, s->s_proto)))) - { - res = copy_service(s); - pthread_mutex_unlock(&_service_cache_lock); - return res; - } - } - } - - pthread_mutex_unlock(&_service_cache_lock); - return NULL; -} - -static struct servent * -ds_getservbyport(int port, const char *proto) -{ - struct servent *entry; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - static int proc = -1; - uint16_t sport; - char val[16]; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getservbyport", &proc); - if (status != KERN_SUCCESS) return NULL; - } - - /* Encode NULL */ - if (proto == NULL) proto = ""; - - sport = port; - snprintf(val, sizeof(val), "%d", ntohs(sport)); - - request = kvbuf_query("ksks", "port", val, "proto", proto); - if (request == NULL) return NULL; - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) return NULL; - - entry = extract_service(reply); - kvarray_free(reply); - - return entry; -} - -static struct servent * -ds_getservbyname(const char *name, const char *proto) -{ - struct servent *entry; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - static int proc = -1; - - if (proc < 0) - { - status = LI_DSLookupGetProcedureNumber("getservbyname", &proc); - if (status != KERN_SUCCESS) return NULL; - } - - /* Encode NULL */ - if (name == NULL) name = ""; - if (proto == NULL) proto = ""; - - request = kvbuf_query("ksks", "name", name, "proto", proto); - if (request == NULL) return NULL; - - reply = NULL; - status = LI_DSLookupQuery(proc, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) return NULL; - - entry = extract_service(reply); - kvarray_free(reply); - - return entry; -} - -static void -ds_endservent() -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static void -ds_setservent() -{ - ds_endservent(); -} - -static struct servent * -ds_getservent() -{ - static int proc = -1; - - return (struct servent *)LI_getent("getservent", &proc, extract_service, ENTRY_KEY, ENTRY_SIZE); -} - -static struct servent * -getserv(const char *name, const char *proto, int port, int source) -{ - struct servent *res = NULL; - struct li_thread_info *tdata; - int add_to_cache; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - add_to_cache = 0; - res = NULL; - - switch (source) - { - case S_GET_NAME: - res = cache_getservbyname(name, proto); - break; - case S_GET_PORT: - res = cache_getservbyport(port, proto); - break; - default: res = NULL; - } - - if (res != NULL) - { - } - else if (_ds_running()) - { - switch (source) - { - case S_GET_NAME: - res = ds_getservbyname(name, proto); - break; - case S_GET_PORT: - res = ds_getservbyport(port, proto); - break; - case S_GET_ENT: - res = ds_getservent(); - break; - default: res = NULL; - } - - if (res != NULL) add_to_cache = 1; - } - else - { - pthread_mutex_lock(&_service_lock); - switch (source) - { - case S_GET_NAME: - res = copy_service(_old_getservbyname(name, proto)); - break; - case S_GET_PORT: - res = copy_service(_old_getservbyport(port, proto)); - break; - case S_GET_ENT: - res = copy_service(_old_getservent()); - break; - default: res = NULL; - } - pthread_mutex_unlock(&_service_lock); - } - - if (add_to_cache == 1) cache_service(res); - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct servent *)tdata->li_entry; -} - -struct servent * -getservbyport(int port, const char *proto) -{ - return getserv(NULL, proto, port, S_GET_PORT); -} - -struct servent * -getservbyname(const char *name, const char *proto) -{ - return getserv(name, proto, 0, S_GET_NAME); -} - -struct servent * -getservent(void) -{ - return getserv(NULL, NULL, 0, S_GET_ENT); -} - -void -setservent(int stayopen) -{ - if (_ds_running()) ds_setservent(); - else _old_setservent(); -} - -void -endservent(void) -{ - if (_ds_running()) ds_endservent(); - else _old_endservent(); -} diff --git a/lookup.subproj/lu_user.c b/lookup.subproj/lu_user.c deleted file mode 100644 index b44cd41..0000000 --- a/lookup.subproj/lu_user.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * user information (passwd) lookup - * Copyright (C) 1989 by NeXT, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lu_utils.h" -#include "lu_overrides.h" - -#define USER_CACHE_SIZE 10 - -static pthread_mutex_t _user_cache_lock = PTHREAD_MUTEX_INITIALIZER; -static void *_user_cache[USER_CACHE_SIZE] = { NULL }; -static unsigned int _user_cache_index = 0; -static unsigned int _user_cache_init = 0; - -static pthread_mutex_t _user_lock = PTHREAD_MUTEX_INITIALIZER; - -#define PW_GET_NAME 1 -#define PW_GET_UID 2 -#define PW_GET_ENT 3 - -#define ENTRY_SIZE sizeof(struct passwd) -#define ENTRY_KEY _li_data_key_user - -__private_extern__ struct passwd *LI_files_getpwent(); -__private_extern__ struct passwd *LI_files_getpwnam(const char *name); -__private_extern__ struct passwd *LI_files_getpwuid(uid_t uid); -__private_extern__ void LI_files_setpwent(); -__private_extern__ void LI_files_endpwent(); - -static struct passwd * -copy_user(struct passwd *in) -{ - if (in == NULL) return NULL; - - return (struct passwd *)LI_ils_create("ss44LssssL", in->pw_name, in->pw_passwd, in->pw_uid, in->pw_gid, in->pw_change, in->pw_class, in->pw_gecos, in->pw_dir, in->pw_shell, in->pw_expire); -} - -/* - * Extract the next user entry from a kvarray. - */ -static void * -extract_user(kvarray_t *in) -{ - struct passwd tmp; - uint32_t d, k, kcount; - - if (in == NULL) return NULL; - - d = in->curr; - in->curr++; - - if (d >= in->count) return NULL; - - memset(&tmp, 0, ENTRY_SIZE); - - tmp.pw_uid = -2; - tmp.pw_gid = -2; - - kcount = in->dict[d].kcount; - - for (k = 0; k < kcount; k++) - { - if (!strcmp(in->dict[d].key[k], "pw_name")) - { - if (tmp.pw_name != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.pw_name = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "pw_passwd")) - { - if (tmp.pw_passwd != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.pw_passwd = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "pw_uid")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.pw_uid = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "pw_gid")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.pw_gid = atoi(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "pw_change")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.pw_change = atol(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "pw_expire")) - { - if (in->dict[d].vcount[k] == 0) continue; - tmp.pw_expire = atol(in->dict[d].val[k][0]); - } - else if (!strcmp(in->dict[d].key[k], "pw_class")) - { - if (tmp.pw_class != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.pw_class = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "pw_gecos")) - { - if (tmp.pw_gecos != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.pw_gecos = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "pw_dir")) - { - if (tmp.pw_dir != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.pw_dir = (char *)in->dict[d].val[k][0]; - } - else if (!strcmp(in->dict[d].key[k], "pw_shell")) - { - if (tmp.pw_shell != NULL) continue; - if (in->dict[d].vcount[k] == 0) continue; - - tmp.pw_shell = (char *)in->dict[d].val[k][0]; - } - } - - if (tmp.pw_name == NULL) tmp.pw_name = ""; - if (tmp.pw_passwd == NULL) tmp.pw_passwd = ""; - if (tmp.pw_class == NULL) tmp.pw_class = ""; - if (tmp.pw_gecos == NULL) tmp.pw_gecos = ""; - if (tmp.pw_dir == NULL) tmp.pw_dir = ""; - if (tmp.pw_shell == NULL) tmp.pw_shell = ""; - - return copy_user(&tmp); -} - -static int -copy_user_r(struct passwd *in, struct passwd *out, char *buffer, int buflen) -{ - int hsize; - char *bp; - - if (in == NULL) return -1; - if (out == NULL) return -1; - - if (buffer == NULL) buflen = 0; - - /* Calculate size of input */ - hsize = 0; - if (in->pw_name != NULL) hsize += (strlen(in->pw_name) + 1); - if (in->pw_passwd != NULL) hsize += (strlen(in->pw_passwd) + 1); - if (in->pw_class != NULL) hsize += (strlen(in->pw_class) + 1); - if (in->pw_gecos != NULL) hsize += (strlen(in->pw_gecos) + 1); - if (in->pw_dir != NULL) hsize += (strlen(in->pw_dir) + 1); - if (in->pw_shell != NULL) hsize += (strlen(in->pw_shell) + 1); - - /* Check buffer space */ - if (hsize > buflen) return -1; - - /* Copy result into caller's struct passwd, using buffer for memory */ - bp = buffer; - - out->pw_name = NULL; - if (in->pw_name != NULL) - { - out->pw_name = bp; - hsize = strlen(in->pw_name) + 1; - memmove(bp, in->pw_name, hsize); - bp += hsize; - } - - out->pw_passwd = NULL; - if (in->pw_passwd != NULL) - { - out->pw_passwd = bp; - hsize = strlen(in->pw_passwd) + 1; - memmove(bp, in->pw_passwd, hsize); - bp += hsize; - } - - out->pw_uid = in->pw_uid; - - out->pw_gid = in->pw_gid; - - out->pw_change = in->pw_change; - - out->pw_class = NULL; - if (in->pw_class != NULL) - { - out->pw_class = bp; - hsize = strlen(in->pw_class) + 1; - memmove(bp, in->pw_class, hsize); - bp += hsize; - } - - out->pw_gecos = NULL; - if (in->pw_gecos != NULL) - { - out->pw_gecos = bp; - hsize = strlen(in->pw_gecos) + 1; - memmove(bp, in->pw_gecos, hsize); - bp += hsize; - } - - out->pw_dir = NULL; - if (in->pw_dir != NULL) - { - out->pw_dir = bp; - hsize = strlen(in->pw_dir) + 1; - memmove(bp, in->pw_dir, hsize); - bp += hsize; - } - - out->pw_shell = NULL; - if (in->pw_shell != NULL) - { - out->pw_shell = bp; - hsize = strlen(in->pw_shell) + 1; - memmove(bp, in->pw_shell, hsize); - bp += hsize; - } - - out->pw_expire = in->pw_expire; - - return 0; -} - -static void -cache_user(struct passwd *pw) -{ - struct passwd *pwcache; - - if (pw == NULL) return; - - pthread_mutex_lock(&_user_cache_lock); - - pwcache = copy_user(pw); - - if (_user_cache[_user_cache_index] != NULL) LI_ils_free(_user_cache[_user_cache_index], ENTRY_SIZE); - - _user_cache[_user_cache_index] = pwcache; - _user_cache_index = (_user_cache_index + 1) % USER_CACHE_SIZE; - - _user_cache_init = 1; - - pthread_mutex_unlock(&_user_cache_lock); -} - -static int -user_cache_check() -{ - uint32_t i, status; - - /* don't consult cache if it has not been initialized */ - if (_user_cache_init == 0) return 1; - - status = LI_L1_cache_check(ENTRY_KEY); - - /* don't consult cache if it is disabled or if we can't validate */ - if ((status == LI_L1_CACHE_DISABLED) || (status == LI_L1_CACHE_FAILED)) return 1; - - /* return 0 if cache is OK */ - if (status == LI_L1_CACHE_OK) return 0; - - /* flush cache */ - pthread_mutex_lock(&_user_cache_lock); - - for (i = 0; i < USER_CACHE_SIZE; i++) - { - LI_ils_free(_user_cache[i], ENTRY_SIZE); - _user_cache[i] = NULL; - } - - _user_cache_index = 0; - - pthread_mutex_unlock(&_user_cache_lock); - - /* don't consult cache - it's now empty */ - return 1; -} - -static struct passwd * -cache_getpwnam(const char *name) -{ - uint32_t i; - struct passwd *pw, *res; - - if (name == NULL) return NULL; - if (user_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_user_cache_lock); - - for (i = 0; i < USER_CACHE_SIZE; i++) - { - pw = (struct passwd *)_user_cache[i]; - if (pw == NULL) continue; - if (pw->pw_name == NULL) continue; - - if (!strcmp(name, pw->pw_name)) - { - res = copy_user(pw); - pthread_mutex_unlock(&_user_cache_lock); - return res; - } - } - - pthread_mutex_unlock(&_user_cache_lock); - return NULL; -} - -static struct passwd * -cache_getpwuid(uid_t uid) -{ - uint32_t i; - struct passwd *pw, *res; - - if (user_cache_check() != 0) return NULL; - - pthread_mutex_lock(&_user_cache_lock); - - for (i = 0; i < USER_CACHE_SIZE; i++) - { - pw = (struct passwd *)_user_cache[i]; - if (pw == NULL) continue; - - if (uid == pw->pw_uid) - { - res = copy_user(pw); - pthread_mutex_unlock(&_user_cache_lock); - return res; - } - } - - pthread_mutex_unlock(&_user_cache_lock); - - return NULL; -} - -static struct passwd * -ds_getpwuid(uid_t uid) -{ - static int proc = -1; - char val[16]; - - snprintf(val, sizeof(val), "%d", (int)uid); - return (struct passwd *)LI_getone("getpwuid", &proc, extract_user, "uid", val); -} - -static struct passwd * -ds_getpwnam(const char *name) -{ - static int proc = -1; - - return (struct passwd *)LI_getone("getpwnam", &proc, extract_user, "login", name); -} - -static void -ds_endpwent(void) -{ - LI_data_free_kvarray(LI_data_find_key(ENTRY_KEY)); -} - -static int -ds_setpwent(void) -{ - ds_endpwent(); - return 1; -} - -static struct passwd * -ds_getpwent() -{ - static int proc = -1; - - return (struct passwd *)LI_getent("getpwent", &proc, extract_user, ENTRY_KEY, ENTRY_SIZE); -} - -static struct passwd * -getpw_internal(const char *name, uid_t uid, int source) -{ - struct passwd *res; - int add_to_cache; - - add_to_cache = 0; - res = NULL; - - switch (source) - { - case PW_GET_NAME: - res = cache_getpwnam(name); - break; - case PW_GET_UID: - res = cache_getpwuid(uid); - break; - default: res = NULL; - } - - if (res != NULL) - { - } - else if (_ds_running()) - { - switch (source) - { - case PW_GET_NAME: - res = ds_getpwnam(name); - break; - case PW_GET_UID: - res = ds_getpwuid(uid); - break; - case PW_GET_ENT: - res = ds_getpwent(); - break; - default: res = NULL; - } - - if (res != NULL) add_to_cache = 1; - } - else - { - pthread_mutex_lock(&_user_lock); - - switch (source) - { - case PW_GET_NAME: - res = copy_user(LI_files_getpwnam(name)); - break; - case PW_GET_UID: - res = copy_user(LI_files_getpwuid(uid)); - break; - case PW_GET_ENT: - res = copy_user(LI_files_getpwent()); - break; - default: res = NULL; - } - - pthread_mutex_unlock(&_user_lock); - } - - if (add_to_cache == 1) cache_user(res); - - return res; -} - -static struct passwd * -getpw(const char *name, uid_t uid, int source) -{ - struct passwd *res = NULL; - struct li_thread_info *tdata; - - tdata = LI_data_create_key(ENTRY_KEY, ENTRY_SIZE); - if (tdata == NULL) return NULL; - - res = getpw_internal(name, uid, source); - - LI_data_recycle(tdata, res, ENTRY_SIZE); - return (struct passwd *)tdata->li_entry; -} - -static int -getpw_r(const char *name, uid_t uid, int source, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) -{ - struct passwd *res = NULL; - int status; - - *result = NULL; - - res = getpw_internal(name, uid, source); - if (res == NULL) return 0; - - status = copy_user_r(res, pwd, buffer, bufsize); - - LI_ils_free(res, ENTRY_SIZE); - - if (status != 0) return ERANGE; - - *result = pwd; - return 0; -} - -struct passwd * -getpwnam(const char *name) -{ - return getpw(name, -2, PW_GET_NAME); -} - -struct passwd * -getpwuid(uid_t uid) -{ - return getpw(NULL, uid, PW_GET_UID); -} - -struct passwd * -getpwent(void) -{ - return getpw(NULL, -2, PW_GET_ENT); -} - -void -setpwent(void) -{ - if (_ds_running()) ds_setpwent(); - else LI_files_setpwent(); -} - -void -endpwent(void) -{ - if (_ds_running()) ds_endpwent(); - else LI_files_endpwent(); -} - -int -getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) -{ - return getpw_r(name, -2, PW_GET_NAME, pwd, buffer, bufsize, result); -} - -int -getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) -{ - return getpw_r(NULL, uid, PW_GET_UID, pwd, buffer, bufsize, result); -} diff --git a/lookup.subproj/lu_utils.c b/lookup.subproj/lu_utils.c deleted file mode 100644 index 02e8d14..0000000 --- a/lookup.subproj/lu_utils.c +++ /dev/null @@ -1,2461 +0,0 @@ -/* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef DEBUG -#include -#endif -#include "lu_utils.h" -#include "netdb_async.h" -#include "DSlibinfoMIG.h" -#include "DSlibinfoMIGAsyncReply.h" - -#define MAX_LOOKUP_ATTEMPTS 10 -#define _LU_MAXLUSTRLEN 256 -#define QBUF_SIZE 16384 -#define KVBUF_START_SIZE 128 - -#define LI_MESSAGE_SEND_ID 4241776 -#define LI_MESSAGE_REPLY_ID 4241876 - -#define ILS_MAGIC_SIZE 8 -#define ILS_MAGIC "ILSMAGIC" - -#define L1_CACHE_NOTIFICATION_KEY_GLOBAL "com.apple.system.DirectoryService.InvalidateCache" -#define L1_CACHE_NOTIFICATION_KEY_GROUP "com.apple.system.DirectoryService.InvalidateCache.group" -#define L1_CACHE_NOTIFICATION_KEY_HOST "com.apple.system.DirectoryService.InvalidateCache.host" -#define L1_CACHE_NOTIFICATION_KEY_SERVICE "com.apple.system.DirectoryService.InvalidateCache.service" -#define L1_CACHE_NOTIFICATION_KEY_USER "com.apple.system.DirectoryService.InvalidateCache.user" - -/* GLOBAL */ -uint32_t gL1CacheEnabled = 1; - -static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 4 }; -static const uint32_t align_64[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 }; - -static pthread_key_t _info_key = 0; -static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT; - -static pthread_mutex_t _notify_lock = PTHREAD_MUTEX_INITIALIZER; -static int _L1_notify_token[] = -{ - -1, /* global */ - -1, /* group */ - -1, /* host */ - -1, /* service */ - -1 /* user */ -}; - -struct _li_data_s -{ - uint32_t icount; - uint32_t *ikey; - void **idata; -}; - -typedef struct _li_async_request_s -{ - mach_port_t reply_port; - uint32_t retry; - uint32_t proc; - void *context; - void *callback; - char request[MAX_MIG_INLINE_DATA]; - mach_msg_type_number_t requestCnt; - char reply[MAX_MIG_INLINE_DATA]; - mach_msg_type_number_t replyCnt; - vm_address_t ooreply; - mach_msg_type_number_t ooreplyCnt; - security_token_t token; - struct _li_async_request_s *next; -} _li_async_request_t; - -static pthread_mutex_t _li_worklist_lock = PTHREAD_MUTEX_INITIALIZER; -static _li_async_request_t *_li_worklist = NULL; - -/* Send an asynchronous query message. */ -static kern_return_t -_LI_async_send(_li_async_request_t *r) -{ - mach_msg_return_t status; - mach_vm_address_t cb; - - if (r == NULL) return KERN_FAILURE; - - if (r->retry == 0) return MIG_SERVER_DIED; - r->retry--; - - cb = (mach_vm_address_t)(r->callback); - status = libinfoDSmig_Query_async(_ds_port, r->reply_port, r->proc, r->request, r->requestCnt, cb); - - if (status == MACH_SEND_INVALID_REPLY) - { - mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1); - r->reply_port = MACH_PORT_NULL; - } - - return status; -} - -static _li_async_request_t * -_LI_worklist_remove(mach_port_t p) -{ - _li_async_request_t *r, *n; - - if (p == MACH_PORT_NULL) return NULL; - if (_li_worklist == NULL) return NULL; - - pthread_mutex_lock(&_li_worklist_lock); - - if (_li_worklist->reply_port == p) - { - r = _li_worklist; - _li_worklist = r->next; - pthread_mutex_unlock(&_li_worklist_lock); - return r; - } - - for (r = _li_worklist; r != NULL; r = r->next) - { - n = r->next; - if (n == NULL) break; - - if (n->reply_port == p) - { - r->next = n->next; - pthread_mutex_unlock(&_li_worklist_lock); - return n; - } - } - - pthread_mutex_unlock(&_li_worklist_lock); - return NULL; -} - -static _li_async_request_t * -_LI_worklist_find(mach_port_t p) -{ - _li_async_request_t *r; - - if (p == MACH_PORT_NULL) return NULL; - if (_li_worklist == NULL) return NULL; - - pthread_mutex_lock(&_li_worklist_lock); - - for (r = _li_worklist; r != NULL; r = r->next) - { - if (r->reply_port == p) - { - pthread_mutex_unlock(&_li_worklist_lock); - return r; - } - } - - pthread_mutex_unlock(&_li_worklist_lock); - return NULL; -} - -static void -_LI_free_request(_li_async_request_t *r) -{ - if (r == NULL) return; - - if (r->reply_port != MACH_PORT_NULL) mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1); - r->reply_port = MACH_PORT_NULL; - - free(r); -} - -/* - * This is a callback for DSLibinfoMIGAsyncReplyServer.c - */ -__private_extern__ kern_return_t -libinfoDSmig_do_Response_async(mach_port_t server, char *reply, mach_msg_type_number_t replyCnt, vm_offset_t ooreply, mach_msg_type_number_t ooreplyCnt, mach_vm_address_t callbackAddr, security_token_t servertoken) -{ - _li_async_request_t *r; - - r = _LI_worklist_find(server); - - if (r != NULL) - { - r->ooreply = ooreply; - r->ooreplyCnt = ooreplyCnt; - if (replyCnt > 0) memcpy(r->reply, reply, replyCnt); - r->replyCnt = replyCnt; - r->token = servertoken; - } - else if (ooreplyCnt != 0) - { - vm_deallocate(mach_task_self(), ooreply, ooreplyCnt); - } - - return KERN_SUCCESS; -} - -/* Receive an asynchronous reply message. */ -kern_return_t -LI_async_receive(mach_port_t p, kvarray_t **reply) -{ - kern_return_t status; - _li_async_request_t *r; - kvbuf_t *out; - int flags; - - flags = MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0); - - /* use mach_msg_server_once to do the work here */ - status = mach_msg_server_once(DSlibinfoMIGAsyncReply_server, 65536, p, flags); - - if (status != KERN_SUCCESS) return status; - - r = _LI_worklist_remove(p); - if (r == NULL) return KERN_FAILURE; - - out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); - if (out == NULL) - { - if (r->ooreplyCnt > 0) vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt); - return KERN_FAILURE; - } - - if (r->ooreplyCnt > 0) - { - out->datalen = r->ooreplyCnt; - out->databuf = malloc(r->ooreplyCnt); - if (out->databuf == NULL) - { - free(out); - *reply = NULL; - vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt); - return KERN_FAILURE; - } - - memcpy(out->databuf, (char *)r->ooreply, r->ooreplyCnt); - vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt); - } - else if (r->replyCnt > 0) - { - out->datalen = r->replyCnt; - out->databuf = malloc(r->replyCnt); - if (out->databuf == NULL) - { - free(out); - *reply = NULL; - return KERN_FAILURE; - } - - memcpy(out->databuf, r->reply, r->replyCnt); - } - - *reply = kvbuf_decode(out); - if (*reply == NULL) - { - /* DS returned no data */ - free(out->databuf); - free(out); - } - - _LI_free_request(r); - - return KERN_SUCCESS; -} - -static void -_LI_worklist_append(_li_async_request_t *r) -{ - _li_async_request_t *p; - - if (r == NULL) return; - - pthread_mutex_lock(&_li_worklist_lock); - - if (_li_worklist == NULL) - { - _li_worklist = r; - pthread_mutex_unlock(&_li_worklist_lock); - return; - } - - for (p = _li_worklist; p->next != NULL; p = p->next); - p->next = r; - - pthread_mutex_unlock(&_li_worklist_lock); -} - -void -LI_async_call_cancel(mach_port_t p, void **context) -{ - _li_async_request_t *req; - - req = _LI_worklist_remove(p); - - if (req != NULL) - { - if (context != NULL) *context = req->context; - _LI_free_request(req); - } - else if (p != MACH_PORT_NULL) - { - mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1); - } -} - -void -lu_async_call_cancel(mach_port_t p) -{ - LI_async_call_cancel(p, NULL); -} - -static _li_async_request_t * -_LI_create_request(uint32_t proc, kvbuf_t *query, void *callback, void *context) -{ - _li_async_request_t *r; - kern_return_t status; - mach_port_t target; - - if (_ds_running() == 0) return NULL; - if (query == NULL) return NULL; - if (query->datalen > MAX_MIG_INLINE_DATA) return NULL; - - r = (_li_async_request_t *)calloc(1, sizeof(_li_async_request_t)); - if (r == NULL) return NULL; - - status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(r->reply_port)); - if (status != KERN_SUCCESS) - { - _LI_free_request(r); - return NULL; - } - - target = MACH_PORT_NULL; - - /* Request no-senders notification so we can tell when server dies */ - mach_port_request_notification(mach_task_self(), r->reply_port, MACH_NOTIFY_NO_SENDERS, 1, r->reply_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &target); - - r->retry = MAX_LOOKUP_ATTEMPTS; - - r->context = context; - r->callback = callback; - r->proc = proc; - - memcpy(r->request, query->databuf, query->datalen); - r->requestCnt = query->datalen; - - r->next = NULL; - - return r; -} - -kern_return_t -LI_async_start(mach_port_t *p, uint32_t proc, kvbuf_t *query, void *callback, void *context) -{ - _li_async_request_t *r; - kern_return_t status; - uint32_t retry; - - if (p == NULL) return KERN_FAILURE; - - *p = MACH_PORT_NULL; - - if (_ds_running() == 0) return KERN_FAILURE; - if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; - - /* Make a request struct to keep track */ - r = _LI_create_request(proc, query, callback, context); - if (r == NULL) return KERN_FAILURE; - - status = MIG_SERVER_DIED; - for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++) - { - status = _LI_async_send(r); - } - - if (status != KERN_SUCCESS) - { - _LI_free_request(r); - return status; - } - - /* Add request to worklist */ - _LI_worklist_append(r); - - *p = r->reply_port; - - return KERN_SUCCESS; -} - -kern_return_t -LI_async_send(mach_port_t *p, uint32_t proc, kvbuf_t *query) -{ - return LI_async_start(p, proc, query, NULL, NULL); -} - -kern_return_t -LI_async_handle_reply(mach_msg_header_t *msg, kvarray_t **reply, void **callback, void **context) -{ - _li_async_request_t *req; - kvbuf_t *out; - kern_return_t status; - uint32_t retry; - mig_reply_error_t *bufReply; - - if (msg == NULL) return -1; - - /* If reply status was an error, resend */ - if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS) - { - /* if server died */ - req = _LI_worklist_find(msg->msgh_local_port); - if (req == NULL) return -1; - - status = MIG_SERVER_DIED; - for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++) - { - /* send message */ - status = _LI_async_send(req); - } - - if (status != KERN_SUCCESS) return -1; - - return MIG_REPLY_MISMATCH; - } - - /* need to implement the msg_server_once type code here */ - mach_msg_size_t reply_alloc = round_page(65536 + MAX_TRAILER_SIZE); - - status = vm_allocate(mach_task_self(), (vm_address_t *) &bufReply, reply_alloc, VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE); - if (status != KERN_SUCCESS) return status; - - status = DSlibinfoMIGAsyncReply_server(msg, (mach_msg_header_t *)bufReply); - - /* we just destroy the reply, because there isn't one */ - if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) mach_msg_destroy(&bufReply->Head); - - vm_deallocate(mach_task_self(), (vm_address_t) bufReply, reply_alloc); - - if (status == FALSE) return KERN_FAILURE; - - req = _LI_worklist_remove(msg->msgh_local_port); - if (req == NULL) return KERN_FAILURE; - - *callback = req->callback; - *context = req->context; - - out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); - if (out == NULL) - { - if (req->ooreplyCnt > 0) vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt); - return KERN_FAILURE; - } - - if (req->ooreplyCnt > 0) - { - out->datalen = req->ooreplyCnt; - out->databuf = malloc(req->ooreplyCnt); - if (out->databuf == NULL) - { - free(out); - *reply = NULL; - vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt); - return KERN_FAILURE; - } - - memcpy(out->databuf, (char *)req->ooreply, req->ooreplyCnt); - vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt); - } - else if (req->replyCnt > 0) - { - out->datalen = req->replyCnt; - out->databuf = malloc(req->replyCnt); - if (out->databuf == NULL) - { - free(out); - *reply = NULL; - return KERN_FAILURE; - } - - memcpy(out->databuf, req->reply, req->replyCnt); - } - - *reply = kvbuf_decode(out); - if (*reply == NULL) - { - /* DS returned no data */ - free(out->databuf); - free(out); - } - - _LI_free_request(req); - - return KERN_SUCCESS; -} - -static void -_LI_thread_info_free(void *x) -{ - struct li_thread_info *tdata; - - if (x == NULL) return; - - tdata = (struct li_thread_info *)x; - LI_ils_free(tdata->li_entry, tdata->li_entry_size); - LI_data_free_kvarray(tdata); - - free(tdata); -} - -static void -_LI_data_free(void *x) -{ - struct _li_data_s *t; - int i; - - if (x == NULL) return; - - t = (struct _li_data_s *)x; - - for (i = 0; i < t->icount; i++) - { - _LI_thread_info_free(t->idata[i]); - t->idata[i] = NULL; - } - - if (t->ikey != NULL) free(t->ikey); - t->ikey = NULL; - - if (t->idata != NULL) free(t->idata); - t->idata = NULL; - - free(t); -} - -static void -_LI_data_init() -{ - pthread_key_create(&_info_key, _LI_data_free); - return; -} - -static struct _li_data_s * -_LI_data_get() -{ - struct _li_data_s *libinfo_data; - - /* - * Only one thread should create the _info_key - */ - pthread_once(&_info_key_initialized, _LI_data_init); - - /* Check if this thread already created libinfo_data */ - libinfo_data = pthread_getspecific(_info_key); - if (libinfo_data != NULL) return libinfo_data; - - libinfo_data = (struct _li_data_s *)calloc(1, sizeof(struct _li_data_s)); - if (libinfo_data == NULL) return NULL; - - pthread_setspecific(_info_key, libinfo_data); - return libinfo_data; -} - -__private_extern__ void * -LI_data_find_key(uint32_t key) -{ - struct _li_data_s *libinfo_data; - uint32_t i; - - libinfo_data = _LI_data_get(); - if (libinfo_data == NULL) return NULL; - - for (i = 0; i < libinfo_data->icount; i++) - { - if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i]; - } - - return NULL; -} - -__private_extern__ void * -LI_data_create_key(uint32_t key, size_t esize) -{ - struct _li_data_s *libinfo_data; - struct li_thread_info *tdata; - uint32_t i, n; - - libinfo_data = _LI_data_get(); - if (libinfo_data == NULL) return NULL; - - for (i = 0; i < libinfo_data->icount; i++) - { - if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i]; - } - - i = libinfo_data->icount; - n = i + 1; - - if (i == 0) - { - libinfo_data->ikey = (uint32_t *)malloc(sizeof(uint32_t)); - libinfo_data->idata = (void **)malloc(sizeof(void *)); - } - else - { - libinfo_data->ikey = (uint32_t *)reallocf(libinfo_data->ikey, n * sizeof(uint32_t)); - libinfo_data->idata = (void **)reallocf(libinfo_data->idata, n * sizeof(void *)); - } - - if ((libinfo_data->ikey == NULL) || (libinfo_data->idata == NULL)) - { - if (libinfo_data->ikey != NULL) free(libinfo_data->ikey); - libinfo_data->ikey = NULL; - - if (libinfo_data->idata != NULL) free(libinfo_data->idata); - libinfo_data->idata = NULL; - - return NULL; - } - - tdata = (struct li_thread_info *)calloc(1, sizeof(struct li_thread_info)); - if (tdata == NULL) return NULL; - - tdata->li_entry_size = esize; - - libinfo_data->ikey[i] = key; - libinfo_data->idata[i] = tdata; - libinfo_data->icount++; - - return tdata; -} - -static uint32_t -_LI_data_index(uint32_t key, struct _li_data_s *libinfo_data) -{ - uint32_t i; - - if (libinfo_data == NULL) return (uint32_t)-1; - - for (i = 0; i < libinfo_data->icount; i++) - { - if (libinfo_data->ikey[i] == key) return i; - } - - return (uint32_t)-1; -} - -void -_LI_data_set_key(uint32_t key, void *data) -{ - struct _li_data_s *libinfo_data; - uint32_t i; - - libinfo_data = _LI_data_get(); - if (libinfo_data == NULL) return; - - i = _LI_data_index(key, libinfo_data); - if (i == (uint32_t)-1) return; - - libinfo_data->idata[i] = data; -} - -void * -_LI_data_get_key(uint32_t key) -{ - struct _li_data_s *libinfo_data; - uint32_t i; - - libinfo_data = _LI_data_get(); - if (libinfo_data == NULL) return NULL; - - i = _LI_data_index(key, libinfo_data); - if (i == (uint32_t)-1) return NULL; - - return libinfo_data->idata[i]; -} - -__private_extern__ void -LI_data_free_kvarray(struct li_thread_info *tdata) -{ - if (tdata == NULL) return; - if (tdata->li_vm == NULL) return; - - kvarray_free((kvarray_t *)tdata->li_vm); - tdata->li_vm = NULL; -} - -__private_extern__ void -LI_data_recycle(struct li_thread_info *tdata, void *entry, size_t entrysize) -{ - if (tdata == NULL) return; - - LI_ils_free(tdata->li_entry, entrysize); - tdata->li_entry = entry; -} - -#define KVBUF_CHUNK 256 - -/* - * kvbuf_t is a list of key/value dictionaries. - * - * First 4 bytes are the number of dictionaries. - * For each dictionary, first 4 bytes is the key / value list count. - * For each value list, first 4 bytes is the list length. - * Keys and values are a 4-byte length followed by a nul-terminated string - * - * When the databuf needs to grow, we add memory in KVBUF_CHUNK size - * increments to reduce malloc / realloc activity. - * The _size variable stores the actual allocated size. - * The datalen variable stores the used data size. - * - * The _dict variable holds an offset from the start of the buffer - * to the "current" dictionary. kvbuf_reset() resets this, - * and kvbuf_next_dict() bumps the offset so that databuf + _dict - * points to the next dictionary. - * - * The _key variable holds an offset from the start of the buffer - * to the "current" key. kvbuf_reset() resets this, and - * kvbuf_next_key() bumps the offset so that databuf + _key - * points to the next key. - * - * The _val variable holds an offset from the start of the buffer - * to the "current" value. kvbuf_reset() resets this, and - * kvbuf_next_val() bumps the offset so that databuf + _val - * points to the next value. - * - * The cache_entry_list_to_kvbuf() routine contains the only - * code that builds an array. - * - */ - -/* - * kvbuf_query is a simple utility for constructing a - * kvbuf with a single dictionary. The format string may - * contain the chars "k", "s", "i", and "u". "k" denotes a key - * (keys are always strings), "s" denotes a string value, - * "i" denotes a 32 bit signed int, and "u" denotes an unsigned. - */ -__private_extern__ kvbuf_t * -kvbuf_query(char *fmt, ...) -{ - va_list ap; - char *arg, *f, str[32]; - int32_t iarg; - uint32_t uarg; - kvbuf_t *kv; - - if (fmt == NULL) return NULL; - - kv = kvbuf_new(); - if (kv == NULL) return NULL; - - kvbuf_add_dict(kv); - - va_start(ap, fmt); - for (f = fmt; (*f) != '\0'; f++) - { - if (*f == 'k') - { - arg = va_arg(ap, char *); - kvbuf_add_key(kv, arg); - } - else if (*f == 's') - { - arg = va_arg(ap, char *); - kvbuf_add_val(kv, arg); - } - else if (*f == 'i') - { - iarg = va_arg(ap, int32_t); - snprintf(str, sizeof(str), "%d", iarg); - kvbuf_add_val(kv, str); - } - else if (*f == 'u') - { - uarg = va_arg(ap,uint32_t); - snprintf(str, sizeof(str), "%u", uarg); - kvbuf_add_val(kv, str); - } - } - va_end(ap); - - return kv; -} - -__private_extern__ kvbuf_t * -kvbuf_query_key_val(const char *key, const char *val) -{ - kvbuf_t *kv; - uint32_t x, kl, vl, vc; - char *p; - - if (key == NULL) return NULL; - - kl = strlen(key) + 1; - - vl = 0; - vc = 0; - - if (val != NULL) - { - vl = strlen(val) + 1; - vc = 1; - } - - kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); - if (kv == NULL) return NULL; - - kv->_size = (5 * sizeof(uint32_t)) + kl + vl; - kv->datalen = kv->_size; - - kv->databuf = calloc(1, kv->_size); - if (kv->databuf == NULL) - { - free(kv); - return NULL; - } - - p = kv->databuf; - - /* 1 dict */ - x = htonl(1); - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - - /* 1 key */ - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - - /* key length */ - x = htonl(kl); - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - - /* key */ - memcpy(p, key, kl); - p += kl; - - /* number of values */ - x = htonl(vc); - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - - if (vc > 0) - { - /* value length */ - x = htonl(vl); - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - - /* value */ - memcpy(p, val, vl); - } - - return kv; -} - -__private_extern__ kvbuf_t * -kvbuf_query_key_int(const char *key, int32_t i) -{ - char str[32]; - - snprintf(str, sizeof(str), "%d", i); - return kvbuf_query_key_val(key, str); -} - -__private_extern__ kvbuf_t * -kvbuf_query_key_uint(const char *key, uint32_t u) -{ - char str[32]; - - snprintf(str, sizeof(str), "%u", u); - return kvbuf_query_key_val(key, str); -} - -kvbuf_t * -kvbuf_new(void) -{ - kvbuf_t *kv; - - kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); - if (kv == NULL) return NULL; - - kv->_size = KVBUF_START_SIZE; - kv->databuf = calloc(1, kv->_size); - if (kv->databuf == NULL) - { - free(kv); - return NULL; - } - - kv->datalen = sizeof(uint32_t); - kv->_dict = kv->datalen; - - return kv; -} - -kvbuf_t * -kvbuf_init(char *buffer, uint32_t length) -{ - kvbuf_t *kv; - - kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); - if (kv == NULL) return NULL; - - kv->_size = length; - kv->datalen = length; - kv->databuf = calloc(1, length); - if (kv->databuf == NULL) - { - free(kv); - kv = NULL; - } - else - { - memcpy(kv->databuf, buffer, length); - } - - return kv; -} - -static void -kvbuf_grow(kvbuf_t *kv, uint32_t delta) -{ - uint32_t newlen, n; - char *p; - - if (kv == NULL) return; - if (delta == 0) return; - - if (kv->databuf == NULL) delta += sizeof(uint32_t); - - n = (delta + KVBUF_CHUNK - 1) / KVBUF_CHUNK; - newlen = kv->datalen + (n * KVBUF_CHUNK); - - if (newlen <= kv->_size) return; - - kv->_size = newlen; - - if (kv->databuf == NULL) - { - kv->databuf = calloc(1, kv->_size); - if (kv->databuf == NULL) - { - memset(kv, 0, sizeof(kvbuf_t)); - return; - } - - kv->datalen = sizeof(uint32_t); - kv->_dict = sizeof(uint32_t); - } - else - { - kv->databuf = reallocf(kv->databuf, kv->_size); - if (kv->databuf == NULL) - { - memset(kv, 0, sizeof(kvbuf_t)); - return; - } - - p = kv->databuf + kv->datalen; - memset(p, 0, kv->_size - kv->datalen); - } -} - -void -kvbuf_add_dict(kvbuf_t *kv) -{ - char *p; - uint32_t x, dict_count; - - if (kv == NULL) return; - - /* Add a key count */ - kvbuf_grow(kv, sizeof(uint32_t)); - if (kv->databuf == NULL) return; - - kv->_dict = kv->datalen; - kv->datalen += sizeof(uint32_t); - - kv->_key = kv->datalen; - kv->_vlist = 0; - kv->_val = 0; - - /* increment and rewrite the dict count */ - p = kv->databuf; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - dict_count = ntohl(x); - - dict_count++; - x = htonl(dict_count); - memcpy(p, &x, sizeof(uint32_t)); -} - -void -kvbuf_add_key(kvbuf_t *kv, const char *key) -{ - uint32_t kl, x, key_count, delta; - char *p; - - if (kv == NULL) return; - if (key == NULL) return; - - kl = strlen(key) + 1; - - /* Grow to hold key len, key, and value list count. */ - delta = (2 * sizeof(uint32_t)) + kl; - kvbuf_grow(kv, delta); - - if (kv->databuf == NULL) return; - - /* increment and rewrite the key count for the current dictionary */ - p = kv->databuf + kv->_dict; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - key_count = ntohl(x); - - if (key_count == 0) kv->_key = kv->_dict + sizeof(uint32_t); - else kv->_key = kv->datalen; - - key_count++; - x = htonl(key_count); - memcpy(p, &x, sizeof(uint32_t)); - - /* append key to data buffer */ - p = kv->databuf + kv->datalen; - - x = htonl(kl); - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - memcpy(p, key, kl); - p += kl; - - kv->_vlist = kv->datalen + sizeof(uint32_t) + kl; - - x = 0; - memcpy(p, &x, sizeof(uint32_t)); - - kv->datalen += delta; - kv->_val = kv->datalen; -} - -void -kvbuf_add_val_len(kvbuf_t *kv, const char *val, uint32_t len) -{ - uint32_t x, val_count, delta; - char *p; - - if (kv == NULL) return; - if (val == NULL) return; - if (len == 0) return; - - /* Grow to hold val len and value. */ - delta = sizeof(uint32_t) + len; - kvbuf_grow(kv, delta); - - if (kv->databuf == NULL) return; - - /* increment and rewrite the value count for the value_list dictionary */ - p = kv->databuf + kv->_vlist; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - val_count = ntohl(x); - val_count++; - x = htonl(val_count); - memcpy(p, &x, sizeof(uint32_t)); - - /* append val to data buffer */ - p = kv->databuf + kv->_val; - - x = htonl(len); - memcpy(p, &x, sizeof(uint32_t)); - p += sizeof(uint32_t); - memcpy(p, val, len); - p += len; - - kv->datalen += delta; - kv->_val = kv->datalen; -} - -/* - * WARNING! Kludge Alert! - * - * This call just looks for the buffer length encoded into a serialized kvbuf_t, - * which preceeds a pointer to a key or value. Obviously, calling it with anything - * other than a pointer value which is embedded in a kvbuf_t is asking for trouble. - */ -uint32_t -kvbuf_get_len(const char *p) -{ - uint32_t x; - - x = 0; - memcpy(&x, p - sizeof(uint32_t), sizeof(uint32_t)); - return ntohl(x); -} - -void -kvbuf_add_val(kvbuf_t *kv, const char *val) -{ - if (kv == NULL) return; - if (val == NULL) return; - - kvbuf_add_val_len(kv, val, strlen(val) + 1); -} - -void -kvbuf_free(kvbuf_t *kv) -{ - if (kv == NULL) return; - if (kv->databuf != NULL) free(kv->databuf); - memset(kv, 0, sizeof(kvbuf_t)); - free(kv); -} - -/* appends a kvbuf to an existing kvbuf */ -void -kvbuf_append_kvbuf(kvbuf_t *kv, const kvbuf_t *kv2) -{ - uint32_t curr_count, new_count, temp; - - if (kv == NULL) return; - if (kv2 == NULL) return; - - curr_count = 0; - new_count = 0; - - memcpy(&temp, kv->databuf, sizeof(uint32_t)); - curr_count = ntohl(temp); - - memcpy(&temp, kv2->databuf, sizeof(uint32_t)); - new_count = ntohl(temp); - - /* nothing to do */ - if (new_count == 0) return; - - /* add the dictionary count to the current dictionary counts */ - curr_count += new_count; - - temp = htonl(curr_count); - memcpy(kv->databuf, &temp, sizeof(uint32_t)); - - /* grow the current buffer so we can append the new buffer */ - temp = kv2->datalen - sizeof(uint32_t); - - kvbuf_grow(kv, temp); - - memcpy(kv->databuf + kv->datalen, kv2->databuf + sizeof(uint32_t), temp); - kv->datalen += temp; -} - -/* returns number of dictionaries */ -uint32_t -kvbuf_reset(kvbuf_t *kv) -{ - uint32_t x; - - if (kv == NULL) return 0; - if (kv->databuf == NULL) return 0; - - kv->_dict = 0; - kv->_key = 0; - kv->_vlist = 0; - kv->_val = 0; - - if (kv->datalen < sizeof(uint32_t)) return 0; - - x = 0; - memcpy(&x, kv->databuf, sizeof(uint32_t)); - return ntohl(x); -} - -/* advance to next dictionary, returns key count */ -uint32_t -kvbuf_next_dict(kvbuf_t *kv) -{ - uint32_t x, k, v, kcount, vcount, kl, vl; - char *p; - - if (kv == NULL) return 0; - if (kv->databuf == NULL) return 0; - - kv->_key = 0; - kv->_vlist = 0; - kv->_val = 0; - - if (kv->_dict == 0) - { - /* first dict */ - if (kv->datalen < sizeof(uint32_t)) return 0; - kv->_dict = sizeof(uint32_t); - - if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0; - - p = kv->databuf + kv->_dict; - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - kcount = ntohl(x); - - return kcount; - } - - p = kv->databuf + kv->_dict; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_dict += sizeof(uint32_t); - kcount = ntohl(x); - - for (k = 0; k < kcount; k++) - { - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_dict += sizeof(uint32_t); - kl = ntohl(x); - p += kl; - kv->_dict += kl; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_dict += sizeof(uint32_t); - vcount = ntohl(x); - - for (v = 0; v < vcount; v++) - { - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_dict += sizeof(uint32_t); - vl = ntohl(x); - p += vl; - kv->_dict += vl; - } - } - - if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0; - - p = kv->databuf + kv->_dict; - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - kcount = ntohl(x); - - return kcount; -} - -/* advance to next key, returns key and sets val_count */ -char * -kvbuf_next_key(kvbuf_t *kv, uint32_t *val_count) -{ - uint32_t x, kl, v, vl, vc; - char *p, *out; - - if (kv == NULL) return NULL; - if (val_count == NULL) return NULL; - - *val_count = 0; - - if (kv->databuf == NULL) return NULL; - if (kv->_dict == 0) return NULL; - - kv->_vlist = 0; - kv->_val = 0; - - if (kv->_key == 0) - { - /* first key */ - if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return NULL; - kv->_key = kv->_dict + sizeof(uint32_t); - } - else - { - p = kv->databuf + kv->_key; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - kl = ntohl(x); - - if (kv->datalen < (kv->_key + sizeof(uint32_t) + kl)) return NULL; - - p += (sizeof(uint32_t) + kl); - kv->_key += (sizeof(uint32_t) + kl); - - /* skip over values */ - if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - vc = ntohl(x); - - p += sizeof(uint32_t); - kv->_key += sizeof(uint32_t); - - for (v = 0; v < vc; v++) - { - if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; - - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - vl = ntohl(x); - - if (kv->datalen < (kv->_key + kl)) return NULL; - - p += (sizeof(uint32_t) + vl); - kv->_key += (sizeof(uint32_t) + vl); - } - } - - if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL; - - p = kv->databuf + kv->_key; - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - kl = ntohl(x); - - p += sizeof(uint32_t); - out = p; - - kv->_vlist = kv->_key + sizeof(uint32_t) + kl; - if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) - { - kv->_vlist = 0; - return NULL; - } - - p = kv->databuf + kv->_vlist; - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - *val_count = ntohl(x); - - return out; -} - -char * -kvbuf_next_val(kvbuf_t *kv) -{ - return kvbuf_next_val_len(kv, NULL); -} - -char * -kvbuf_next_val_len(kvbuf_t *kv, uint32_t *len) -{ - uint32_t x = 0; - uint32_t vltemp = 0; - char *p; - - if (kv == NULL) return NULL; - if (kv->databuf == NULL) return NULL; - if (kv->_vlist == 0) return NULL; - - if (kv->_val == 0) - { - /* first val */ - if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) return NULL; - kv->_val = kv->_vlist + sizeof(uint32_t); - - p = kv->databuf + kv->_val; - - memcpy(&x, p, sizeof(uint32_t)); - vltemp = ntohl(x); - } - else - { - p = kv->databuf + kv->_val; - - memcpy(&x, p, sizeof(uint32_t)); - vltemp = ntohl(x); - - if (kv->datalen < (kv->_val + sizeof(uint32_t) + vltemp)) return NULL; - - p += (sizeof(uint32_t) + vltemp); - kv->_val += (sizeof(uint32_t) + vltemp); - } - - if (kv->datalen < (kv->_val + sizeof(uint32_t))) return NULL; - - if (len != NULL) (*len) = vltemp; - p = kv->databuf + kv->_val + sizeof(uint32_t); - return p; -} - -/* - * Builds a kvarray_t / kvdict_t structure on top of a kvbuf_t. - * It allocates the appropriate number of kvdict_t structures - * for the array, sets all the counters, and fills in pointers - * for keys and valuse. The pointers are NOT to newly allocated - * strings: they just point into the kvbuf data buffer. - * - * To dispose of the kvarray_t and all of the associated - * memory AND to free the original kvbuf, clients only - * need to call kvarray_free(). - */ -kvarray_t * -kvbuf_decode(kvbuf_t *kv) -{ - kvarray_t *a; - uint32_t x, d, k, v; - char *p; - - if (kv == NULL) return NULL; - if (kv->databuf == NULL) return NULL; - - if (kv->datalen < sizeof(uint32_t)) return NULL; - - p = kv->databuf; - kv->_size = kv->datalen; - - /* array count */ - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_size -= sizeof(uint32_t); - x = ntohl(x); - - if (x == 0) return NULL; - - a = (kvarray_t *)calloc(1, sizeof(kvarray_t)); - if (a == NULL) return NULL; - - a->count = x; - a->dict = (kvdict_t *)calloc(a->count, sizeof(kvdict_t)); - if (a->dict == NULL) - { - free(a); - return NULL; - } - - for (d = 0; d < a->count; d++) - { - if (kv->_size < sizeof(uint32_t)) - { - kvarray_free(a); - return NULL; - } - - /* key count */ - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_size -= sizeof(uint32_t); - a->dict[d].kcount = ntohl(x); - - if (a->dict[d].kcount > 0) - { - a->dict[d].key = (const char **)calloc(a->dict[d].kcount, sizeof(const char *)); - if (a->dict[d].key == NULL) - { - kvarray_free(a); - return NULL; - } - - a->dict[d].vcount = (uint32_t *)calloc(a->dict[d].kcount, sizeof(uint32_t)); - if (a->dict[d].vcount == NULL) - { - kvarray_free(a); - return NULL; - } - - a->dict[d].val = (const char ***)calloc(a->dict[d].kcount, sizeof(char **)); - if (a->dict[d].val == NULL) - { - kvarray_free(a); - return NULL; - } - } - - for (k = 0; k < a->dict[d].kcount; k++) - { - /* get key */ - if (kv->_size < sizeof(uint32_t)) - { - kvarray_free(a); - return NULL; - } - - /* key length */ - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_size -= sizeof(uint32_t); - x = ntohl(x); - - if (kv->_size < x) - { - kvarray_free(a); - return NULL; - } - - /* key data */ - a->dict[d].key[k] = p; - - p += x; - kv->_size -= x; - - if (kv->_size < sizeof(uint32_t)) - { - kvarray_free(a); - return NULL; - } - - /* val count */ - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_size -= sizeof(uint32_t); - a->dict[d].vcount[k] = ntohl(x); - - if (a->dict[d].vcount[k] > 0) - { - /* N.B. we add a NULL pointer at the end of the list */ - a->dict[d].val[k] = (const char **)calloc(a->dict[d].vcount[k] + 1, sizeof(const char *)); - if (a->dict[d].val[k] == NULL) - { - kvarray_free(a); - return NULL; - } - } - - for (v = 0; v < a->dict[d].vcount[k]; v++) - { - /* get val */ - if (kv->_size < sizeof(uint32_t)) - { - kvarray_free(a); - return NULL; - } - - /* val length */ - x = 0; - memcpy(&x, p, sizeof(uint32_t)); - p += sizeof(uint32_t); - kv->_size -= sizeof(uint32_t); - x = ntohl(x); - - if (kv->_size < x) - { - kvarray_free(a); - return NULL; - } - - /* val data */ - a->dict[d].val[k][v] = p; - - p += x; - kv->_size -= x; - } - } - } - - a->kv = kv; - return a; -} - -void -kvarray_free(kvarray_t *a) -{ - uint32_t d, k; - - if (a == NULL) return; - - for (d = 0; d < a->count; d++) - { - for (k = 0; k < a->dict[d].kcount; k++) - { - if (a->dict[d].val == NULL) continue; - if (a->dict[d].val[k] != NULL) free(a->dict[d].val[k]); - } - - if (a->dict[d].key != NULL) free(a->dict[d].key); - if (a->dict[d].vcount != NULL) free(a->dict[d].vcount); - if (a->dict[d].val != NULL) free(a->dict[d].val); - } - - a->count = 0; - - if (a->dict != NULL) free(a->dict); - a->dict = NULL; - - if (a->kv != NULL) kvbuf_free(a->kv); - a->kv = NULL; - - free(a); -} - -kern_return_t -LI_DSLookupGetProcedureNumber(const char *name, int32_t *procno) -{ - kern_return_t status; - security_token_t token; - uint32_t n, len; - - if (name == NULL) return KERN_FAILURE; - - len = strlen(name) + 1; - if (len == 1) return KERN_FAILURE; - - token.val[0] = -1; - token.val[1] = -1; - - if (_ds_running() == 0) return KERN_FAILURE; - if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; - - status = MIG_SERVER_DIED; - for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) - { - status = libinfoDSmig_GetProcedureNumber(_ds_port, (char *)name, procno, &token); - - if (status == MACH_SEND_INVALID_DEST) - { - mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); - status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port); - if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL; - status = MIG_SERVER_DIED; - } - } - - if (status != KERN_SUCCESS) - { -#ifdef DEBUG - asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s status %u", name, status); -#endif - return status; - } - - if (token.val[0] != 0) - { -#ifdef DEBUG - asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s auth failure uid=%d", name, token.val[0]); -#endif - return KERN_FAILURE; - } - -#ifdef DEBUG - asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s = %d", name, *procno); -#endif - return status; -} - -__private_extern__ kern_return_t -LI_DSLookupQuery(int32_t procno, kvbuf_t *request, kvarray_t **reply) -{ - kern_return_t status; - security_token_t token; - uint32_t n; - mach_msg_type_number_t illen, oolen; - char ilbuf[MAX_MIG_INLINE_DATA]; - vm_offset_t oobuf; - kvbuf_t *out; - - if (reply == NULL) return KERN_FAILURE; - if ((request != NULL) && ((request->databuf == NULL) || (request->datalen == 0))) return KERN_FAILURE; - - token.val[0] = -1; - token.val[1] = -1; - *reply = NULL; - - if (_ds_running() == 0) return KERN_FAILURE; - if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE; - - status = MIG_SERVER_DIED; - for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++) - { - illen = 0; - oolen = 0; - oobuf = 0; - - if (request != NULL) - { - status = libinfoDSmig_Query(_ds_port, procno, request->databuf, request->datalen, ilbuf, &illen, &oobuf, &oolen, &token); - } - else - { - status = libinfoDSmig_Query(_ds_port, procno, "", 0, ilbuf, &illen, &oobuf, &oolen, &token); - } - - if (status == MACH_SEND_INVALID_DEST) - { - mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); - status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port); - if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL; - status = MIG_SERVER_DIED; - } - } - - if (status != KERN_SUCCESS) - { -#ifdef DEBUG - asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status %u", procno, status); -#endif - return status; - } - - if (token.val[0] != 0) - { -#ifdef DEBUG - asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d auth failure uid=%d", procno, token.val[0]); -#endif - if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); - return KERN_FAILURE; - } - - out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t)); - if (out == NULL) - { - if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); - return KERN_FAILURE; - } - - if (oolen > 0) - { - out->datalen = oolen; - out->databuf = malloc(oolen); - if (out->databuf == NULL) - { - free(out); - *reply = NULL; - vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); - return KERN_FAILURE; - } - - memcpy(out->databuf, (char *)oobuf, oolen); - vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen); - } - else if (illen > 0) - { - out->datalen = illen; - out->databuf = malloc(illen); - if (out->databuf == NULL) - { - free(out); - *reply = NULL; - return KERN_FAILURE; - } - - memcpy(out->databuf, ilbuf, illen); - } - - *reply = kvbuf_decode(out); - if (*reply == NULL) - { - /* DS returned no data */ - free(out->databuf); - free(out); - } - -#ifdef DEBUG - asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status OK", procno); -#endif - return status; -} - -/* - * Get an entry from a kvarray. - * Calls the system information daemon if the list doesn't exist (first call), - * or extracts the next entry if the list has been fetched. - */ -__private_extern__ void * -LI_getent(const char *procname, int *procnum, void *(*extract)(kvarray_t *), int tkey, size_t esize) -{ - void *entry; - struct li_thread_info *tdata; - kvarray_t *reply; - kern_return_t status; - - tdata = LI_data_create_key(tkey, esize); - if (tdata == NULL) return NULL; - - if (tdata->li_vm == NULL) - { - if (*procnum < 0) - { - status = LI_DSLookupGetProcedureNumber(procname, procnum); - if (status != KERN_SUCCESS) - { - LI_data_free_kvarray(tdata); - tdata->li_vm = NULL; - return NULL; - } - } - - reply = NULL; - status = LI_DSLookupQuery(*procnum, NULL, &reply); - - if (status != KERN_SUCCESS) - { - LI_data_free_kvarray(tdata); - tdata->li_vm = NULL; - return NULL; - } - - tdata->li_vm = (char *)reply; - } - - entry = extract((kvarray_t *)(tdata->li_vm)); - if (entry == NULL) - { - LI_data_free_kvarray(tdata); - tdata->li_vm = NULL; - return NULL; - } - - return entry; -} - -__private_extern__ void * -LI_getone(const char *procname, int *procnum, void *(*extract)(kvarray_t *), const char *key, const char *val) -{ - void *entry; - kvbuf_t *request; - kvarray_t *reply; - kern_return_t status; - - if (*procnum < 0) - { - status = LI_DSLookupGetProcedureNumber(procname, procnum); - if (status != KERN_SUCCESS) return NULL; - } - - request = kvbuf_query_key_val(key, val); - if (request == NULL) return NULL; - - reply = NULL; - status = LI_DSLookupQuery(*procnum, request, &reply); - kvbuf_free(request); - - if (status != KERN_SUCCESS) return NULL; - - entry = extract(reply); - kvarray_free(reply); - - return entry; -} - -__private_extern__ -int LI_L1_cache_check(int tkey) -{ - int check, x; - const char *notify_key; - - /* check if L1 cache is disabled */ - if (gL1CacheEnabled == 0) return LI_L1_CACHE_DISABLED; - - /* Initialize on first call */ - if (_L1_notify_token[0] == -1) - { - pthread_mutex_lock(&_notify_lock); - if (_L1_notify_token[0] == -1) notify_register_check(L1_CACHE_NOTIFICATION_KEY_GLOBAL, &(_L1_notify_token[0])); - pthread_mutex_unlock(&_notify_lock); - } - - if (_L1_notify_token[0] == -1) return LI_L1_CACHE_FAILED; - - check = 1; - if (notify_check(_L1_notify_token[0], &check) != 0) return LI_L1_CACHE_FAILED; - if (check == 1) return LI_L1_CACHE_STALE; - - x = 0; - notify_key = NULL; - - switch (tkey) - { - case _li_data_key_group: - { - x = 1; - notify_key = L1_CACHE_NOTIFICATION_KEY_GROUP; - break; - } - case _li_data_key_host: - { - x = 2; - notify_key = L1_CACHE_NOTIFICATION_KEY_HOST; - break; - } - case _li_data_key_service: - { - x = 3; - notify_key = L1_CACHE_NOTIFICATION_KEY_SERVICE; - break; - } - case _li_data_key_user: - { - x = 4; - notify_key = L1_CACHE_NOTIFICATION_KEY_USER; - break; - } - default: break; - } - - if ((x != 0) && (notify_key != NULL)) - { - /* Initialize on first call */ - if (_L1_notify_token[x] == -1) - { - pthread_mutex_lock(&_notify_lock); - if (_L1_notify_token[x] == -1) notify_register_check(notify_key, &(_L1_notify_token[x])); - pthread_mutex_unlock(&_notify_lock); - } - - if (_L1_notify_token[x] == -1) return LI_L1_CACHE_FAILED; - - check = 1; - if (notify_check(_L1_notify_token[x], &check) != 0) return LI_L1_CACHE_FAILED; - if (check == 1) return LI_L1_CACHE_STALE; - } - - return LI_L1_CACHE_OK; -} - -static uint32_t -padsize(size_t curr, size_t item, const uint32_t *align) -{ - uint32_t na, diff; - - if (item > 8) item = 8; - - na = align[item]; - if (na == 0) return 0; - - diff = curr % na; - if (diff == 0) return 0; - - return na - diff; -} - - -/* - * Create a structure using in-line memory (i.e. all one blob). - * This reduces malloc/free workload. - * - * Structutre components may be strings, 1, 2, 4, or 8-byte values, - * lists of strings, or lists of 4, 8, or 16-byte values. - * - * Format keys: - * s NUL terminated string - * 1 1 byte value - * 2 2 byte value - * 4 4 byte value - * 8 8 byte value - * L long (32 or 64 bits, depending on architecture) - * * NULL-terminated list of strings - * a NULL-terminated list of 4-byte values - * b NULL-terminated list of 8-byte values - * c NULL-terminated list of 16-byte values - * - */ -__private_extern__ void * -LI_ils_create(char *fmt, ...) -{ - va_list ap; - char *arg, *f; - char **list; - void *hp, *dp, *lp, *ils; - uint8_t u8; - uint16_t u16; - uint32_t u32, i, pad; - uint64_t u64; - unsigned long l; - size_t memsize, hsize, csize, slen, largest; - const uint32_t *align; - - if (fmt == NULL) return NULL; - - largest = 0; - align = align_32; - if (sizeof(char *) == 8) align = align_64; - - /* first pass: calculate size */ - memsize = ILS_MAGIC_SIZE; - hsize = 0; - - va_start(ap, fmt); - - for (f = fmt; (*f) != '\0'; f++) - { - csize = 0; - slen = 0; - - if (*f == 's') - { - if (largest < sizeof(char *)) largest = sizeof(char *); - - csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); - arg = va_arg(ap, char *); - if (arg != NULL) slen = strlen(arg) + 1; - } - else if (*f == '1') - { - if (largest < 1) largest = 1; - - csize = 1; - u8 = va_arg(ap, int); - } - else if (*f == '2') - { - if (largest < 2) largest = 2; - - csize = 2 + padsize(hsize, 2, align); - u16 = va_arg(ap, int); - } - else if (*f == '4') - { - if (largest < 4) largest = 4; - - csize = 4 + padsize(hsize, 4, align); - u32 = va_arg(ap, uint32_t); - } - else if (*f == '8') - { - if (largest < 8) largest = 8; - - csize = 8 + padsize(hsize, 8, align); - u64 = va_arg(ap, uint64_t); - } - else if (*f == 'L') - { - if (largest < sizeof(unsigned long)) largest = sizeof(unsigned long); - - csize = sizeof(unsigned long) + padsize(hsize, sizeof(unsigned long), align); - l = va_arg(ap, unsigned long); - } - else if (*f == '*') - { - /* NULL-terminated list of strings */ - if (largest < sizeof(char *)) largest = sizeof(char *); - - csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); - list = va_arg(ap, char **); - if (list != NULL) - { - for (i = 0; list[i] != NULL; i++) - { - slen += sizeof(char *); - slen += (strlen(list[i]) + 1); - } - - slen += sizeof(char *); - } - } - else if (*f == 'a') - { - /* NULL-terminated list of 4-byte values */ - if (largest < sizeof(char *)) largest = sizeof(char *); - - csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); - list = va_arg(ap, char **); - if (list != NULL) - { - for (i = 0; list[i] != NULL; i++) - { - slen += sizeof(char *); - slen += 4; - } - - slen += sizeof(char *); - } - } - else if (*f == 'b') - { - /* NULL-terminated list of 8-byte values */ - if (largest < sizeof(char *)) largest = sizeof(char *); - - csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); - list = va_arg(ap, char **); - if (list != NULL) - { - for (i = 0; list[i] != NULL; i++) - { - slen += sizeof(char *); - slen += 8; - } - - slen += sizeof(char *); - } - } - else if (*f == 'c') - { - /* NULL-terminated list of 16-byte values */ - if (largest < sizeof(char *)) largest = sizeof(char *); - - csize = sizeof(char *) + padsize(hsize, sizeof(char *), align); - list = va_arg(ap, char **); - if (list != NULL) - { - for (i = 0; list[i] != NULL; i++) - { - slen += sizeof(char *); - slen += 16; - } - - slen += sizeof(char *); - } - } - else return NULL; - - memsize += csize; - memsize += slen; - hsize += csize; - } - - va_end(ap); - - pad = padsize(hsize, largest, align); - memsize += pad; - hsize += pad; - - ils = malloc(memsize); - if (ils == NULL) - { - errno = ENOMEM; - return NULL; - } - - /* insert magic cookie */ - dp = ils + hsize; - memcpy(dp, ILS_MAGIC, ILS_MAGIC_SIZE); - dp += ILS_MAGIC_SIZE; - - hp = ils; - hsize = 0; - - /* second pass: copy data */ - va_start(ap, fmt); - for (f = fmt; (*f) != '\0'; f++) - { - if (*f == 's') - { - pad = padsize(hsize, sizeof(char *), align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - arg = va_arg(ap, char *); - if (arg == NULL) - { - memset(hp, 0, sizeof(char *)); - } - else - { - memcpy(hp, &dp, sizeof(char *)); - slen = strlen(arg) + 1; - memcpy(dp, arg, slen); - dp += slen; - } - - hp += sizeof(char *); - hsize += sizeof(char *); - } - else if (*f == '1') - { - u8 = va_arg(ap, int); - memcpy(hp, &u8, sizeof(uint8_t)); - hp += sizeof(uint8_t); - } - else if (*f == '2') - { - pad = padsize(hsize, 2, align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - u16 = va_arg(ap, int); - memcpy(hp, &u16, sizeof(uint16_t)); - - hp += sizeof(uint16_t); - hsize += sizeof(uint16_t); - } - else if (*f == '4') - { - pad = padsize(hsize, 4, align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - u32 = va_arg(ap, uint32_t); - memcpy(hp, &u32, sizeof(uint32_t)); - - hp += sizeof(uint32_t); - hsize += sizeof(uint32_t); - } - else if (*f == '8') - { - pad = padsize(hsize, 8, align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - u64 = va_arg(ap, uint64_t); - memcpy(hp, &u64, sizeof(uint64_t)); - - hp += sizeof(uint64_t); - hsize += sizeof(uint64_t); - } - else if (*f == 'L') - { - pad = padsize(hsize, sizeof(unsigned long), align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - l = va_arg(ap, unsigned long); - memcpy(hp, &l, sizeof(unsigned long)); - - hp += sizeof(unsigned long); - hsize += sizeof(unsigned long); - } - else if (*f == '*') - { - pad = padsize(hsize, sizeof(char *), align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - list = va_arg(ap, char **); - - if (list == NULL) - { - memset(hp, 0, sizeof(char *)); - } - else - { - memcpy(hp, &dp, sizeof(char *)); - - for (i = 0; list[i] != NULL; i++); - - lp = dp; - dp += ((i + 1) * sizeof(char *)); - - for (i = 0; list[i] != NULL; i++) - { - memcpy(lp, &dp, sizeof(char *)); - lp += sizeof(char *); - slen = strlen(list[i]) + 1; - memcpy(dp, list[i], slen); - dp += slen; - } - - memset(lp, 0, sizeof(char *)); - } - - hp += sizeof(char *); - hsize += sizeof(char *); - } - else if (*f == 'a') - { - pad = padsize(hsize, sizeof(char *), align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - list = va_arg(ap, char **); - - if (list == NULL) - { - memset(hp, 0, sizeof(char *)); - } - else - { - memcpy(hp, &dp, sizeof(char *)); - - for (i = 0; list[i] != NULL; i++); - - lp = dp; - dp += ((i + 1) * sizeof(char *)); - - for (i = 0; list[i] != NULL; i++) - { - memcpy(lp, &dp, sizeof(char *)); - lp += sizeof(char *); - slen = 4; - memcpy(dp, list[i], slen); - dp += slen; - } - - memset(lp, 0, sizeof(char *)); - } - - hp += sizeof(char *); - hsize += sizeof(char *); - } - else if (*f == 'b') - { - pad = padsize(hsize, sizeof(char *), align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - list = va_arg(ap, char **); - - if (list == NULL) - { - memset(hp, 0, sizeof(char *)); - } - else - { - memcpy(hp, &dp, sizeof(char *)); - - for (i = 0; list[i] != NULL; i++); - - lp = dp; - dp += ((i + 1) * sizeof(char *)); - - for (i = 0; list[i] != NULL; i++) - { - memcpy(lp, &dp, sizeof(char *)); - lp += sizeof(char *); - slen = 8; - memcpy(dp, list[i], slen); - dp += slen; - } - - memset(lp, 0, sizeof(char *)); - } - - hp += sizeof(char *); - hsize += sizeof(char *); - } - else if (*f == 'c') - { - pad = padsize(hsize, sizeof(char *), align); - if (pad != 0) - { - memset(hp, 0, pad); - hp += pad; - hsize += pad; - } - - list = va_arg(ap, char **); - - if (list == NULL) - { - memset(hp, 0, sizeof(char *)); - } - else - { - memcpy(hp, &dp, sizeof(char *)); - - for (i = 0; list[i] != NULL; i++); - - lp = dp; - dp += ((i + 1) * sizeof(char *)); - - for (i = 0; list[i] != NULL; i++) - { - memcpy(lp, &dp, sizeof(char *)); - lp += sizeof(char *); - slen = 16; - memcpy(dp, list[i], slen); - dp += slen; - } - - memset(lp, 0, sizeof(char *)); - } - - hp += sizeof(char *); - hsize += sizeof(char *); - } - } - - va_end(ap); - - pad = padsize(hsize, largest, align); - if (pad > 0) memset(hp, 0, pad); - - return ils; -} - -__private_extern__ int -LI_ils_free(void *ils, size_t len) -{ - char *p; - - if (ils == NULL) return 0; - - p = ils + len; - if (memcmp(p, ILS_MAGIC, ILS_MAGIC_SIZE) != 0) return -1; - - free(ils); - - return 0; -} - -kern_return_t -_lookup_link(mach_port_t server, char *name, int *procno) -{ - syslog(LOG_ERR, "RED ALERT! lookupd call %s from pid %u", name, getpid()); - return KERN_FAILURE; -} - -kern_return_t -_lookup_one(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char *outdata, mach_msg_type_number_t *outdataCnt) -{ - return KERN_FAILURE; -} - -kern_return_t -_lookup_all(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt) -{ - return KERN_FAILURE; -} - -kern_return_t -_lookup_ooall(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt) -{ - return KERN_FAILURE; -} diff --git a/lookup.subproj/lu_utils.h b/lookup.subproj/lu_utils.h deleted file mode 100644 index 77273a5..0000000 --- a/lookup.subproj/lu_utils.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Useful macros and other stuff for generic lookups - * Copyright (C) 1989 by NeXT, Inc. - */ - -#ifndef _LU_UTILS_H_ -#define _LU_UTILS_H_ - -#include "DSlibinfoMIG_types.h" -#include "kvbuf.h" -#include - -#define _li_data_key_alias 10010 -#define _li_data_key_bootp 10020 -#define _li_data_key_bootparams 10030 -#define _li_data_key_fstab 10040 -#define _li_data_key_group 10050 -#define _li_data_key_host 10060 -#define _li_data_key_netgroup 10070 -#define _li_data_key_network 10080 -#define _li_data_key_printer 10090 -#define _li_data_key_protocol 10100 -#define _li_data_key_rpc 10110 -#define _li_data_key_service 10120 -#define _li_data_key_user 10130 - -/* - * Return values for LI_L1_cache_check. - */ -#define LI_L1_CACHE_OK 0 -#define LI_L1_CACHE_STALE 1 -#define LI_L1_CACHE_DISABLED 2 -#define LI_L1_CACHE_FAILED 3 - -struct li_thread_info -{ - void *li_entry; - size_t li_entry_size; - char *li_vm; - uint32_t li_vm_length; - uint32_t li_vm_cursor; - uint32_t li_flags; -}; - -extern mach_port_t _ds_port; -extern int _ds_running(void); - -/* - * Thread-local data management - */ -__private_extern__ void *LI_data_find_key(uint32_t key); -__private_extern__ void *LI_data_create_key(uint32_t key, size_t esize); -__private_extern__ void LI_data_set_key(uint32_t key, void *data); -__private_extern__ void *LI_data_get_key(uint32_t key); -__private_extern__ void LI_data_free_kvarray(struct li_thread_info *tdata); -__private_extern__ void LI_data_recycle(struct li_thread_info *tdata, void *entry, size_t entrysize); -__private_extern__ void *LI_ils_create(char *fmt, ...); -__private_extern__ int LI_ils_free(void *ils, size_t len); - -kern_return_t _lookup_link(mach_port_t server, char *name, int *procno); -kern_return_t _lookup_one(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char *outdata, mach_msg_type_number_t *outdataCnt); -kern_return_t _lookup_all(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt); -kern_return_t _lookup_ooall(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt); - -/* - * Directory Service queries - */ -kern_return_t LI_DSLookupGetProcedureNumber(const char *name, int *procno); - -__private_extern__ kern_return_t LI_DSLookupQuery(int32_t proc, kvbuf_t *request, kvarray_t **reply); -__private_extern__ void *LI_getent(const char *procname, int *procnum, void *(*extract)(kvarray_t *), int tkey, size_t esize); -__private_extern__ void *LI_getone(const char *procname, int *procnum, void *(*extract)(kvarray_t *), const char *key, const char *val); - -/* - * L1 cache - * Takes _li_data_key_xxx as an argument. - * Returns 0 is the cache is valid, non-zero if it is invalid. - */ -__private_extern__ int LI_L1_cache_check(int tkey); - -/* - * Async support - */ -void LI_async_call_cancel(mach_port_t p, void **context); -kern_return_t LI_async_handle_reply(mach_msg_header_t *msg, kvarray_t **reply, void **callback, void **context); -kern_return_t LI_async_receive(mach_port_t p, kvarray_t **reply); -kern_return_t LI_async_send(mach_port_t *p, uint32_t proc, kvbuf_t *query); -kern_return_t LI_async_start(mach_port_t *p, uint32_t proc, kvbuf_t *query, void *callback, void *context); - -/* - * kvbuf query support - */ -__private_extern__ kvbuf_t *kvbuf_query(char *fmt, ...); -__private_extern__ kvbuf_t *kvbuf_query_key_int(const char *key, int32_t i); -__private_extern__ kvbuf_t *kvbuf_query_key_uint(const char *key, uint32_t u); -__private_extern__ kvbuf_t *kvbuf_query_key_val(const char *key, const char *val); - -#endif /* ! _LU_UTILS_H_ */ diff --git a/lookup.subproj/mdns_module.c b/lookup.subproj/mdns_module.c new file mode 100644 index 0000000..b90fb5b --- /dev/null +++ b/lookup.subproj/mdns_module.c @@ -0,0 +1,1960 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "ils.h" +#include "netdb.h" +#include "si_module.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* from dns_util.c */ +#define DNS_MAX_RECEIVE_SIZE 65536 + +#define INET_NTOP_AF_INET_OFFSET 4 +#define INET_NTOP_AF_INET6_OFFSET 8 + +#define IPPROTO_UNSPEC 0 + +static int _mdns_debug = 0; + +// mutex protects DNSServiceProcessResult and DNSServiceRefDeallocate +static pthread_mutex_t _mdns_mutex = PTHREAD_MUTEX_INITIALIZER; + +// XXX +// Options: timeout:n total_timeout attempts + +/* _dns_config_token: notify token indicating dns config needs refresh + */ +static int _dns_config_token = -1; + +typedef struct { + int32_t rc; + dns_config_t *dns; + dns_resolver_t *primary; + uint32_t n_defaults; + dns_resolver_t **defaults; + char **search_list; + int ndots; +} mdns_config_t; + +typedef struct { + uint16_t priority; + uint16_t weight; + uint16_t port; + uint8_t target[0]; +} mdns_rr_srv_t; + +typedef struct mdns_srv_t mdns_srv_t; +struct mdns_srv_t { + si_srv_t srv; + mdns_srv_t *next; +}; + +typedef struct { + struct hostent host; + int alias_count; + int addr_count; +} mdns_hostent_t; + +typedef struct { + mdns_hostent_t *h4; + mdns_hostent_t *h6; + mdns_srv_t *srv; + uint64_t ttl; + uint32_t ifnum; +} mdns_reply_t; + +DNSServiceRef _mdns_sdref; +DNSServiceRef _mdns_old_sdref; + +static int _mdns_query_mDNSResponder(const char *name, int class, int type, + uint8_t *answer, uint32_t *anslen, + mdns_reply_t *reply, uint32_t timeout); + +static int _mdns_resolver_get_option(dns_resolver_t *resolver, const char* option); +static void _mdns_hostent_clear(mdns_hostent_t *h); +static void _mdns_reply_clear(mdns_reply_t *r); + +static const char hexchar[] = "0123456789abcdef"; + +#define BILLION 1000000000 + +/* length of a reverse DNS IPv6 address query name, e.g. "9.4.a.f.c.e.e.f.e.e.1.5.4.1.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa" */ +#define IPv6_REVERSE_LEN 72 + +/* index of the trailing char that must be "8", "9", "A", "a", "b", or "B" */ +#define IPv6_REVERSE_LINK_LOCAL_TRAILING_CHAR 58 + +/* index of low-order nibble of embedded scope id */ +#define IPv6_REVERSE_LINK_LOCAL_SCOPE_ID_LOW 48 + +const static uint8_t hexval[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32 - 47 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 48 - 63 */ + 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 64 - 79 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 95 */ + 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 96 - 111 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 112 - 127 */ +}; + +/* + * _mdns_create_search_list + * Creates a NULL terminated array of strings from the specied resolver's + * search list, or from the components of the specified resolver's domain + * if search list is empty. + * Free the list and elements with free(3) when done. + */ +static char ** +_mdns_create_search_list(dns_resolver_t *resolver) +{ + int n, m; + char *p, *domain; + char **list; + + if (resolver == NULL) return NULL; + + // return the search list if present + if (resolver->n_search > 0) { + list = (char **)calloc(resolver->n_search+1, sizeof(char *)); + if (list == NULL) return NULL; + for (n = 0; n < resolver->n_search; ++n) { + list[n] = strdup(resolver->search[n]); + } + return list; + } + + if (resolver->domain == NULL) return NULL; + domain = strdup(resolver->domain); + if (domain == NULL) return NULL; + + // count dots + n = 0; + for (p = domain; *p != '\0'; p++) { + if (*p == '.') n++; + } + + // trim trailing dots + for (p--; (p >= domain) && (*p == '.'); p--) { + *p = '\0'; + n--; + } + + // make sure the resulting string is not empty + if (p < domain) { + free(domain); + return NULL; + } + + // dots are separators, so number of components is one larger + n++; + + m = 0; + list = (char **)calloc(n+1, sizeof(char *)); + if (list == NULL) return NULL; + // first item in list is domain itself + list[m++] = domain; + + // include parent domains with at least LOCALDOMAINPARTS components + p = domain; + while (n > LOCALDOMAINPARTS) { + // find next component + while ((*p != '.') && (*p != '\0')) p++; + if (*p == '\0') break; + p++; + // add to the list + n--; + list[m++] = strdup(p); + } + return list; +} + +/* _mdns_resolver_get_option + * Determines whether the specified option is present in the resolver. + */ +static int +_mdns_resolver_get_option(dns_resolver_t *resolver, const char* option) +{ + if (resolver == NULL) return 0; + int len = strlen(option); + char *options = resolver->options; + if (options == NULL) return 0; + // look for "(^| )option( |:|$)" + char *ptr = strstr(options, option); + while (ptr) { + if (ptr == options || ptr[-1] == ' ') { + if (ptr[len] == ' ' || ptr[len] == 0) { + return 1; + } else if (ptr[len] == ':') { + return strtol(&ptr[len+1], NULL, 10); + } + } + ptr = strstr(ptr, option); + } + return 0; +} + +/* _mdns_compare_resolvers + * Compares two dns_resolver_t pointers by search order ascending. + */ +static int +_mdns_compare_resolvers(const void *a, const void *b) +{ + dns_resolver_t **x = (dns_resolver_t **)a, **y = (dns_resolver_t **)b; + return ((*x)->search_order - (*y)->search_order); +} + +/* _mdns_create_default_resolvers_list + * Returns an array of dns_resolver_t containing only default resolvers. + * A resolver is a default resolver if it is the primary resolver or if it + * contains the "default" configuration option. + */ +static void +_mdns_config_init_default_resolvers(mdns_config_t *config) +{ + uint32_t count = config->dns->n_resolver; + if (count == 0) return; + config->defaults = calloc(count, sizeof(dns_resolver_t *)); + if (config->defaults == NULL) return; + int m = 0, i, j; + if (config->primary) config->defaults[m++] = config->primary; + // iterate the resolvers, add any default resolvers that are not + // already in the list. + for (i = 0; i < count; ++i) { + dns_resolver_t *resolver = config->dns->resolver[i]; + if (_mdns_resolver_get_option(resolver, "default")) { + int exists = 0; + for (j = 0; j < m; ++j) { + if (config->defaults[j] == resolver) { + exists = 1; + break; + } + } + if (!exists) { + config->defaults[m++] = resolver; + } + } + } + config->n_defaults = m; + // sort list by search order ascending + qsort(config->defaults, config->n_defaults, + sizeof(dns_resolver_t *), _mdns_compare_resolvers); +} + +#if 0 +static void +_mdns_print_dns_resolver(dns_resolver_t *resolver) +{ + printf("resolver = {\n"); + printf("\tdomain = %s\n", resolver->domain); + int j; + for (j = 0; j < resolver->n_nameserver; ++j) { + int res; + char host[255], serv[255]; + res = getnameinfo(resolver->nameserver[j], resolver->nameserver[j]->sa_len, host, sizeof(host), serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV); + if (res == 0) { + printf("\tnameserver[%d] = %s:%s\n", j, host, serv); + } else { + printf("\tnameserver[%d] = %s\n", j, gai_strerror(res)); + } + } + printf("\tport = %d\n", resolver->port); + for (j = 0; j < resolver->n_search; ++j) { + printf("\tsearch[%d] = %s\n", j, resolver->search[j]); + } + // sortaddr + printf("\tn_sortaddr = %d\n", resolver->n_sortaddr); + // options + printf("\toptions = %s\n", resolver->options); + printf("\ttimeout = %d\n", resolver->timeout); + printf("\tsearch_order = %d\n", resolver->search_order); + printf("}\n"); +} + +static void +_mdns_print_dns_config(dns_config_t *config) +{ + int i; + dns_resolver_t **list = _mdns_create_sorted_resolver_list(config); + dns_resolver_t **ptr = list; + while (*ptr) { + _mdns_print_dns_resolver(*ptr); + ptr++; + } + free(list); +} + +static void +_mdns_print_hostent(mdns_hostent_t* h) +{ + if (h == NULL) return; + printf("hostent[%p] = {\n", h); + printf("\thost = {\n"); + printf("\t\th_name = %s\n", h->host.h_name); + printf("\t\th_length = %d\n", h->host.h_length); + printf("\t\th_addrtype = %d\n", h->host.h_addrtype); + char **alias = h->host.h_aliases; + while (alias && *alias) { + printf("\t\th_aliases = %s\n", *alias++); + } + char **addr = h->host.h_addr_list; + while (addr && *addr) { + printf("\t\th_addr_list = %x\n", ntohl(*(uint32_t*)*addr++)); + } + printf("\t}\n"); + printf("\talias_count = %d\n", h->alias_count); + printf("\taddr_count = %d\n", h->addr_count); + printf("}\n"); +} + +#endif + +/* _mdns_config_retain + * Retain the mdns configuration. + */ +static mdns_config_t * +_mdns_config_retain(mdns_config_t *config) { + int32_t rc; + if (config == NULL) return NULL; + rc = OSAtomicIncrement32Barrier(&config->rc); + assert(rc > 1); + return config; +} +/* _mdns_config_release + * Releases the mdns configuration structure and + * frees the data if no references remain. + */ +static void +_mdns_config_release(mdns_config_t *config) { + int32_t rc; + if (config == NULL) return; + rc = OSAtomicDecrement32Barrier(&config->rc); + assert(rc >= 0); + if (rc == 0) { + if (config->dns) dns_configuration_free(config->dns); + free(config->defaults); + char **p = config->search_list; + while (p && *p) { free(*p++); } + free(config->search_list); + free(config); + } +} + +/* _mdns_copy_system_config + * Retrieves DNS configuration from SystemConfiguration.framework. + * Checks notify notification to determine whether configuration is in need + * of a refresh. + */ +static mdns_config_t * +_mdns_copy_system_config(void) +{ + // first call needs refresh + static mdns_config_t *current_config; + mdns_config_t *config = NULL; + int refresh = 1; + int res; + + pthread_mutex_lock(&_mdns_mutex); + + // check whether the global configuration has changed + if (_dns_config_token == -1) { + res = notify_register_check(dns_configuration_notify_key(), &_dns_config_token); + if (res != NOTIFY_STATUS_OK) _dns_config_token = -1; + } + if (_dns_config_token != -1) { + res = notify_check(_dns_config_token, &refresh); + if (res != NOTIFY_STATUS_OK) refresh = 1; + } + + // return the current configuration if still valid + if (refresh == 0) { + mdns_config_t *config = _mdns_config_retain(current_config); + pthread_mutex_unlock(&_mdns_mutex); + return config; + } + + // need to allocate a new configuration + + config = calloc(1, sizeof(mdns_config_t)); + if (config != NULL) config->dns = dns_configuration_copy(); + + // failed to get new config, return previous config + if (config == NULL || config->dns == NULL) { + free(config); + config = _mdns_config_retain(current_config); + pthread_mutex_unlock(&_mdns_mutex); + return config; + } + + config->rc = 1; + if (config->dns->n_resolver > 0) { + // primary resolver is always index 0 and contains the + // search domains + config->primary = config->dns->resolver[0]; + config->search_list = _mdns_create_search_list(config->primary); + _mdns_config_init_default_resolvers(config); + } + config->ndots = _mdns_resolver_get_option(config->primary, "ndots"); + + // promote the new configuration to current + _mdns_config_release(current_config); + current_config = config; + + // return the new configuration + config = _mdns_config_retain(config); + pthread_mutex_unlock(&_mdns_mutex); + return config; +} + +/* _mdns_timeout_for_name + * Returns the appropriate timeout for the specified name based on the + * sum of the timeouts of all resolvers that match the name. + */ +static uint32_t +_mdns_timeout_for_name(mdns_config_t *config, const char *name) +{ + int i; + uint32_t timeout = 0; + + if (name == NULL) return 0; + + // use strncasecmp to ignore a trailing '.' in name + int len = strlen(name); + if ((len - 1) >= 0 && name[len-1] == '.') --len; + + const char *p = name; + while (len > 0) { + uint32_t count = config->dns->n_resolver; + for (i = 0; i < count; ++i) { + dns_resolver_t *resolver = config->dns->resolver[i]; + if (resolver->domain == NULL) continue; + if (strncasecmp(resolver->domain, p, len) == 0) { + timeout += resolver->timeout; + } + } + // discard the current label + while (len > 0) { + ++p; + --len; + if (p[-1] == '.') break; + } + } + return timeout; +} + +/* _mdns_query_unqualified + * Performs a query for the name as an unqualified name (appends each + * of the default resolver's domains). + */ +static int +_mdns_query_unqualified(mdns_config_t *config, const char *name, uint32_t class, uint32_t type, uint8_t *buf, uint32_t *len, mdns_reply_t *reply) +{ + int i, res = -1; + + for (i = 0; i < config->n_defaults; ++i) { + dns_resolver_t *resolver = config->defaults[i]; + char *qname; + + asprintf(&qname, "%s.%s", name, + resolver->domain ? resolver->domain : ""); + res = _mdns_query_mDNSResponder(qname, class, type, buf, len, reply, resolver->timeout); + free(qname); + + if (res == 0) break; + else _mdns_reply_clear(reply); + } + return res; +} + +/* _mdns_query_absolute + * Performs a query for the name as an absolute name (does not qualify with any + * additional domains). + */ +static int +_mdns_query_absolute(mdns_config_t *config, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint8_t *buf, uint32_t *len, mdns_reply_t *reply) +{ + int res = -1; + char *qname = (char *)name; + + uint32_t timeout = _mdns_timeout_for_name(config, name); + + if (fqdn == 0) asprintf(&qname, "%s.", name); + res = _mdns_query_mDNSResponder(qname, class, type, buf, len, reply, timeout); + if (fqdn == 0) free(qname); + if (res != 0) _mdns_reply_clear(reply); + return res; +} + +static int +_mdns_search(const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint32_t recurse, uint8_t *buf, uint32_t *len, mdns_reply_t *reply) +{ + int res = -1; + int i, n, ndots; + char *dot; + + if (name == NULL) return -1; + + mdns_config_t *config = _mdns_copy_system_config(); + if (config == NULL) return -1; + + // NDOTS is the threshold for trying a qualified name "as is" + ndots = config->ndots; + if (ndots == 0) ndots = 1; + + // count the dots, and remember position of the last one + n = 0; + dot = NULL; + for (i = 0; name[i] != '\0'; i++) { + if (name[i] == '.') { + n++; + dot = (char *)(name + i); + } + } + // FQDN has dot for last character + if (fqdn == 0 && dot != NULL && dot[1] == '\0') fqdn = 1; + + // if the name has at least ndots, try first as an absolute query. + // FQDN and PTR queries are always absolute. + if (n >= ndots || fqdn == 1 || type == ns_t_ptr) { + res = _mdns_query_absolute(config, name, class, type, fqdn, buf, len, reply); + if (res == 0) { + _mdns_config_release(config); + return res; + } + } + + // stop if FQDN, PTR, or no recursion requested + if (fqdn == 1 || type == ns_t_ptr || recurse == 0) { + _mdns_config_release(config); + return -1; + } + + // Qualify the name with each of the search domains looking for a match. + char **search = config->search_list; + if (search != NULL) { + res = -1; + for (i = 0; i < MAXDNSRCH && search[i] != NULL; ++i) { + char *qname; + asprintf(&qname, "%s.%s", name, search[i]); + res = _mdns_search(qname, class, type, 0, 0, buf, len, reply); + free(qname); + if (res == 0) break; + } + } else { + // The name is not fully qualified and there is no search list. + // Try each default resolver, qualifying the name with that + // resolver's domain. + res = _mdns_query_unqualified(config, name, class, type, buf, len, reply); + } + _mdns_config_release(config); + return res; +} + +static char * +_mdns_reverse_ipv4(const char *addr) +{ + union + { + uint32_t a; + unsigned char b[4]; + } ab; + char *p; + + if (addr == NULL) return NULL; + + memcpy(&(ab.a), addr, 4); + + asprintf(&p, "%u.%u.%u.%u.in-addr.arpa.", ab.b[3], ab.b[2], ab.b[1], ab.b[0]); + return p; +} + +static char * +_mdns_reverse_ipv6(const char *addr) +{ + char x[65], *p; + int i, j; + u_int8_t d, hi, lo; + + if (addr == NULL) return NULL; + + x[64] = '\0'; + j = 63; + for (i = 0; i < 16; i++) + { + d = addr[i]; + lo = d & 0x0f; + hi = d >> 4; + x[j--] = '.'; + x[j--] = hexchar[hi]; + x[j--] = '.'; + x[j--] = hexchar[lo]; + } + + asprintf(&p, "%sip6.arpa.", x); + + return p; +} + +/* _mdns_canonicalize + * Canonicalize the domain name by converting to lower case and removing the + * trailing '.' if present. + */ +static char * +_mdns_canonicalize(const char *s) +{ + int i; + char *t; + if (s == NULL) return NULL; + t = strdup(s); + if (t == NULL) return NULL; + if (t[0] == '\0') return t; + for (i = 0; t[i] != '\0'; i++) { + if (t[i] >= 'A' && t[i] <= 'Z') t[i] += 32; + } + if (t[i-1] == '.') t[i-1] = '\0'; + return t; +} + +/* _mdns_hostent_append_alias + * Appends an alias to the mdns_hostent_t structure. + */ +static int +_mdns_hostent_append_alias(mdns_hostent_t *h, const char *alias) +{ + int i; + char *name; + if (h == NULL || alias == NULL) return 0; + name = _mdns_canonicalize(alias); + if (name == NULL) return -1; + + // don't add the name if it matches an existing name + if (h->host.h_name && string_equal(h->host.h_name, name)) { + free(name); + return 0; + } + for (i = 0; i < h->alias_count; ++i) { + if (string_equal(h->host.h_aliases[i], name)) { + free(name); + return 0; + } + } + + // add the alias and NULL terminate the list + h->host.h_aliases = (char **)reallocf(h->host.h_aliases, (h->alias_count+2) * sizeof(char *)); + if (h->host.h_aliases == NULL) { + h->alias_count = 0; + free(name); + return -1; + } + h->host.h_aliases[h->alias_count] = name; + ++h->alias_count; + h->host.h_aliases[h->alias_count] = NULL; + return 0; +} + +/* _mdns_hostent_append_addr + * Appends an alias to the mdns_hostent_t structure. + */ +static int +_mdns_hostent_append_addr(mdns_hostent_t *h, const uint8_t *addr, uint32_t len) +{ + if (h == NULL || addr == NULL || len == 0) return 0; + + // copy the address buffer + uint8_t *buf = malloc(len); + if (buf == NULL) return -1; + memcpy(buf, addr, len); + + // add the address and NULL terminate the list + h->host.h_addr_list = (char **)reallocf(h->host.h_addr_list, (h->addr_count+2) * sizeof(char *)); + if (h->host.h_addr_list == NULL) { + h->addr_count = 0; + return -1; + } + h->host.h_addr_list[h->addr_count] = (char*)buf; + h->addr_count++; + h->host.h_addr_list[h->addr_count] = NULL; + return 0; +} + +static void +_mdns_hostent_clear(mdns_hostent_t *h) +{ + if (h == NULL) return; + free(h->host.h_name); + h->host.h_name = NULL; + + char **aliases = h->host.h_aliases; + while (aliases && *aliases) { + free(*aliases++); + } + free(h->host.h_aliases); + h->host.h_aliases = NULL; + h->alias_count = 0; + + char **addrs = h->host.h_addr_list; + while (addrs && *addrs) { + free(*addrs++); + } + free(h->host.h_addr_list); + h->host.h_addr_list = NULL; + h->addr_count = 0; + +} + +static void +_mdns_reply_clear(mdns_reply_t *r) +{ + if (r == NULL) return; + r->ifnum = 0; + _mdns_hostent_clear(r->h4); + _mdns_hostent_clear(r->h6); + mdns_srv_t *srv = r->srv; + r->srv = NULL; + while (srv) { + mdns_srv_t *next = srv->next; + free(srv->srv.target); + free(srv); + srv = next; + } +} + +static si_item_t * +_mdns_hostbyname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + uint32_t type; + mdns_hostent_t h; + mdns_reply_t reply; + si_item_t *out = NULL; + uint64_t bb; + int status; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (name == NULL) { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + memset(&h, 0, sizeof(h)); + memset(&reply, 0, sizeof(reply)); + + switch (af) { + case AF_INET: + type = ns_t_a; + h.host.h_length = 4; + reply.h4 = &h; + break; + case AF_INET6: + type = ns_t_aaaa; + h.host.h_length = 16; + reply.h6 = &h; + break; + default: + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + h.host.h_addrtype = af; + + status = _mdns_search(name, ns_c_in, type, 0, 1, NULL, NULL, &reply); + if (status != 0 || h.addr_count == 0) { + _mdns_reply_clear(&reply); + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + bb = reply.ttl + time(NULL); + + switch (af) { + case AF_INET: + out = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, bb, 0LL, h.host.h_name, h.host.h_aliases, h.host.h_addrtype, h.host.h_length, h.host.h_addr_list); + break; + case AF_INET6: + out = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, bb, 0LL, h.host.h_name, h.host.h_aliases, h.host.h_addrtype, h.host.h_length, h.host.h_addr_list); + break; + } + + _mdns_reply_clear(&reply); + + if (out == NULL && err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + + return out; +} + +static si_item_t * +_mdns_hostbyaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + mdns_hostent_t h; + mdns_reply_t reply; + char *name; + si_item_t *out; + uint64_t bb; + int cat; + int status; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (addr == NULL || si == NULL) { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + memset(&h, 0, sizeof(h)); + memset(&reply, 0, sizeof(reply)); + + switch (af) { + case AF_INET: + h.host.h_length = 4; + reply.h4 = &h; + name = _mdns_reverse_ipv4(addr); + cat = CATEGORY_HOST_IPV4; + break; + case AF_INET6: + h.host.h_length = 16; + reply.h6 = &h; + name = _mdns_reverse_ipv6(addr); + cat = CATEGORY_HOST_IPV6; + break; + default: + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + h.host.h_addrtype = af; + + status = _mdns_search(name, ns_c_in, ns_t_ptr, 0, 1, NULL, NULL, &reply); + free(name); + if (status != 0) { + _mdns_reply_clear(&reply); + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + status = _mdns_hostent_append_addr(&h, addr, h.host.h_length); + if (status != 0) { + _mdns_hostent_clear(&h); + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + bb = reply.ttl + time(NULL); + out = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, cat, 1, bb, 0LL, h.host.h_name, h.host.h_aliases, h.host.h_addrtype, h.host.h_length, h.host.h_addr_list); + + _mdns_hostent_clear(&h); + + if (out == NULL && err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return out; +} + +// embedded does not do parallel A/AAAA +#if !TARGET_OS_EMBEDDED +static si_list_t * +_mdns_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, uint32_t *err) +{ + int wantv4 = 1; + int wantv6 = 1; + if (family == AF_INET6) wantv4 = 0; + else if (family == AF_INET) wantv6 = 0; + else if (family != AF_UNSPEC) return NULL; + + struct in_addr a4; + struct in6_addr a6; + mdns_hostent_t h4; + mdns_hostent_t h6; + mdns_reply_t reply; + uint32_t type; + uint16_t port; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + si_list_t *out = NULL; + + memset(&h4, 0, sizeof(h4)); + memset(&h6, 0, sizeof(h6)); + memset(&reply, 0, sizeof(reply)); + + h4.host.h_addrtype = AF_INET; + h4.host.h_length = 4; + h6.host.h_addrtype = AF_INET6; + h6.host.h_length = 16; + + if (wantv4 && wantv6) { + type = 0; + reply.h4 = &h4; + reply.h6 = &h6; + } else if (wantv4) { + reply.h4 = &h4; + type = ns_t_a; + } else if (wantv6) { + type = ns_t_aaaa; + reply.h6 = &h6; + } else { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + // service lookup + if ((flags & AI_NUMERICSERV) != 0) { + port = *(uint16_t *)serv; + } else { + if (_gai_serv_to_port(serv, proto, &port) != 0) { + if (err) *err = SI_STATUS_EAI_NONAME; + return NULL; + } + } + + // host lookup + if ((flags & AI_NUMERICHOST) != 0) { + char *cname = NULL; + struct in_addr *p4 = NULL; + struct in6_addr *p6 = NULL; + if (family == AF_INET) { + p4 = &a4; + memcpy(p4, node, sizeof(a4)); + } else if (family == AF_INET6) { + p6 = &a6; + memcpy(p6, node, sizeof(a6)); + } + out = si_addrinfo_list(si, socktype, proto, + p4, p6, port, 0, cname, cname); + } else { + int res; + res = _mdns_search(node, ns_c_in, type, 0, 1, NULL, NULL, &reply); + if (res == 0 && (h4.addr_count > 0 || h6.addr_count > 0)) { + out = si_addrinfo_list_from_hostent(si, socktype, proto, + port, 0, + (wantv4 ? &h4.host : NULL), + (wantv6 ? &h6.host : NULL)); + } else if (err != NULL) { + *err = SI_STATUS_EAI_NONAME; + } + _mdns_reply_clear(&reply); + } + return out; +} +#endif // !TARGET_OS_EMBEDDED + +static si_list_t * +_mdns_srv_byname(si_mod_t* si, const char *qname, uint32_t *err) +{ + si_list_t *out = NULL; + mdns_reply_t reply; + mdns_srv_t *srv; + int res; + const uint64_t unused = 0; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + memset(&reply, 0, sizeof(reply)); + res = _mdns_search(qname, ns_c_in, ns_t_srv, 0, 1, NULL, NULL, &reply); + if (res == 0) { + srv = reply.srv; + while (srv) { + si_item_t *item; + item = (si_item_t *)LI_ils_create("L4488222s", (unsigned long)si, CATEGORY_SRV, 1, unused, unused, srv->srv.priority, srv->srv.weight, srv->srv.port, srv->srv.target); + out = si_list_add(out, item); + si_item_release(item); + srv = srv->next; + } + } + _mdns_reply_clear(&reply); + return out; +} + +/* + * We support dns_async_start / cancel / handle_reply using dns_item_call + */ +static si_item_t * +_mdns_item_call(si_mod_t *si, int call, const char *name, const char *ignored, uint32_t class, uint32_t type, uint32_t *err) +{ + int res; + uint8_t buf[DNS_MAX_RECEIVE_SIZE]; + uint32_t len = sizeof(buf); + mdns_reply_t reply; + mdns_hostent_t h4; + mdns_hostent_t h6; + si_item_t *out; + int norecurse = 0; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + switch (call) { + case SI_CALL_DNS_QUERY: + norecurse = 1; + break; + case SI_CALL_DNS_SEARCH: + break; + default: + if (err) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + break; + } + + if (name == NULL) { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + memset(&h4, 0, sizeof(h4)); + memset(&h6, 0, sizeof(h6)); + memset(&reply, 0, sizeof(reply)); + + h4.host.h_addrtype = AF_INET; + h4.host.h_length = 4; + h6.host.h_addrtype = AF_INET6; + h6.host.h_length = 16; + reply.h4 = &h4; + reply.h6 = &h6; + + res = _mdns_search(name, class, type, norecurse, 1, buf, &len, &reply); + if (res != 0 || len <= 0 || len > DNS_MAX_RECEIVE_SIZE) { + _mdns_reply_clear(&reply); + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + struct sockaddr_in6 from; + uint32_t fromlen = sizeof(from); + memset(&from, 0, fromlen); + from.sin6_len = fromlen; + from.sin6_family = AF_INET6; + from.sin6_addr.__u6_addr.__u6_addr8[15] = 1; + if (reply.ifnum != 0) { + from.sin6_addr.__u6_addr.__u6_addr16[0] = htons(0xfe80); + from.sin6_scope_id = reply.ifnum; + } + + out = (si_item_t *)LI_ils_create("L4488@@", (unsigned long)si, CATEGORY_DNSPACKET, 1, 0LL, 0LL, len, buf, fromlen, &from); + if (out == NULL && err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + + _mdns_reply_clear(&reply); + + return out; +} + +static int +_mdns_is_valid(si_mod_t *si, si_item_t *item) +{ + return 0; +} + +static void +_mdns_close(si_mod_t *si) +{ + if (_dns_config_token != -1) notify_cancel(_dns_config_token); + //_mdns_dir_token; +} + +static void +_mdns_atfork_prepare(void) +{ + // acquire our lock so that we know all other threads have "drained" + pthread_mutex_lock(&_mdns_mutex); +} + +static void +_mdns_atfork_parent(void) +{ + // parent can simply resume + pthread_mutex_unlock(&_mdns_mutex); +} + +static void +_mdns_atfork_child(void) +{ + // child needs to force re-initialization + _mdns_old_sdref = _mdns_sdref; // for later deallocation + _mdns_sdref = NULL; + _dns_config_token = -1; + pthread_mutex_unlock(&_mdns_mutex); +} + +__private_extern__ si_mod_t * +si_module_static_mdns(void) +{ + si_mod_t *out = (si_mod_t *)calloc(1, sizeof(si_mod_t)); + char *outname = strdup("mdns"); + + if ((out == NULL) || (outname == NULL)) + { + free(out); + free(outname); + return NULL; + } + + out->name = outname; + out->vers = 1; + out->refcount = 1; + out->private = NULL; + + out->sim_close = _mdns_close; + out->sim_is_valid = _mdns_is_valid; + out->sim_host_byname = _mdns_hostbyname; + out->sim_host_byaddr = _mdns_hostbyaddr; + out->sim_item_call = _mdns_item_call; +#if !TARGET_OS_EMBEDDED + out->sim_addrinfo = _mdns_addrinfo; +#endif + out->sim_srv_byname = _mdns_srv_byname; + + int res; + + res = notify_register_check(dns_configuration_notify_key(), &_dns_config_token); + if (res != NOTIFY_STATUS_OK) _dns_config_token = -1; + + pthread_atfork(_mdns_atfork_prepare, _mdns_atfork_parent, _mdns_atfork_child); + + _mdns_debug = getenv("RES_DEBUG") != NULL; + + return out; +} + +/* + * _mdns_parse_domain_name + * Combine DNS labels to form a string. + * DNSService API does not return compressed names. + */ +static char * +_mdns_parse_domain_name(const uint8_t *data, uint32_t datalen) +{ + int i = 0, j = 0; + uint32_t len; + uint32_t domainlen = 0; + char *domain = NULL; + + // i: index into input data + // j: index into output string + while (datalen-- > 0) { + len = data[i++]; + domainlen += (len + 1); + domain = reallocf(domain, domainlen); + if (domain == NULL) return NULL; + if (len == 0) break; // DNS root (NUL) + if (j > 0) { + domain[j++] = datalen ? '.' : '\0'; + } + + while ((len-- > 0) && (datalen--)) { + if (data[i] == '.') { + // special case: escape the '.' with a '\' + domain = reallocf(domain, ++domainlen); + if (domain == NULL) return NULL; + domain[j++] = '\\'; + } + domain[j++] = data[i++]; + } + } + domain[j] = '\0'; + + return domain; +} + +/* + * _mdns_pack_domain_name + * Format the string as packed DNS labels. + * Only used for one string at a time, therefore no need for compression. + */ +static int +_mdns_pack_domain_name(const char* str, uint8_t *buf, size_t buflen) { + int i = 0; + while (i < buflen) { + uintptr_t len; + // calculate length to next '.' or '\0' + char *dot = strchr(str, '.'); + if (dot == NULL) dot = strchr(str, '\0'); + len = (dot - str); + if (len > NS_MAXLABEL) return -1; + // copy data for label + buf[i++] = len; + while (str < dot) { + buf[i++] = *str++; + } + // skip past '.', break if '\0' + if (*str++ == '\0') break; + } + if (i >= buflen) return -1; + buf[i] = '\0'; + return i; +} + +static int +_is_rev_link_local(const char *name) +{ + int len, i; + + if (name == NULL) return 0; + + len = strlen(name); + if (len == 0) return 0; + + /* check for trailing '.' */ + if (name[len - 1] == '.') len--; + + if (len != IPv6_REVERSE_LEN) return 0; + + i = IPv6_REVERSE_LINK_LOCAL_TRAILING_CHAR; + if ((name[i] != '8') && (name[i] != '9') && (name[i] != 'A') && (name[i] != 'a') && (name[i] != 'B') && (name[i] != 'b')) return 0; + + i = IPv6_REVERSE_LINK_LOCAL_TRAILING_CHAR + 1; + if (strncasecmp(name + i, ".e.f.ip6.arpa", 13)) return 0; + + for (i = 0; i < IPv6_REVERSE_LINK_LOCAL_TRAILING_CHAR; i += 2) + { + if (name[i] < '0') return 0; + if ((name[i] > '9') && (name[i] < 'A')) return 0; + if ((name[i] > 'F') && (name[i] < 'a')) return 0; + if (name[i] > 'f') return 0; + if (name[i + 1] != '.') return 0; + } + + return 1; +} + +/* _mdns_ipv6_extract_scope_id + * If the input string is a link local IPv6 address with an encoded scope id, + * the scope id is extracted to the "iface" parameter and a new string is + * returned with it removed. + */ +static char * +_mdns_ipv6_extract_scope_id(const char *name, uint32_t *outscope) +{ + char *qname = NULL; + uint16_t nibble; + int i; + + if (outscope) *outscope = 0; + + if (name && _is_rev_link_local(name)) { + uint32_t iface; + + /* _is_rev_link_local rejects chars > 127 so it's safe to index into hexval */ + i = IPv6_REVERSE_LINK_LOCAL_SCOPE_ID_LOW; + nibble = hexval[(uint32_t)name[i]]; + iface = nibble; + + i += 2; + nibble = hexval[(uint32_t)name[i]]; + iface += (nibble << 4); + + i += 2; + nibble = hexval[(uint32_t)name[i]]; + iface += (nibble << 8); + + i += 2; + nibble = hexval[(uint32_t)name[i]]; + iface += (nibble << 12); + + if (iface != 0) + { + qname = strdup(name); + if (qname == NULL) return NULL; + + i = IPv6_REVERSE_LINK_LOCAL_SCOPE_ID_LOW; + qname[i] = '0'; + qname[i + 2] = '0'; + qname[i + 4] = '0'; + qname[i + 6] = '0'; + + if (outscope) *outscope = iface; + } + } + return qname; +} + +static int +_mdns_make_query(const char* name, int class, int type, uint8_t *buf, uint32_t buflen) +{ + uint32_t len = 0; + + if (buf == NULL || buflen < (NS_HFIXEDSZ + NS_QFIXEDSZ)) return -1; + memset(buf, 0, NS_HFIXEDSZ); + HEADER *hp = (HEADER *)buf; + + len += NS_HFIXEDSZ; + hp->id = arc4random(); + hp->qr = 1; + hp->opcode = ns_o_query; + hp->rd = 1; + hp->rcode = ns_r_noerror; + hp->qdcount = htons(1); + + int n = _mdns_pack_domain_name(name, &buf[len], buflen - len); + if (n < 0) return -1; + + len += n; + uint16_t word; + word = htons(type); + memcpy(&buf[len], &word, sizeof(word)); + len += sizeof(word); + word = htons(class); + memcpy(&buf[len], &word, sizeof(word)); + len += sizeof(word); + return len; +} + +typedef struct { + mdns_reply_t *reply; + mdns_hostent_t *host; + uint8_t *answer; // DNS packet buffer + size_t anslen; // DNS packet buffer current length + size_t ansmaxlen; // DNS packet buffer maximum length + int type; // type of query: A, AAAA, PTR, SRV... + uint16_t last_type; // last type received + DNSServiceRef sd; + DNSServiceFlags flags; + DNSServiceErrorType error; + int kq; // kqueue to notify when callback received +} mdns_query_context_t; + +static void +_mdns_query_callback(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType, const char *, uint16_t, uint16_t, uint16_t, const void *, uint32_t, void *); + +/* _mdns_query_start + * initializes the context and starts a DNS-SD query. + */ +static DNSServiceErrorType +_mdns_query_start(mdns_query_context_t *ctx, mdns_reply_t *reply, uint8_t *answer, uint32_t *anslen, const char* name, int class, int type, int kq) +{ + DNSServiceErrorType status; + + int dns_flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsReturnIntermediates; + + memset(ctx, 0, sizeof(mdns_query_context_t)); + + if (answer && anslen) { + // build a dummy DNS header to return to the caller + ctx->answer = answer; + ctx->ansmaxlen = *anslen; + ctx->anslen = _mdns_make_query(name, class, type, answer, ctx->ansmaxlen); + if (ctx->anslen <= 0) return -1; + } + + ctx->type = type; + ctx->sd = _mdns_sdref; + ctx->kq = kq; + if (reply) { + ctx->reply = reply; + if (type == ns_t_a) ctx->host = reply->h4; + else if (type == ns_t_aaaa) ctx->host = reply->h6; + else if (type == ns_t_ptr && reply->h4) ctx->host = reply->h4; + else if (type == ns_t_ptr && reply->h6) ctx->host = reply->h6; + else if (type != ns_t_srv && type != ns_t_cname) abort(); + } + + uint32_t iface = 0; + char *qname = _mdns_ipv6_extract_scope_id(name, &iface); + if (qname == NULL) qname = (char *)name; + if (_mdns_debug) printf(";; mdns query %s %d %d\n", qname, type, class); + status = DNSServiceQueryRecord(&ctx->sd, dns_flags, iface, qname, type, class, _mdns_query_callback, ctx); + if (iface != 0) free(qname); + return status; +} + +/* _mdns_query_is_complete + * Determines whether the specified query has sufficient information to be + * considered complete. + */ +static int +_mdns_query_is_complete(mdns_query_context_t *ctx) +{ + if (ctx == NULL) return 1; + //if (ctx->flags & kDNSServiceFlagsMoreComing) return 0; + if (ctx->last_type != ctx->type) return 0; + switch (ctx->type) { + case ns_t_a: + case ns_t_aaaa: + if (ctx->host != NULL && ctx->host->addr_count > 0) { + return 1; + } + break; + case ns_t_ptr: + if (ctx->host != NULL && ctx->host->host.h_name != NULL) { + return 1; + } + break; + case ns_t_srv: + if (ctx->reply != NULL && ctx->reply->srv != NULL) { + return 1; + } + break; + default: + abort(); + } + return 0; +} + +/* _mdns_query_clear + * Clear out the temporary fields of the context, and clear any result + * structures that are incomplete. Retrns 1 if the query was complete. + */ +static int +_mdns_query_clear(mdns_query_context_t *ctx) +{ + int complete = _mdns_query_is_complete(ctx); + if (ctx == NULL) return complete; + + if (ctx->sd != NULL) { + DNSServiceRefDeallocate(ctx->sd); + ctx->sd = NULL; + } + ctx->flags = 0; + ctx->kq = -1; + + if (!complete) { + _mdns_hostent_clear(ctx->host); + ctx->anslen = -1; + } + return complete; +} + +static void +_mdns_query_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t ifIndex, DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *ctx) +{ + mdns_query_context_t *context; + struct in6_addr a6; + + context = (mdns_query_context_t *)ctx; + + context->flags = flags; + context->error = errorCode; + context->last_type = rrtype; + + if (errorCode != kDNSServiceErr_NoError) { + if (_mdns_debug) printf(";; [%s %hu %hu]: error %d\n", fullname, rrtype, rrclass, errorCode); + goto wakeup_kevent; + } + + // embed the scope ID into link-local IPv6 addresses + if (rrtype == ns_t_aaaa && rdlen == sizeof(struct in6_addr) && + IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)rdata)) { + memcpy(&a6, rdata, rdlen); + a6.__u6_addr.__u6_addr16[1] = htons(ifIndex); + rdata = &a6; + } + + if (context->reply) { + char *name; + int malformed = 0; + mdns_reply_t *reply = context->reply; + + if (reply->ifnum == 0) { + reply->ifnum = ifIndex; + } + + _mdns_hostent_append_alias(context->host, fullname); + if (reply->ttl == 0 || ttl < reply->ttl) reply->ttl = ttl; + + switch (rrtype) { + case ns_t_a: + case ns_t_aaaa: + if (((rrtype == ns_t_a && context->host->host.h_addrtype == AF_INET) || + (rrtype == ns_t_aaaa && context->host->host.h_addrtype == AF_INET6)) && + rdlen >= context->host->host.h_length) { + if (context->host->host.h_name == NULL) { + int i; + mdns_hostent_t *h = context->host; + char *h_name = _mdns_canonicalize(fullname); + context->host->host.h_name = h_name; + + // 6863416 remove h_name from h_aliases + for (i = 0; i < h->alias_count; ++i) { + if (h_name == NULL) break; + if (string_equal(h->host.h_aliases[i], h_name)) { + // includes trailing NULL pointer + int sz = sizeof(char *) * (h->alias_count - i); + free(h->host.h_aliases[i]); + memmove(&h->host.h_aliases[i], &h->host.h_aliases[i+1], sz); + h->alias_count -= 1; + break; + } + } + } + _mdns_hostent_append_addr(context->host, rdata, context->host->host.h_length); + } else { + malformed = 1; + } + break; + case ns_t_cname: + name = _mdns_parse_domain_name(rdata, rdlen); + if (!name) malformed = 1; + _mdns_hostent_append_alias(context->host, name); + free(name); + break; + case ns_t_ptr: + name = _mdns_parse_domain_name(rdata, rdlen); + if (!name) malformed = 1; + if (context->host && context->host->host.h_name == NULL) { + context->host->host.h_name = _mdns_canonicalize(name); + } + _mdns_hostent_append_alias(context->host, name); + free(name); + break; + case ns_t_srv: { + mdns_rr_srv_t *p = (mdns_rr_srv_t*)rdata; + mdns_srv_t *srv = calloc(1, sizeof(mdns_srv_t)); + if (srv == NULL) break; + if (rdlen < sizeof(mdns_rr_srv_t)) { + malformed = 1; + break; + } + srv->srv.priority = ntohs(p->priority); + srv->srv.weight = ntohs(p->weight); + srv->srv.port = ntohs(p->port); + srv->srv.target = _mdns_parse_domain_name(&p->target[0], rdlen - 3*sizeof(uint16_t)); + if (srv->srv.target == NULL) { + malformed = 1; + break; + } + // append to the end of the list + if (reply->srv == NULL) { + reply->srv = srv; + } else { + mdns_srv_t *iter = reply->srv; + while (iter->next) iter = iter->next; + iter->next = srv; + } + break; + } + default: + malformed = _mdns_debug; + break; + } + if (malformed && _mdns_debug) { + printf(";; [%s %hu %hu]: malformed reply\n", fullname, rrtype, rrclass); + goto wakeup_kevent; + } + } + + if (context->answer) { + int n; + uint8_t *cp; + HEADER *ans; + size_t buflen = context->ansmaxlen - context->anslen; + if (buflen < NS_HFIXEDSZ) + { + if (_mdns_debug) printf(";; [%s %hu %hu]: malformed reply\n", fullname, rrtype, rrclass); + goto wakeup_kevent; + } + + cp = context->answer + context->anslen; + + n = _mdns_pack_domain_name(fullname, cp, buflen); + if (n < 0) { + if (_mdns_debug) printf(";; [%s %hu %hu]: name mismatch\n", fullname, rrtype, rrclass); + goto wakeup_kevent; + } + + // check that there is enough space in the buffer for the + // resource name (n), the resource record data (rdlen) and + // the resource record header (10). + if (buflen < n + rdlen + 10) { + if (_mdns_debug) printf(";; [%s %hu %hu]: insufficient buffer space for reply\n", fullname, rrtype, rrclass); + goto wakeup_kevent; + } + + cp += n; + buflen -= n; + + uint16_t word; + uint32_t longword; + + word = htons(rrtype); + memcpy(cp, &word, sizeof(word)); + cp += sizeof(word); + + word = htons(rrclass); + memcpy(cp, &word, sizeof(word)); + cp += sizeof(word); + + longword = htonl(ttl); + memcpy(cp, &longword, sizeof(longword)); + cp += sizeof(longword); + + word = htons(rdlen); + memcpy(cp, &word, sizeof(word)); + cp += sizeof(word); + + memcpy(cp, rdata, rdlen); + cp += rdlen; + + ans = (HEADER *)context->answer; + ans->ancount = htons(ntohs(ans->ancount) + 1); + + context->anslen = (size_t)(cp - context->answer); + } + + if (_mdns_debug) printf(";; [%s %hu %hu]\n", fullname, rrtype, rrclass); + +wakeup_kevent: + // Ping the waiting thread in case this callback was invoked on another + if (context->kq != -1) { + struct kevent ev; + EV_SET(&ev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0); + int res = kevent(context->kq, &ev, 1, NULL, 0, NULL); + if (res && _mdns_debug) printf(";; kevent EV_TRIGGER: %s\n", strerror(errno)); + } +} + +static void +_mdns_now(struct timespec *now) { + struct timeval tv; + gettimeofday(&tv, NULL); + now->tv_sec = tv.tv_sec; + now->tv_nsec = tv.tv_usec * 1000; +} + +static void +_mdns_add_time(struct timespec *sum, const struct timespec *a, const struct timespec *b) +{ + sum->tv_sec = a->tv_sec + b->tv_sec; + sum->tv_nsec = a->tv_nsec + b->tv_nsec; + if (sum->tv_nsec > 1000000000) { + sum->tv_sec += (sum->tv_nsec / 1000000000); + sum->tv_nsec %= 1000000000; + } +} + +// calculate a deadline from the current time based on the desired timeout +static void +_mdns_deadline(struct timespec *deadline, const struct timespec *delta) +{ + struct timespec now; + _mdns_now(&now); + _mdns_add_time(deadline, &now, delta); +} + +static void +_mdns_sub_time(struct timespec *delta, const struct timespec *a, const struct timespec *b) +{ + delta->tv_sec = a->tv_sec - b->tv_sec; + delta->tv_nsec = a->tv_nsec - b->tv_nsec; + if (delta->tv_nsec < 0) { + delta->tv_nsec += 1000000000; + delta->tv_sec -= 1; + } +} + +// calculate a timeout remaining before the given deadline +static void +_mdns_timeout(struct timespec *timeout, const struct timespec *deadline) +{ + struct timespec now; + _mdns_now(&now); + _mdns_sub_time(timeout, deadline, &now); +} + +int +_mdns_query_mDNSResponder(const char *name, int class, int type, uint8_t *answer, uint32_t *anslen, mdns_reply_t *reply, uint32_t timeout_sec) +{ + DNSServiceErrorType err = 0; + int kq, n, wait = 1; + struct kevent ev; + struct timespec start, finish, delta, timeout; + int res = 0; + int i, complete, got_response = 0; + int initialize = 1; + + // 2 for A and AAAA parallel queries + int n_ctx = 0; + mdns_query_context_t ctx[2]; + + if (name == NULL) return -1; + +#if TARGET_OS_EMBEDDED + // log a warning for queries from the main thread + if (pthread_main_np()) asl_log(NULL, NULL, ASL_LEVEL_WARNING, "Warning: Libinfo call to mDNSResponder on main thread"); +#endif // #if TARGET_OS_EMBEDDED + + // Timeout Logic + // The kevent(2) API timeout parameter is used to enforce the total + // timeout of the DNS query. Each iteraion recalculates the relative + // timeout based on the desired end time (total timeout from origin). + // + // In order to workaround some DNS configurations that do not return + // responses for AAAA queries, parallel queries modify the total + // timeout upon receipt of the first response. The new total timeout is + // set to an effective value of 2N where N is the time taken to receive + // the A response (the original total timeout is preserved if 2N would + // have exceeded it). However, since mDNSResponder caches values, a + // minimum value of 50ms for N is enforced in order to give some time + // for the receipt of a AAAA response. + + // determine the maximum time to wait for a result + if (timeout_sec == 0) timeout_sec = RES_MAXRETRANS; + delta.tv_sec = timeout_sec; + delta.tv_nsec = 0; + _mdns_deadline(&finish, &delta); + timeout = delta; + _mdns_now(&start); + + // set up the kqueue + kq = kqueue(); + EV_SET(&ev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, 0); + n = kevent(kq, &ev, 1, NULL, 0, NULL); + if (n != 0) wait = 0; + + while (wait == 1) { + if (initialize) { + initialize = 0; + pthread_mutex_lock(&_mdns_mutex); + // clear any stale contexts + for (i = 0; i < n_ctx; ++i) { + _mdns_query_clear(&ctx[i]); + } + n_ctx = 0; + + if (_mdns_sdref == NULL) { + if (_mdns_old_sdref != NULL) { + DNSServiceRefDeallocate(_mdns_old_sdref); + _mdns_old_sdref = NULL; + } + // (re)initialize the shared connection + err = DNSServiceCreateConnection(&_mdns_sdref); + if (err != 0) { + wait = 0; + pthread_mutex_unlock(&_mdns_mutex); + break; + } + } + + // issue (or reissue) the queries + // unspecified type: do parallel A and AAAA + if (err == 0) { + err = _mdns_query_start(&ctx[n_ctx++], reply, + answer, anslen, + name, class, + (type == 0) ? ns_t_a : type, kq); + } + if (err == 0 && type == 0) { + err = _mdns_query_start(&ctx[n_ctx++], reply, + answer, anslen, + name, class, ns_t_aaaa, kq); + } + if (err && _mdns_debug) printf(";; initialization error %d\n", err); + // try to reinitialize + if (err == kDNSServiceErr_Unknown || + err == kDNSServiceErr_ServiceNotRunning || + err == kDNSServiceErr_BadReference) { + if (_mdns_sdref) { + DNSServiceRefDeallocate(_mdns_sdref); + _mdns_sdref = NULL; + } + err = 0; + initialize = 1; + pthread_mutex_unlock(&_mdns_mutex); + continue; + } else if (err != 0) { + pthread_mutex_unlock(&_mdns_mutex); + break; + } + + // (re)register the fd with kqueue + int fd = DNSServiceRefSockFD(_mdns_sdref); + EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0); + n = kevent(kq, &ev, 1, NULL, 0, NULL); + pthread_mutex_unlock(&_mdns_mutex); + if (err != 0 || n != 0) break; + } + + if (_mdns_debug) printf(";; kevent timeout %ld.%ld\n", timeout.tv_sec, timeout.tv_nsec); + n = kevent(kq, NULL, 0, &ev, 1, &timeout); + if (n < 0 && errno != EINTR) { + res = -1; + break; + } + + pthread_mutex_lock(&_mdns_mutex); + // DNSServiceProcessResult() is a blocking API + // confirm that there is still data on the socket + const struct timespec notimeout = { 0, 0 }; + int m = kevent(kq, NULL, 0, &ev, 1, ¬imeout); + if (_mdns_sdref == NULL) { + initialize = 1; + } else if (m > 0 && ev.filter == EVFILT_READ) { + err = DNSServiceProcessResult(_mdns_sdref); + if (err == kDNSServiceErr_ServiceNotRunning || + err == kDNSServiceErr_BadReference) { + if (_mdns_debug) printf(";; DNSServiceProcessResult status %d\n", err); + err = 0; + // re-initialize the shared connection + DNSServiceRefDeallocate(_mdns_sdref); + _mdns_sdref = NULL; + initialize = 1; + } + } + + // Check if all queries are complete (including errors) + complete = 1; + for (i = 0; i < n_ctx; ++i) { + if (_mdns_query_is_complete(&ctx[i]) || ctx[i].error) { + if (ctx[i].type == ns_t_a) { + got_response = 1; + } + } else { + complete = 0; + } + } + pthread_mutex_unlock(&_mdns_mutex); + + if (err != 0) { + if (_mdns_debug) printf(";; DNSServiceProcessResult status %d\n", err); + break; + } else if (complete == 1) { + if (_mdns_debug) printf(";; done\n"); + break; + } else if (got_response == 1) { + // got A, adjust deadline for AAAA + struct timespec now; + _mdns_now(&now); + _mdns_sub_time(&delta, &now, &start); // delta = N + // minimum N of 50ms + if (delta.tv_sec == 0 && delta.tv_nsec < 50000000) { + delta.tv_nsec = 50000000; + } + + // only move deadline if timeout > 2N + _mdns_sub_time(&now, &timeout, &delta); + if (now.tv_sec >= 0) { + if (_mdns_debug) printf(";; new timeout %ld.%ld\n", delta.tv_sec, delta.tv_nsec); + _mdns_deadline(&finish, &delta); + } + } + + // calculate remaining timeout + _mdns_timeout(&timeout, &finish); + // no time remaining + if (timeout.tv_sec < 0) { + if (_mdns_debug) printf(";; timeout\n"); + break; + } + } + + complete = 0; + pthread_mutex_lock(&_mdns_mutex); + for (i = 0; i < n_ctx; ++i) { + if (err == 0) err = ctx[i].error; + // Only clears hostents if result is incomplete. + complete = _mdns_query_clear(&ctx[i]) || complete; + } + pthread_mutex_unlock(&_mdns_mutex); + // Everything should be done with the kq by now. + close(kq); + + // Return error if everything is incomplete + if (complete == 0) { + res = -1; + } + + if (anslen) *anslen = ctx[0].anslen; + return res; +} + diff --git a/lookup.subproj/netdb.h b/lookup.subproj/netdb.h index 95e485d..552c8aa 100644 --- a/lookup.subproj/netdb.h +++ b/lookup.subproj/netdb.h @@ -35,12 +35,12 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -52,16 +52,17 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * + * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT @@ -95,7 +96,9 @@ typedef __darwin_size_t size_t; typedef __darwin_socklen_t socklen_t; #endif -#define _PATH_HEQUIV "/etc/hosts.equiv" +#ifndef _PATH_HEQUIV +# define _PATH_HEQUIV "/etc/hosts.equiv" +#endif #define _PATH_HOSTS "/etc/hosts" #define _PATH_NETWORKS "/etc/networks" #define _PATH_PROTOCOLS "/etc/protocols" @@ -112,14 +115,14 @@ extern int h_errno; * supplied in host order, and returned in network order (suitable for * use in system calls). */ -struct hostent { +struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define h_addr h_addr_list[0] /* address, for backward compatiblity */ +#define h_addr h_addr_list[0] /* address, for backward compatibility */ #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ }; @@ -127,21 +130,21 @@ struct hostent { * Assumption here is that a network number * fits in an unsigned long -- probably a poor one. */ -struct netent { +struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ uint32_t n_net; /* network # */ }; -struct servent { +struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; -struct protoent { +struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ @@ -152,10 +155,10 @@ struct addrinfo { int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - socklen_t ai_addrlen; /* length of ai_addr */ + socklen_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ }; #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) @@ -168,7 +171,7 @@ struct rpcent { /* * Error return codes from gethostbyname() and gethostbyaddr() - * (left in extern int h_errno). + * (left in h_errno). */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) #define NETDB_INTERNAL -1 /* see errno */ @@ -200,11 +203,12 @@ struct rpcent { #define EAI_SOCKTYPE 10 /* ai_socktype not supported */ #define EAI_SYSTEM 11 /* system error returned in errno */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define EAI_BADHINTS 12 -#define EAI_PROTOCOL 13 -#define EAI_MAX 14 -#else /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ -#define EAI_OVERFLOW 14 /* An argument buffer overflowed */ +#define EAI_BADHINTS 12 /* invalid value for hints */ +#define EAI_PROTOCOL 13 /* resolved protocol is unknown */ +#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ +#define EAI_OVERFLOW 14 /* argument buffer overflow */ +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) +#define EAI_MAX 15 #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ /* @@ -212,10 +216,14 @@ struct rpcent { */ #define AI_PASSIVE 0x00000001 /* get address to use bind() */ #define AI_CANONNAME 0x00000002 /* fill ai_canonname */ -#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */ -/* valid flags for addrinfo */ +#define AI_NUMERICHOST 0x00000004 /* prevent host name resolution */ +#define AI_NUMERICSERV 0x00001000 /* prevent service name resolution */ +/* valid flags for addrinfo (not a standard def, apps should not use it) */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) +#define AI_MASK \ + (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \ + AI_ADDRCONFIG) + #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) @@ -249,7 +257,7 @@ struct rpcent { /* * Scope delimit character */ -#define SCOPE_DELIMITER '%' +#define SCOPE_DELIMITER '%' #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ __BEGIN_DECLS diff --git a/lookup.subproj/netdb_async.h b/lookup.subproj/netdb_async.h index 3f6b347..46453ec 100644 --- a/lookup.subproj/netdb_async.h +++ b/lookup.subproj/netdb_async.h @@ -36,6 +36,7 @@ /* SPI for parallel / fast getaddrinfo */ #define AI_PARALLEL 0x00000008 +#define AI_SRV 0x01000000 __BEGIN_DECLS diff --git a/lookup.subproj/search_module.c b/lookup.subproj/search_module.c new file mode 100644 index 0000000..adc18c3 --- /dev/null +++ b/lookup.subproj/search_module.c @@ -0,0 +1,1185 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "si_module.h" + +#define _PATH_SI_CONF "/etc/sysinfo.conf" + +#define SEARCH_FLAG_MAC 0x00000001 +#define SEARCH_FLAG_APPLETV 0x00000002 +#define SEARCH_FLAG_IPHONE 0x00000004 +#define SEARCH_FLAG_CACHE_ENABLED 0x00010000 + +typedef struct +{ + si_mod_t **module; + uint32_t count; + uint32_t flags; +} search_list_t; + +typedef struct +{ + uint32_t flags; + search_list_t search_list[CATEGORY_COUNT]; + si_mod_t *cache; + si_mod_t *dns; + si_mod_t *mdns; + si_mod_t *file; + si_mod_t *ds; +} search_si_private_t; + +__private_extern__ void si_cache_add_item(si_mod_t *si, si_mod_t *src, si_item_t *item); +__private_extern__ void si_cache_add_list(si_mod_t *si, si_mod_t *src, si_list_t *list); + +__private_extern__ char **_fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens); +__private_extern__ char *_fsi_get_line(FILE *fp); + +#ifdef DS_AVAILABLE +extern int _ds_running(); +#else +static inline int _ds_running(void) { return 0; } +#endif + +static __attribute__((noinline)) si_mod_t * +search_get_module(search_si_private_t *pp, int cat, int *n) +{ + int x; + + if ((pp == NULL) || (n == NULL)) return NULL; + + x = *n; + *n = x + 1; + + /* Use custom search list if available */ + if (x < pp->search_list[cat].count) + { + return pp->search_list[cat].module[x]; + } + + /* + * Search order: + * 1) cache + * 2) DS if available, otherwise flat files + * 3) mdns (for host lookups only) + */ + switch (x) + { + case 0: return pp->cache; + case 1: if (_ds_running()) return pp->ds; + else return pp->file; + case 2: return pp->mdns; + default: return NULL; + } +} + +static si_mod_t * +search_cat_cache(search_si_private_t *pp, int cat) +{ + if (pp == NULL) return NULL; + if ((cat < 0) || (cat > CATEGORY_COUNT)) return NULL; + + if (pp->search_list[cat].count > 0) + { + if (pp->search_list[cat].flags & SEARCH_FLAG_CACHE_ENABLED) return pp->cache; + return NULL; + } + + if ((pp->flags & SEARCH_FLAG_MAC) || (pp->flags & SEARCH_FLAG_APPLETV) || (pp->flags & SEARCH_FLAG_IPHONE)) return pp->cache; + return NULL; +} + +static void +search_close(si_mod_t *si) +{ + int i; + search_si_private_t *pp; + + if (si == NULL) return; + if (si->private == NULL) return; + + pp = (search_si_private_t *)si->private; + + si_module_release(pp->cache); + si_module_release(pp->file); + si_module_release(pp->dns); + si_module_release(pp->mdns); + si_module_release(pp->ds); + + for (i = 0; i < CATEGORY_COUNT; i++) + { + if (pp->search_list[i].module != NULL) + { + free(pp->search_list[i].module); + pp->search_list[i].module = NULL; + pp->search_list[i].count = 0; + pp->search_list[i].flags = 0; + } + } + + free(pp); +} + +static si_item_t * +search_item_byname(si_mod_t *si, const char *name, int cat, si_item_t *(*call)(si_mod_t *, const char *)) +{ + int i; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (si == NULL) return NULL; + if (call == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = call(src, name); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + return NULL; +} + +static si_item_t * +search_item_bynumber(si_mod_t *si, uint32_t number, int cat, si_item_t *(*call)(si_mod_t *, uint32_t)) +{ + int i; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (si == NULL) return NULL; + if (call == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = call(src, number); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + return NULL; +} + +static si_list_t * +search_list(si_mod_t *si, int cat, si_list_t *(*call)(si_mod_t *)) +{ + int i; + search_si_private_t *pp; + si_list_t *list, *all; + si_mod_t *cache, *src; + + if (si == NULL) return NULL; + if (call == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cache = search_cat_cache(pp, cat); + if (cache != NULL) + { + list = call(cache); + if (list != NULL) return list; + } + + i = 0; + + all = NULL; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + if (src == pp->cache) continue; + + list = call(src); + if (list == NULL) continue; + + all = si_list_concat(all, list); + si_list_release(list); + } + + si_cache_add_list(cache, si, all); + return all; +} + +__private_extern__ si_item_t * +search_user_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_USER, si_user_byname); +} + +__private_extern__ si_item_t * +search_user_byuid(si_mod_t *si, uid_t uid) +{ + return search_item_bynumber(si, (uint32_t)uid, CATEGORY_USER, si_user_byuid); +} + +__private_extern__ si_list_t * +search_user_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_USER, si_user_all); +} + +__private_extern__ si_item_t * +search_group_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_GROUP, si_group_byname); +} + +__private_extern__ si_item_t * +search_group_bygid(si_mod_t *si, gid_t gid) +{ + return search_item_bynumber(si, (uint32_t)gid, CATEGORY_USER, si_group_bygid); +} + +__private_extern__ si_list_t * +search_group_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_GROUP, si_group_all); +} + +__private_extern__ si_item_t * +search_groupist(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_GROUPLIST, si_grouplist); +} + +__private_extern__ si_list_t * +search_netgroup_byname(si_mod_t *si, const char *name) +{ + int i, cat; + search_si_private_t *pp; + si_list_t *list, *all; + si_mod_t *cache, *src; + + if (si == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_NETGROUP; + + cache = search_cat_cache(pp, cat); + if (cache != NULL) + { + list = si_netgroup_byname(cache, name); + if (list != NULL) return list; + } + + i = 0; + + all = NULL; + while (NULL != (src = search_get_module(pp, cat, &i))) + { + if (src == pp->cache) continue; + + list = si_netgroup_byname(src, name); + if (list == NULL) continue; + + all = si_list_concat(all, list); + si_list_release(list); + } + + si_cache_add_list(cache, si, all); + return all; +} + +__private_extern__ int +search_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain) +{ + int i, cat, innetgr; + search_si_private_t *pp; + si_mod_t *src; + + if (si == NULL) return 0; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return 0; + + cat = CATEGORY_NETGROUP; + i = 0; + innetgr = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + innetgr = si_in_netgroup(src, group, host, user, domain); + if (innetgr != 0) return 1; + } + + return 0; +} + +__private_extern__ si_item_t * +search_alias_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_ALIAS, si_alias_byname); +} + +__private_extern__ si_list_t * +search_alias_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_ALIAS, si_alias_all); +} + +__private_extern__ si_item_t * +search_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + int i, cat; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if ((si == NULL) || (name == NULL)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + pp = (search_si_private_t *)si->private; + if (pp == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + cat = CATEGORY_HOST_IPV4; + if (af == AF_INET6) cat = CATEGORY_HOST_IPV6; + + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = si_host_byname(src, name, af, err); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; +} + +__private_extern__ si_item_t * +search_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + int i, cat; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if ((si == NULL) || (addr == NULL)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + pp = (search_si_private_t *)si->private; + if (pp == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + cat = CATEGORY_HOST_IPV4; + if (af == AF_INET6) cat = CATEGORY_HOST_IPV6; + + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = si_host_byaddr(src, addr, af, err); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; +} + +__private_extern__ si_list_t * +search_host_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_HOST, si_host_all); +} + +__private_extern__ si_item_t * +search_network_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_NETWORK, si_network_byname); +} + +__private_extern__ si_item_t * +search_network_byaddr(si_mod_t *si, uint32_t addr) +{ + return search_item_bynumber(si, addr, CATEGORY_NETWORK, si_network_byaddr); +} + +__private_extern__ si_list_t * +search_network_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_NETWORK, si_network_all); +} + +__private_extern__ si_item_t * +search_service_byname(si_mod_t *si, const char *name, const char *proto) +{ + int i, cat; + si_item_t *item; + search_si_private_t *pp; + si_mod_t *src; + + if (si == NULL) return NULL; + if (name == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_SERVICE; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = si_service_byname(src, name, proto); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + return NULL; +} + +__private_extern__ si_item_t * +search_service_byport(si_mod_t *si, int port, const char *proto) +{ + int i, cat; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (si == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_SERVICE; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = si_service_byport(src, port, proto); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + return NULL; +} + +__private_extern__ si_list_t * +search_service_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_SERVICE, si_service_all); +} + +__private_extern__ si_item_t * +search_protocol_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_PROTOCOL, si_protocol_byname); +} + +__private_extern__ si_item_t * +search_protocol_bynumber(si_mod_t *si, int number) +{ + return search_item_bynumber(si, (uint32_t)number, CATEGORY_PROTOCOL, si_protocol_bynumber); +} + +__private_extern__ si_list_t * +search_protocol_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_PROTOCOL, si_protocol_all); +} + +__private_extern__ si_item_t * +search_rpc_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_RPC, si_rpc_byname); +} + +__private_extern__ si_item_t * +search_rpc_bynumber(si_mod_t *si, int number) +{ + int i, cat; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (si == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_RPC; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = si_rpc_bynumber(src, number); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + return item; + } + } + + return NULL; +} + +__private_extern__ si_list_t * +search_rpc_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_RPC, si_rpc_all); +} + +__private_extern__ si_item_t * +search_fs_byspec(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_FS, si_fs_byspec); +} + +__private_extern__ si_item_t * +search_fs_byfile(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_FS, si_fs_byfile); +} + +__private_extern__ si_list_t * +search_fs_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_FS, si_fs_all); +} + +__private_extern__ si_item_t * +search_mac_byname(si_mod_t *si, const char *name) +{ + return search_item_byname(si, name, CATEGORY_MAC, si_mac_byname); +} + +__private_extern__ si_item_t * +search_mac_bymac(si_mod_t *si, const char *mac) +{ + return search_item_byname(si, mac, CATEGORY_MAC, si_mac_bymac); +} + +__private_extern__ si_list_t * +search_mac_all(si_mod_t *si) +{ + return search_list(si, CATEGORY_MAC, si_mac_all); +} + +__private_extern__ si_list_t * +search_srv_byname(si_mod_t *si, const char* qname, uint32_t *err) +{ + int i, cat; + si_list_t *list = NULL; + si_mod_t *src; + search_si_private_t *pp; + + if (si == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_SRV; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + if (src == pp->cache) continue; + + if (src->sim_srv_byname != NULL) + { + list = src->sim_srv_byname(src, qname, err); + if (list != NULL) return list; + } + } + + if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME; + return NULL; +} + +__private_extern__ int +search_wants_addrinfo(si_mod_t *si) +{ + int i, cat; + si_mod_t *src; + search_si_private_t *pp; + + if (si == NULL) return 0; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return 0; + + cat = CATEGORY_ADDRINFO; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + if (src == pp->cache) continue; + if (src->sim_addrinfo != NULL) return 1; + } + + return 0; +} + +__private_extern__ si_list_t * +search_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, uint32_t socktype, uint32_t protocol, uint32_t flags, uint32_t *err) +{ + int i, cat; + search_si_private_t *pp; + si_list_t *list = NULL; + si_mod_t *src; + + if (err != NULL) *err = SI_STATUS_EAI_FAIL; + + if (si == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_ADDRINFO; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + if (src == pp->cache) continue; + + if (src->sim_addrinfo != NULL) + { + list = src->sim_addrinfo(src, node, serv, family, socktype, protocol, flags, err); + if (list != NULL) return list; + } + } + + if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME; + return NULL; +} + +__private_extern__ si_item_t * +search_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, uint32_t *err) +{ + int i, cat; + search_si_private_t *pp; + si_item_t *item; + si_mod_t *src; + + if (err != NULL) *err = SI_STATUS_EAI_FAIL; + + if (si == NULL) return NULL; + + pp = (search_si_private_t *)si->private; + if (pp == NULL) return NULL; + + cat = CATEGORY_NAMEINFO; + i = 0; + + while (NULL != (src = search_get_module(pp, cat, &i))) + { + item = si_nameinfo(src, sa, flags, err); + if (item != NULL) + { + si_cache_add_item(search_cat_cache(pp, cat), src, item); + if (err != NULL) *err = SI_STATUS_NO_ERROR; + return item; + } + } + + if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME; + return NULL; +} + +__private_extern__ int +search_is_valid(si_mod_t *si, si_item_t *item) +{ + si_mod_t *src; + + if (si == NULL) return 0; + if (item == NULL) return 0; + if (si->name == NULL) return 0; + if (item->src == NULL) return 0; + + src = (si_mod_t *)item->src; + + if (src->name == NULL) return 0; + if (string_not_equal(si->name, src->name)) return 0; + return 0; +} + +static si_mod_t * +search_alloc() +{ + si_mod_t *out; + char *outname; + search_si_private_t *pp; + + out = (si_mod_t *)calloc(1, sizeof(si_mod_t)); + outname = strdup("search"); + pp = (search_si_private_t *)calloc(1, sizeof(search_si_private_t)); + + if ((out == NULL) || (outname == NULL) || (pp == NULL)) + { + if (out != NULL) free(out); + if (outname != NULL) free(outname); + if (pp != NULL) free(pp); + + errno = ENOMEM; + return NULL; + } + + out->name = outname; + out->vers = 1; + out->refcount = 1; + out->private = pp; + + out->sim_close = search_close; + + out->sim_is_valid = search_is_valid; + + out->sim_user_byname = search_user_byname; + out->sim_user_byuid = search_user_byuid; + out->sim_user_all = search_user_all; + + out->sim_group_byname = search_group_byname; + out->sim_group_bygid = search_group_bygid; + out->sim_group_all = search_group_all; + + out->sim_grouplist = search_groupist; + + out->sim_netgroup_byname = search_netgroup_byname; + out->sim_in_netgroup = search_in_netgroup; + + out->sim_alias_byname = search_alias_byname; + out->sim_alias_all = search_alias_all; + + out->sim_host_byname = search_host_byname; + out->sim_host_byaddr = search_host_byaddr; + out->sim_host_all = search_host_all; + + out->sim_network_byname = search_network_byname; + out->sim_network_byaddr = search_network_byaddr; + out->sim_network_all = search_network_all; + + out->sim_service_byname = search_service_byname; + out->sim_service_byport = search_service_byport; + out->sim_service_all = search_service_all; + + out->sim_protocol_byname = search_protocol_byname; + out->sim_protocol_bynumber = search_protocol_bynumber; + out->sim_protocol_all = search_protocol_all; + + out->sim_rpc_byname = search_rpc_byname; + out->sim_rpc_bynumber = search_rpc_bynumber; + out->sim_rpc_all = search_rpc_all; + + out->sim_fs_byspec = search_fs_byspec; + out->sim_fs_byfile = search_fs_byfile; + out->sim_fs_all = search_fs_all; + + out->sim_mac_byname = search_mac_byname; + out->sim_mac_bymac = search_mac_bymac; + out->sim_mac_all = search_mac_all; + + out->sim_addrinfo = search_addrinfo; + out->sim_wants_addrinfo = search_wants_addrinfo; + out->sim_nameinfo = search_nameinfo; + + out->sim_srv_byname = search_srv_byname; + + return out; +} + +static void +init_optional_modules(search_si_private_t *pp) +{ + if (pp->mdns == NULL) + { + pp->mdns = si_module_with_name("mdns"); + /* allow this to fail */ + } + +#ifdef DS_AVAILABLE + if (pp->flags & SEARCH_FLAG_MAC) + { + if (pp->ds == NULL) + { + pp->ds = si_module_with_name("ds"); + /* allow this to fail */ + } + } +#endif + + if (pp->flags & (SEARCH_FLAG_APPLETV | SEARCH_FLAG_IPHONE)) + { + if (pp->dns == NULL) + { + pp->dns = si_module_with_name("dns"); + /* allow this to fail */ + } + } +} + +__private_extern__ si_mod_t * +si_module_static_search() +{ + si_mod_t *out; + search_si_private_t *pp; + FILE *conf; + char *line, **tokens; + int cat, i, j, ntokens; + + out = search_alloc(); + if (out == NULL) return NULL; + + pp = (search_si_private_t *)out->private; + if (pp == NULL) + { + free(out); + return NULL; + } + +#ifdef CONFIG_MAC + pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_MAC; +#endif +#ifdef CONFIG_APPLETV + pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_APPLETV; +#endif + +#ifdef CONFIG_IPHONE + pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_IPHONE; +#endif + + pp->cache = si_module_with_name("cache"); + if (pp->cache == NULL) + { + search_close(out); + return NULL; + } + + pp->file = si_module_with_name("file"); + if (pp->file == NULL) + { + search_close(out); + return NULL; + } + + init_optional_modules(pp); + + conf = fopen(_PATH_SI_CONF, "r"); + if (conf == NULL) return out; + + forever + { + line = _fsi_get_line(conf); + if (line == NULL) break; + + if (line[0] == '#') + { + free(line); + line = NULL; + continue; + } + + ntokens = 0; + tokens = _fsi_tokenize(line, " : ", 0, &ntokens); + + if (ntokens < 2) + { + free(tokens); + tokens = NULL; + free(line); + line = NULL; + continue; + } + + if (string_equal(tokens[0], "config")) + { + if (string_equal(tokens[1], "mac")) pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_MAC; + else if (string_equal(tokens[1], "appletv")) pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_APPLETV; + else if (string_equal(tokens[1], "iphone")) pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_IPHONE; + + init_optional_modules(pp); + + free(tokens); + tokens = NULL; + free(line); + line = NULL; + continue; + } + + if (string_equal(tokens[0], "user")) cat = CATEGORY_USER; + else if (string_equal(tokens[0], "group")) cat = CATEGORY_GROUP; + else if (string_equal(tokens[0], "grouplist")) cat = CATEGORY_GROUPLIST; + else if (string_equal(tokens[0], "netgroup")) cat = CATEGORY_NETGROUP; + else if (string_equal(tokens[0], "alias")) cat = CATEGORY_ALIAS; + else if (string_equal(tokens[0], "host")) cat = CATEGORY_HOST_IPV4; + else if (string_equal(tokens[0], "network")) cat = CATEGORY_NETWORK; + else if (string_equal(tokens[0], "service")) cat = CATEGORY_SERVICE; + else if (string_equal(tokens[0], "protocol")) cat = CATEGORY_PROTOCOL; + else if (string_equal(tokens[0], "rpc")) cat = CATEGORY_RPC; + else if (string_equal(tokens[0], "fs")) cat = CATEGORY_FS; + else if (string_equal(tokens[0], "mac")) cat = CATEGORY_MAC; + else if (string_equal(tokens[0], "addrinfo")) cat = CATEGORY_ADDRINFO; + else if (string_equal(tokens[0], "nameinfo")) cat = CATEGORY_NAMEINFO; + else + { + free(tokens); + tokens = NULL; + free(line); + line = NULL; + continue; + } + + do_ipv6: + + if (pp->search_list[cat].module != NULL) + { + free(tokens); + tokens = NULL; + free(line); + line = NULL; + continue; + } + + pp->search_list[cat].count = ntokens - 1; + pp->search_list[cat].module = (si_mod_t **)calloc(pp->search_list[cat].count, sizeof(si_mod_t *)); + if (pp->search_list[cat].module == NULL) + { + search_close(out); + free(tokens); + tokens = NULL; + free(line); + line = NULL; + return NULL; + } + + for (i = 1, j = 0; i < ntokens; i++, j++) + { + if (string_equal(tokens[i], "cache")) + { + pp->search_list[cat].module[j] = pp->cache; + pp->search_list[cat].flags = SEARCH_FLAG_CACHE_ENABLED; + } + else if (string_equal(tokens[i], "file")) + { + if (pp->file == NULL) pp->file = si_module_with_name("file"); + pp->search_list[cat].module[j] = pp->file; + } + else if (string_equal(tokens[i], "dns")) + { + if (pp->dns == NULL) pp->dns = si_module_with_name("dns"); + pp->search_list[cat].module[j] = pp->dns; + } + else if (string_equal(tokens[i], "mdns")) + { + if (pp->mdns == NULL) pp->mdns = si_module_with_name("mdns"); + pp->search_list[cat].module[j] = pp->mdns; + } + else if (string_equal(tokens[i], "ds")) + { + if (pp->ds == NULL) pp->ds = si_module_with_name("ds"); + pp->search_list[cat].module[j] = pp->ds; + } + } + + if (cat == CATEGORY_HOST_IPV4) + { + cat = CATEGORY_HOST_IPV6; + goto do_ipv6; + } + + free(tokens); + tokens = NULL; + free(line); + line = NULL; + } + + return out; +} + +__private_extern__ si_mod_t * +search_custom(int n, ...) +{ + va_list ap; + si_mod_t *out, *m; + search_si_private_t *pp; + int cat, i; + char *name; + + if (n == 0) return si_module_static_search(); + + out = search_alloc(); + if (out == NULL) return NULL; + + pp = (search_si_private_t *)out->private; + if (pp == NULL) + { + free(out); + return NULL; + } + + for (cat = 0; cat < CATEGORY_COUNT; cat++) + { + pp->search_list[cat].count = n; + pp->search_list[cat].module = (si_mod_t **)calloc(pp->search_list[cat].count, sizeof(si_mod_t *)); + if (pp->search_list[cat].module == NULL) + { + search_close(out); + return NULL; + } + + } + + va_start(ap, n); + + for (i = 0; i < n; i++) + { + name = va_arg(ap, char *); + if (name == NULL) break; + + m = NULL; + if (string_equal(name, "cache")) + { + if (pp->cache == NULL) + { + pp->cache = si_module_with_name("cache"); + m = pp->cache; + if (pp->cache == NULL) + { + search_close(out); + return NULL; + } + } + } + else if (string_equal(name, "file")) + { + if (pp->file == NULL) + { + pp->file = si_module_with_name("file"); + m = pp->file; + if (pp->file == NULL) + { + search_close(out); + return NULL; + } + } + } + else if (string_equal(name, "dns")) + { + if (pp->dns == NULL) + { + pp->dns = si_module_with_name("dns"); + m = pp->dns; + if (pp->dns == NULL) + { + search_close(out); + return NULL; + } + } + } + else if (string_equal(name, "mdns")) + { + if (pp->mdns == NULL) + { + pp->mdns = si_module_with_name("mdns"); + m = pp->mdns; + if (pp->mdns == NULL) + { + search_close(out); + return NULL; + } + } + } + else if (string_equal(name, "ds")) + { + if (pp->ds == NULL) + { + pp->ds = si_module_with_name("ds"); + m = pp->ds; + if (pp->ds == NULL) + { + search_close(out); + return NULL; + } + } + } + + for (cat = 0; cat < CATEGORY_COUNT; cat++) + { + if (string_equal(name, "cache")) pp->search_list[cat].flags = SEARCH_FLAG_CACHE_ENABLED; + pp->search_list[cat].module[i] = m; + } + } + + va_end(ap); + + return out; +} diff --git a/lookup.subproj/si_data.c b/lookup.subproj/si_data.c new file mode 100644 index 0000000..978f6ac --- /dev/null +++ b/lookup.subproj/si_data.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include "si_data.h" +#include "si_module.h" + +si_list_t * +si_list_add(si_list_t *l, si_item_t *e) +{ + size_t size; + + if (e == NULL) return l; + + if (l == NULL) + { + l = (si_list_t *)calloc(1, sizeof(si_list_t)); + l->refcount = 1; + } + + if (l != NULL) + { + size = (l->count + 1) * sizeof(si_item_t *); + + l->entry = (si_item_t **)reallocf(l->entry, size); + if (l->entry != NULL) + { + l->entry[l->count++] = si_item_retain(e); + } + } + + if ((l == NULL) || (l->entry == NULL)) + { + free(l); + l = NULL; + errno = ENOMEM; + } + + return l; +} + +si_list_t * +si_list_concat(si_list_t *l, si_list_t *x) +{ + si_item_t *item; + uint32_t newcount; + size_t size; + int i; + + if ((x == NULL) || (x->count == 0)) return l; + + if (l == NULL) + { + l = (si_list_t *)calloc(1, sizeof(si_list_t)); + l->refcount = 1; + } + + if (l != NULL) + { + newcount = l->count + x->count; + size = newcount * sizeof(si_item_t *); + + l->entry = (si_item_t **)reallocf(l->entry, size); + if (l->entry) + { + for (i = 0; i < x->count; ++i) + { + item = x->entry[i]; + si_item_retain(item); + l->entry[l->count + i] = item; + } + + l->count += x->count; + } + else + { + l->count = 0; + l = NULL; + } + } + + if (l == NULL) errno = ENOMEM; + + return l; +} + +si_item_t * +si_list_next(si_list_t *list) +{ + if (list == NULL) return NULL; + if (list->curr >= list->count) return NULL; + + return list->entry[list->curr++]; +} + +void +si_list_reset(si_list_t *list) +{ + if (list != NULL) list->curr = 0; +} + +si_list_t * +si_list_retain(si_list_t *list) +{ + int32_t rc; + + if (list == NULL) return NULL; + + rc = OSAtomicIncrement32Barrier(&list->refcount); + assert(rc >= 1); + + return list; +} + +void +si_list_release(si_list_t *list) +{ + int32_t rc, i; + + if (list == NULL) return; + + rc = OSAtomicDecrement32Barrier(&list->refcount); + assert(rc >= 0); + + if (rc == 0) + { + for (i = 0; i < list->count; i++) + { + si_item_release(list->entry[i]); + } + + free(list->entry); + free(list); + } +} + +si_item_t * +si_item_retain(si_item_t *item) +{ + int32_t rc; + + if (item == NULL) return NULL; + + rc = OSAtomicIncrement32Barrier(&item->refcount); + assert(rc >= 1); + + return item; +} + +void +si_item_release(si_item_t *item) +{ + int32_t rc; + + if (item == NULL) return; + + rc = OSAtomicDecrement32Barrier(&item->refcount); + assert(rc >= 0); + + if (rc == 0) free(item); +} diff --git a/lookup.subproj/DSlibinfoMIGAsyncReply.defs b/lookup.subproj/si_data.h similarity index 54% rename from lookup.subproj/DSlibinfoMIGAsyncReply.defs rename to lookup.subproj/si_data.h index 4524a8e..b6ad04e 100644 --- a/lookup.subproj/DSlibinfoMIGAsyncReply.defs +++ b/lookup.subproj/si_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2008 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,35 +21,39 @@ * @APPLE_LICENSE_HEADER_END@ */ -/*! - * @header DSLookupMIGAsyncReply.defs - */ +#ifndef __SI_DATA_H__ +#define __SI_DATA_H__ -/* - * Warning! - * Do not re-order this file as it will cause MIG API number - * changes. Always add to the end of the file for new defs. - */ +#include -subsystem DSlibinfoMIGAsyncReply 50050; +typedef struct +{ + void *src; + uint32_t type; + int32_t refcount; + uint64_t validation_a; + uint64_t validation_b; +} si_item_t; -userprefix libinfoDSmig_; -serverprefix libinfoDSmig_do_; +typedef struct +{ + int32_t refcount; + uint32_t count; + uint32_t curr; + si_item_t **entry; +} si_list_t; -import ; +/* list construction - these do not retain items */ +si_list_t *si_list_add(si_list_t *l, si_item_t *e); +si_list_t *si_list_concat(si_list_t *l, si_list_t *x); -#include -#include +si_list_t *si_list_retain(si_list_t *l); +void si_list_release(si_list_t *l); -import ; +si_item_t *si_list_next(si_list_t *list); +void si_list_reset(si_list_t *list); -type inline_data_t = array [* : 16384] of char; +si_item_t *si_item_retain(si_item_t *item); +void si_item_release(si_item_t *item); -simpleroutine Response_async -( - server : mach_port_move_send_once_t; - reply : inline_data_t; - ooreply : pointer_t, Dealloc; - callbackAddr : mach_vm_address_t; - ServerSecToken servertoken : security_token_t -); +#endif /* ! __SI_DATA_H__ */ diff --git a/lookup.subproj/si_getaddrinfo.c b/lookup.subproj/si_getaddrinfo.c new file mode 100644 index 0000000..8263d57 --- /dev/null +++ b/lookup.subproj/si_getaddrinfo.c @@ -0,0 +1,1338 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "netdb_async.h" +#include "si_module.h" + +#define SOCK_UNSPEC 0 +#define IPPROTO_UNSPEC 0 + +#define IPV6_ADDR_LEN 16 +#define IPV4_ADDR_LEN 4 + +#define WANT_NOTHING 0 +#define WANT_A4_ONLY 1 +#define WANT_A6_ONLY 2 +#define WANT_A6_PLUS_MAPPED_A4 3 +#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 4 + +typedef struct { + struct hostent host; + int alias_count; + int addr_count; + uint64_t ttl; +} build_hostent_t; + +void +freeaddrinfo(struct addrinfo *a) +{ + struct addrinfo *next; + + while (a != NULL) + { + next = a->ai_next; + if (a->ai_addr != NULL) free(a->ai_addr); + if (a->ai_canonname != NULL) free(a->ai_canonname); + free(a); + a = next; + } +} + +const char * +gai_strerror(int32_t err) +{ + switch (err) + { + case EAI_ADDRFAMILY: return "Address family for nodename not supported"; + case EAI_AGAIN: return "Temporary failure in name resolution"; + case EAI_BADFLAGS: return "Invalid value for ai_flags"; + case EAI_FAIL: return "Non-recoverable failure in name resolution"; + case EAI_FAMILY: return "ai_family not supported"; + case EAI_MEMORY: return "Memory allocation failure"; + case EAI_NODATA: return "No address associated with nodename"; + case EAI_NONAME: return "nodename nor servname provided, or not known"; + case EAI_SERVICE: return "servname not supported for ai_socktype"; + case EAI_SOCKTYPE: return "ai_socktype not supported"; + case EAI_SYSTEM: return "System error"; + case EAI_BADHINTS: return "Bad hints"; + case EAI_PROTOCOL: return "ai_protocol not supported"; + case EAI_OVERFLOW: return "argument buffer overflow"; + } + + return "Unknown error"; +} + +/* + * getnameinfo + * + * We handle some "trival" cases locally. If the caller passes + * NI_NUMERICHOST (only), then this call turns into a getservbyport + * to get the service name + inet_pton() to create a host string. + * If the caller passes NI_NUMERICSERV (only), then we zero out the port + * number, complete the getnameinfo, and use printf() to create a service + * string. If the caller specifies both NI_NUMERICHOST and NI_NUMERICSERV, + * we inet_ntop() and printf() and return the results. + */ +__private_extern__ si_item_t * +si_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, uint32_t *err) +{ + si_item_t *out = NULL; + const struct sockaddr *lookup_sa; + struct sockaddr_in s4; + struct in_addr a4; + struct in6_addr a6; + const uint64_t unused = 0; + void *addr = NULL; + char *host = NULL; + char *serv = NULL; + uint32_t ifnum = 0; + uint16_t port = 0; + + int do_host_lookup = ((flags & NI_NUMERICHOST) == 0); + int do_serv_lookup = ((flags & NI_NUMERICSERV) == 0); + + /* check input */ + if ((si == NULL) || (sa == NULL)) + { + if (err != NULL) *err = SI_STATUS_EAI_FAIL; + return NULL; + } + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + lookup_sa = sa; + + if (sa->sa_family == AF_INET) + { + struct sockaddr_in *s4 = (struct sockaddr_in *)sa; + memcpy(&a4, &s4->sin_addr, sizeof(a4)); + port = s4->sin_port; + addr = &a4; + } + else if (sa->sa_family == AF_INET6) + { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)sa; + memcpy(&a6, &s6->sin6_addr, sizeof(a6)); + port = s6->sin6_port; + + /* Look for link-local IPv6 scope id */ + if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) + { + ifnum = ntohs(a6.__u6_addr.__u6_addr16[1]); + if (ifnum == 0) + { + ifnum = s6->sin6_scope_id; + a6.__u6_addr.__u6_addr16[1] = htons(ifnum); + } + + if (ifnum != s6->sin6_scope_id) + { + if (err != NULL) *err = SI_STATUS_EAI_FAIL; + return NULL; + } + } + + /* v4 mapped and compat addresses are converted to plain v4 */ + if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr)) + { + memcpy(&a4, &s6->sin6_addr.s6_addr[12], sizeof(a4)); + addr = &a4; + memset(&s4, 0, sizeof(s4)); + s4.sin_len = sizeof(s4); + s4.sin_family = AF_INET; + s4.sin_port = port; + memcpy(&s4.sin_addr, &a4, sizeof(s4.sin_addr)); + lookup_sa = (const struct sockaddr *)&s4; + } + else + { + addr = &a6; + } + } + else + { + if (err != NULL) *err = SI_STATUS_EAI_FAMILY; + return NULL; + } + + if (do_host_lookup == 1) + { +#if 0 + if ((do_serv_lookup == 1) && (si->sim_nameinfo != NULL)) + { + return si->sim_nameinfo(si, lookup_sa, flags, err); + } +#endif + si_item_t *item = si_host_byaddr(si, addr, lookup_sa->sa_family, NULL); + if (item != NULL) + { + struct hostent *h; + h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); + host = strdup(h->h_name); + si_item_release(item); + if (host == NULL) + { + if (err != NULL) *err = SI_STATUS_EAI_MEMORY; + return NULL; + } + } + } + + if ((do_serv_lookup == 1) && (port != 0)) + { + si_item_t *item = si_service_byport(si, port, NULL); + if (item != NULL) + { + struct servent *s; + s = (struct servent *)((uintptr_t)item + sizeof(si_item_t)); + serv = strdup(s->s_name); + si_item_release(item); + if (serv == NULL) + { + free(host); + if (err != NULL) *err = SI_STATUS_EAI_MEMORY; + return NULL; + } + } + } + + /* + * Return numeric host name for NI_NUMERICHOST or if lookup failed, but not + * if NI_NAMEREQD is specified (so that we later fail with EAI_NONAME). + */ + if (host == NULL && (flags & NI_NAMEREQD) == 0) + { + char tmp[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1]; + tmp[0] = '\0'; + if (sa->sa_family == AF_INET) + { + char buf[INET_ADDRSTRLEN]; + if (inet_ntop(AF_INET, &a4, buf, sizeof(buf)) != 0) + { + host = strdup(buf); + } + } + else if (sa->sa_family == AF_INET6) + { + char buf[INET6_ADDRSTRLEN]; + + /* zero the embedded scope ID */ + if (ifnum != 0) + { + a6.__u6_addr.__u6_addr16[1] = 0; + } + + if (inet_ntop(AF_INET6, &a6, buf, sizeof(buf)) != 0) + { + if (ifnum != 0) + { + char ifname[IF_NAMESIZE]; + if (if_indextoname(ifnum, ifname) != NULL) + { + asprintf(&host, "%s%%%s", buf, ifname); + } + else + { + /* ENXIO */ + if (err != NULL) *err = SI_STATUS_EAI_FAIL; + return NULL; + } + } + else + { + host = strdup(buf); + } + } + } + } + + /* Return numeric service name for NI_NUMERICSERV or if lookup failed. */ + if (serv == NULL) + { + asprintf(&serv, "%hu", ntohs(port)); + } + + if ((host == NULL) || (serv == NULL)) + { + if (err != NULL) + { + if ((flags & NI_NAMEREQD) != 0) + { + *err = SI_STATUS_EAI_NONAME; + } + else + { + *err = SI_STATUS_EAI_MEMORY; + } + } + } + else + { + out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_NAMEINFO, 1, unused, unused, host, serv); + } + + free(host); + free(serv); + return out; +} + +static int +_gai_numericserv(const char *serv, uint16_t *port) +{ + int numeric; + char *endptr; + long num; + + numeric = 0; + + if (serv == NULL) + { + if (port) *port = 0; + numeric = 1; + } + else + { + num = strtol(serv, &endptr, 10); + if ((serv[0] != '\0') && (*endptr == '\0') && (num >= 0) && (num <= UINT16_MAX)) + { + numeric = 1; + if (port != NULL) *port = (uint16_t)num; + } + } + + return numeric; +} + +__private_extern__ int +_gai_serv_to_port(const char *serv, uint32_t proto, uint16_t *port) +{ + si_item_t *item; + struct servent *s; + const char *protoname = NULL; + + if (_gai_numericserv(serv, port)) return 0; + + if (proto == IPPROTO_UDP) protoname = "udp"; + if (proto == IPPROTO_TCP) protoname = "tcp"; + + item = si_service_byname(si_search(), serv, protoname); + if (item == NULL) return -1; + + s = (struct servent *)((uintptr_t)item + sizeof(si_item_t)); + if (port) *port = ntohs(s->s_port); + si_item_release(item); + + return 0; +} + +__private_extern__ si_item_t * +si_addrinfo_v4(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr *addr, uint16_t iface, const char *cname) +{ + socket_data_t sockdata; + struct sockaddr_in *sa; + int32_t len, v32; + uint64_t unused; + + unused = 0; + len = sizeof(struct sockaddr_in); + memset(&sockdata, 0, sizeof(socket_data_t)); + sa = (struct sockaddr_in *)&sockdata; + + sa->sin_len = len; + sa->sin_family = AF_INET; + sa->sin_port = htons(port); + memcpy(&sa->sin_addr, addr, sizeof(sa->sin_addr)); + + /* Kludge: Jam the interface number into sin_zero (4 bytes). */ + v32 = iface; + memmove(sa->sin_zero, &v32, sizeof(uint32_t)); + + return (si_item_t *)LI_ils_create("L448844444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET, sock, proto, len, sockdata, cname); +} + +__private_extern__ si_item_t * +si_addrinfo_v6(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr *addr, uint16_t iface, const char *cname) +{ + socket_data_t sockdata; + struct sockaddr_in6 *sa; + int32_t len; + uint64_t unused; + + unused = 0; + len = sizeof(struct sockaddr_in6); + memset(&sockdata, 0, sizeof(socket_data_t)); + sa = (struct sockaddr_in6 *)&sockdata; + + sa->sin6_len = len; + sa->sin6_family = AF_INET6; + sa->sin6_port = htons(port); + memcpy(&sa->sin6_addr, addr, sizeof(sa->sin6_addr)); + + /* sin6_scope_id is in host byte order */ + sa->sin6_scope_id = iface; + + if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) + { + /* check for embedded scopeid */ + uint16_t esid = ntohs(sa->sin6_addr.__u6_addr.__u6_addr16[1]); + if (esid != 0) + { + sa->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + if (iface == 0) sa->sin6_scope_id = esid; + } + } + + return (si_item_t *)LI_ils_create("L448844444Ss", (unsigned long)si, CATEGORY_ADDRINFO, 1, unused, unused, flags, AF_INET6, sock, proto, len, sockdata, cname); +} + +__private_extern__ si_list_t * +si_addrinfo_list(si_mod_t *si, int socktype, int proto, struct in_addr *a4, struct in6_addr *a6, int port, int scopeid, const char *cname4, const char *cname6) +{ + si_item_t *item = NULL; + si_list_t *out4 = NULL, *out6 = NULL; + if (a4 != NULL) + { + if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) + { + item = si_addrinfo_v4(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a4, 0, cname4); + out4 = si_list_add(out4, item); + si_item_release(item); + } + + if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) + { + item = si_addrinfo_v4(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a4, 0, cname4); + out4 = si_list_add(out4, item); + si_item_release(item); + } + + if (proto == IPPROTO_ICMP) + { + item = si_addrinfo_v4(si, 0, SOCK_RAW, IPPROTO_ICMP, port, a4, 0, cname4); + out4 = si_list_add(out4, item); + si_item_release(item); + } + } + + if (a6 != NULL) + { + if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_UDP)) + { + item = si_addrinfo_v6(si, 0, SOCK_DGRAM, IPPROTO_UDP, port, a6, scopeid, cname6); + out6 = si_list_add(out6, item); + si_item_release(item); + } + + if ((proto == IPPROTO_UNSPEC) || (proto == IPPROTO_TCP)) + { + item = si_addrinfo_v6(si, 0, SOCK_STREAM, IPPROTO_TCP, port, a6, scopeid, cname6); + out6 = si_list_add(out6, item); + si_item_release(item); + } + + if (proto == IPPROTO_ICMPV6) + { + item = si_addrinfo_v6(si, 0, SOCK_RAW, IPPROTO_ICMPV6, port, a6, scopeid, cname6); + out6 = si_list_add(out6, item); + si_item_release(item); + } + } + + out6 = si_list_concat(out6, out4); + si_list_release(out4); + + return out6; +} + +/* + * _gai_numerichost + * Determines whether the given host name is a numeric IPv4 or IPv6 address, + * based on the address family input value. If the input addres family is + * unspecified, a more specific value will be provided on output if possible. + * Returns 1 if host name is numeric or 0 if not, or -1 on error. + */ +static int +_gai_numerichost(const char* nodename, uint32_t *family, int flags, struct in_addr *a4, struct in6_addr *a6) +{ + int numerichost, passive; + + numerichost = 0; + + if (nodename == NULL) + { + /* return loopback or passive addresses */ + passive = (flags & AI_PASSIVE); + + if ((*family == AF_UNSPEC) || (*family == AF_INET)) + { + if (passive) a4->s_addr = 0; + else a4->s_addr = htonl(INADDR_LOOPBACK); + } + + if ((*family == AF_UNSPEC) || (*family == AF_INET6)) + { + memset(a6, 0, sizeof(*a6)); + if (!passive) a6->__u6_addr.__u6_addr32[3] = htonl(1); + } + + numerichost = 1; + } + else + { + /* numeric IPv4 host valid for AF_UNSPEC and AF_INET */ + numerichost = inet_pton(AF_INET, nodename, a4); + if (numerichost == 1) + { + if (*family == AF_UNSPEC) *family = AF_INET; + else if (*family == AF_INET6) numerichost = -1; + return numerichost; + } + + /* numeric IPv6 host valid for AF_UNSPEC and AF_INET6 */ + numerichost = inet_pton(AF_INET6, nodename, a6); + if (numerichost == 1) + { + if (*family == AF_UNSPEC) *family = AF_INET6; + else if (*family == AF_INET) numerichost = -1; + return numerichost; + } + } + + return numerichost; +} + +/* si_addrinfo_list_from_hostent + * Returns an addrinfo list from IPv4 and IPv6 hostent entries + */ +__private_extern__ si_list_t * +si_addrinfo_list_from_hostent(si_mod_t *si, uint32_t socktype, uint32_t proto, uint16_t port, uint16_t scope, const struct hostent *h4, const struct hostent *h6) +{ + int i; + si_list_t *out = NULL; + si_list_t *list; + + if ((h6 != NULL) && (h6->h_addr_list != NULL)) + { + for (i = 0; h6->h_addr_list[i] != NULL; i++) + { + struct in6_addr a6; + memcpy(&a6, h6->h_addr_list[i], h6->h_length); + list = si_addrinfo_list(si, socktype, proto, NULL, &a6, port, scope, NULL, h6->h_name); + out = si_list_concat(out, list); + si_list_release(list); + } + } + + if ((h4 != NULL) && (h4->h_addr_list != NULL)) + { + for (i = 0; h4->h_addr_list[i] != NULL; i++) + { + struct in_addr a4; + memcpy(&a4, h4->h_addr_list[i], h4->h_length); + list = si_addrinfo_list(si, socktype, proto, &a4, NULL, port, 0, h4->h_name, NULL); + out = si_list_concat(out, list); + si_list_release(list); + } + } + + return out; +} + +/* _gai_simple + * Simple lookup via gethostbyname2(3) mechanism. + */ +static si_list_t * +_gai_simple(si_mod_t *si, const void *nodeptr, const void *servptr, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, uint32_t *err) +{ + si_item_t *h4_item = NULL, *h6_item = NULL; + struct hostent *h4 = NULL, *h6 = NULL; + si_list_t *out = NULL; + uint16_t port; + + if ((flags & AI_NUMERICSERV) != 0) + { + port = *(uint16_t*)servptr; + } + else + { + if (_gai_serv_to_port(servptr, proto, &port) != 0) + { + if (err) *err = SI_STATUS_EAI_NONAME; + return NULL; + } + } + + if ((flags & AI_NUMERICHOST) != 0) + { + if (family == AF_INET) + { + h4_item = si_host_byaddr(si, nodeptr, AF_INET, NULL); + } + else if (family == AF_INET6) + { + h6_item = si_host_byaddr(si, nodeptr, AF_INET6, NULL); + } + } + else + { + if ((family == AF_INET) || (family == AF_UNSPEC)) + { + h4_item = si_host_byname(si, nodeptr, AF_INET, NULL); + } +#if !TARGET_OS_EMBEDDED + if ((family == AF_INET6) || (family == AF_UNSPEC)) + { + h6_item = si_host_byname(si, nodeptr, AF_INET6, NULL); + } +#endif /* !TARGET_OS_EMBEDDED */ + } + + if (h4_item != NULL) + { + h4 = (struct hostent *)((uintptr_t)h4_item + sizeof(si_item_t)); + } + + if (h6_item != NULL) + { + h6 = (struct hostent *)((uintptr_t)h6_item + sizeof(si_item_t)); + } + + out = si_addrinfo_list_from_hostent(si, socktype, proto, port, 0, h4, h6); + si_item_release(h4_item); + si_item_release(h6_item); + + return out; +} + +__private_extern__ si_list_t * +si_srv_byname(si_mod_t *si, const char *qname, uint32_t *err) +{ + if (si == NULL) return 0; + if (si->sim_srv_byname == NULL) return 0; + + return si->sim_srv_byname(si, qname, err); +} + +__private_extern__ int +si_wants_addrinfo(si_mod_t *si) +{ + if (si == NULL) return 0; + if (si->sim_addrinfo == NULL) return 0; + if (si->sim_wants_addrinfo == NULL) return 0; + + return si->sim_wants_addrinfo(si); +} + +__private_extern__ si_list_t * +si_addrinfo(si_mod_t *si, const char *node, const char *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, uint32_t *err) +{ + int i, lastprio, numerichost, numericserv = 0; + const void *nodeptr = NULL, *servptr = NULL; + uint16_t port; + struct in_addr a4, *p4; + struct in6_addr a6, *p6; + char srvnode[MAXHOSTNAMELEN]; + const char *cname; + si_srv_t *srv; + si_item_t *item; + si_list_t *list; + char *qname; + + if (err != NULL) *err = SI_STATUS_NO_ERROR; + + if (si == NULL) + { + if (err != NULL) *err = SI_STATUS_EAI_FAIL; + return NULL; + } + + /* treat empty strings as NULL */ + if ((node != NULL) && (node[0] == '\0')) node = NULL; + if ((serv != NULL) && (serv[0] == '\0')) serv = NULL; + + /* make sure we have a query */ + if ((node == NULL) && (serv == NULL)) + { + if (err != NULL) *err = SI_STATUS_EAI_NONAME; + return NULL; + } + + /* verify family is supported */ + switch (family) + { + case AF_UNSPEC: +#if TARGET_OS_EMBEDDED + family = AF_INET; +#endif + case AF_INET: + case AF_INET6: + break; + default: + if (err != NULL) *err = SI_STATUS_EAI_FAMILY; + return NULL; + } + + /* verify socket type is supported */ + switch (socktype) + { + case SOCK_UNSPEC: + case SOCK_RAW: + case SOCK_DGRAM: + case SOCK_STREAM: + break; + default: + if (err != NULL) *err = SI_STATUS_EAI_BADHINTS; + return NULL; + } + + /* verify protocol is supported */ + switch (proto) + { + case IPPROTO_UNSPEC: + case IPPROTO_UDP: + case IPPROTO_TCP: + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: + break; + default: + if (err != NULL) *err = SI_STATUS_EAI_BADHINTS; + return NULL; + } + + /* verify socket type compatible with protocol */ + if (((socktype == SOCK_DGRAM) && (proto != IPPROTO_UNSPEC) && (proto != IPPROTO_UDP)) || ((socktype == SOCK_STREAM) && (proto != IPPROTO_UNSPEC) && (proto != IPPROTO_TCP))) + { + if (err != NULL) *err = SI_STATUS_EAI_BADHINTS; + return NULL; + } + + memset(&a4, 0, sizeof(struct in_addr)); + memset(&a6, 0, sizeof(struct in6_addr)); + + /* determine the protocol if possible */ + if ((proto == IPPROTO_UNSPEC) && (socktype == SOCK_DGRAM)) proto = IPPROTO_UDP; + if ((proto == IPPROTO_UNSPEC) && (socktype == SOCK_STREAM)) proto = IPPROTO_TCP; + + port = 0; + + if ((flags & AI_SRV) != 0) + { + /* AI_SRV SPI */ + lastprio = INT_MAX; + + /* set so that getaddrinfo(3) fails if the SRV fails */ + flags |= AI_NUMERICSERV; + + /* XXX what if serv is NULL */ + asprintf(&qname, "%s.%s", serv, node); + list = si_srv_byname(si, qname, err); + free(qname); + + if (list != NULL) + { + for (i = 0; i < list->count; ++i) + { + item = list->entry[i]; + srv = (si_srv_t *)((uintptr_t)item + sizeof(si_item_t)); + + if (srv->priority < lastprio) + { + port = srv->port; + numericserv = 1; + strlcpy(srvnode, srv->target, sizeof(srvnode)); + node = srvnode; + } + } + + si_list_release(list); + } + } + else + { + /* Usual service lookup */ + numericserv = _gai_numericserv(serv, &port); + } + + if ((flags & AI_NUMERICSERV) && (numericserv == 0)) + { + /* FreeBSD returns SI_STATUS_EAI_SERVICE */ + if (err != NULL) *err = SI_STATUS_EAI_NONAME; + return NULL; + } + + if (serv != NULL) + { + if (numericserv == 1) + { + flags |= AI_NUMERICSERV; + servptr = &port; + } + else + { + servptr = serv; + } + } + + numerichost = _gai_numerichost(node, &family, flags, &a4, &a6); + if ((numerichost == -1) || ((flags & AI_NUMERICHOST) && (numerichost == 0))) + { + if (err != NULL) *err = SI_STATUS_EAI_NONAME; + return NULL; + } + + if (numerichost == 1) + { + flags |= AI_NUMERICHOST; + if (family == AF_INET) + { + nodeptr = &a4; + } + else if (family == AF_INET6) + { + nodeptr = &a6; + } + } + else + { + nodeptr = node; + } + + if ((numerichost == 1) && (numericserv == 0)) + { + /* only service lookup needed. convert to port and perform a trivial getaddrinfo */ + if (_gai_serv_to_port(serv, proto, &port) != 0) + { + if (err != NULL) *err = SI_STATUS_EAI_NONAME; + return NULL; + } + else + { + flags |= AI_NUMERICSERV; + servptr = &port; + numericserv = 1; + } + } + + if ((numerichost == 1) && (numericserv == 1)) + { + p4 = &a4; + p6 = &a6; + cname = NULL; + + if (family == AF_INET) p6 = NULL; + if (family == AF_INET6) p4 = NULL; + if (node == NULL) cname = "localhost"; + + /* handle trivial questions */ + return si_addrinfo_list(si, socktype, proto, p4, p6, port, 0, cname, cname); + } + else if ((si->sim_wants_addrinfo != NULL) && si->sim_wants_addrinfo(si)) + { + /* or let the current module handle the host lookups intelligently */ + return si->sim_addrinfo(si, nodeptr, servptr, family, socktype, proto, flags, err); + } + + /* fall back to a default path */ + return _gai_simple(si, nodeptr, servptr, family, socktype, proto, flags, err); +} + +static struct addrinfo * +si_item_to_addrinfo(si_item_t *item) +{ + si_addrinfo_t *a; + struct addrinfo *out; + + if (item == NULL) return NULL; + + a = (si_addrinfo_t *)((uintptr_t)item + sizeof(si_item_t)); + + out = (struct addrinfo *)calloc(1, sizeof(struct addrinfo)); + if (out == NULL) return NULL; + + out->ai_flags = a->ai_flags; + out->ai_family = a->ai_family; + out->ai_socktype = a->ai_socktype; + out->ai_protocol = a->ai_protocol; + out->ai_addrlen = a->ai_addrlen; + + out->ai_addr = (struct sockaddr *)calloc(1, out->ai_addrlen); + if (out->ai_addr == NULL) + { + free(out); + return NULL; + } + + memcpy(out->ai_addr, a->ai_addr.x, out->ai_addrlen); + + if (a->ai_canonname != NULL) + { + out->ai_canonname = strdup(a->ai_canonname); + if (out->ai_canonname == NULL) + { + free(out); + return NULL; + } + } + + return out; +} + +__private_extern__ struct addrinfo * +si_list_to_addrinfo(si_list_t *list) +{ + struct addrinfo *tail, *out; + int i; + + if (list == NULL) return NULL; + if (list->count == 0) return NULL; + + i = list->count - 1; + + out = si_item_to_addrinfo(list->entry[i]); + tail = out; + + for (i--; i >= 0; i--) + { + out = si_item_to_addrinfo(list->entry[i]); + if (out == NULL) + { + freeaddrinfo(tail); + return NULL; + } + + out->ai_next = tail; + tail = out; + } + + return out; +} + +/* getipnodebyname */ + +static si_item_t * +make_hostent(si_mod_t *si, const char *name, struct in_addr addr) +{ + char *addrs[2]; + char *aliases[1]; + uint64_t unused; + + if (name == NULL) return NULL; + + unused = 0; + + addrs[0] = (char *)&(addr.s_addr); + addrs[1] = NULL; + aliases[0] = NULL; + + return (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, unused, unused, name, aliases, AF_INET, IPV4_ADDR_LEN, addrs); +} + +static si_item_t * +make_hostent6(si_mod_t *si, const char *name, struct in6_addr addr) +{ + char *addrs[2]; + char *aliases[1]; + uint64_t unused; + + if (name == NULL) return NULL; + + unused = 0; + + addrs[0] = (char *)&(addr.__u6_addr.__u6_addr32[0]); + addrs[1] = NULL; + aliases[0] = NULL; + + return (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, name, aliases, AF_INET6, IPV6_ADDR_LEN, addrs); +} + +static char * +lower_case(const char *s) +{ + int i; + char *t; + + if (s == NULL) return NULL; + + t = malloc(strlen(s) + 1); + + for (i = 0; s[i] != '\0'; i++) + { + if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32; + else t[i] = s[i]; + } + + t[i] = '\0'; + + return t; +} + +static int +merge_alias(const char *name, build_hostent_t *h) +{ + int i; + + if (name == NULL) return 0; + if (h == NULL) return 0; + + if ((h->host.h_name != NULL) && (string_equal(name, h->host.h_name))) return 0; + + for (i = 0; i < h->alias_count; i++) + { + if (string_equal(name, h->host.h_aliases[i])) return 0; + } + + if (h->alias_count == 0) h->host.h_aliases = (char **)calloc(2, sizeof(char *)); + else h->host.h_aliases = (char **)reallocf(h->host.h_aliases, (h->alias_count + 2) * sizeof(char *)); + + if (h->host.h_aliases == NULL) + { + h->alias_count = 0; + return -1; + } + + h->host.h_aliases[h->alias_count] = lower_case(name); + h->alias_count++; + h->host.h_aliases[h->alias_count] = NULL; + + return 0; +} + +static int +append_addr(const char *addr, uint32_t len, build_hostent_t *h) +{ + if (addr == NULL) return 0; + if (h == NULL) return 0; + + if (h->addr_count == 0) h->host.h_addr_list = (char **)calloc(2, sizeof(char *)); + else h->host.h_addr_list = (char **)reallocf(h->host.h_addr_list, (h->addr_count + 2) * sizeof(char *)); + + if (h->host.h_addr_list == NULL) + { + h->addr_count = 0; + return -1; + } + + h->host.h_addr_list[h->addr_count] = malloc(len); + if (h->host.h_addr_list[h->addr_count] == NULL) return -1; + + memcpy(h->host.h_addr_list[h->addr_count], addr, len); + h->addr_count++; + h->host.h_addr_list[h->addr_count] = NULL; + + return 0; +} + +static void +free_build_hostent(build_hostent_t *h) +{ + uint32_t i; + char **aliases; + + if (h == NULL) return; + + if (h->host.h_name != NULL) free(h->host.h_name); + h->host.h_name = NULL; + + aliases = h->host.h_aliases; + if (aliases != NULL) + { + while (*aliases != NULL) free(*aliases++); + free(h->host.h_aliases); + } + + h->host.h_aliases = NULL; + + if (h->host.h_addr_list != NULL) + { + for (i = 0; h->host.h_addr_list[i] != NULL; i++) free(h->host.h_addr_list[i]); + free(h->host.h_addr_list); + } + + h->host.h_addr_list = NULL; + free(h); +} + +__private_extern__ si_item_t * +si_ipnode_byname(si_mod_t *si, const char *name, int family, int flags, uint32_t *err) +{ + int i, status, want, if4, if6; + struct ifaddrs *ifa, *ifap; + struct in_addr addr4; + struct in6_addr addr6; + si_item_t *item4, *item6; + build_hostent_t *out; + struct hostent *h; + uint64_t unused; + + memset(&addr4, 0, sizeof(struct in_addr)); + memset(&addr6, 0, sizeof(struct in6_addr)); + + if (err != NULL) *err = 0; + + if (family == AF_INET) + { + status = inet_aton(name, &addr4); + if (status == 1) + { + /* create a host entry */ + item4 = make_hostent(si, name, addr4); + if (item4 == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + return item4; + } + } + else if (family == AF_INET6) + { + status = inet_pton(family, name, &addr6); + if (status == 1) + { + /* create a host entry */ + item6 = make_hostent6(si, name, addr6); + if (item6 == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + return item6; + } + + status = inet_aton(name, &addr4); + if (status == 1) + { + if (!(flags & (AI_V4MAPPED | AI_V4MAPPED_CFG))) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + addr6.__u6_addr.__u6_addr32[0] = 0x00000000; + addr6.__u6_addr.__u6_addr32[1] = 0x00000000; + addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); + memmove(&(addr6.__u6_addr.__u6_addr32[3]), &(addr4.s_addr), IPV4_ADDR_LEN); + + /* create a host entry */ + item6 = make_hostent6(si, name, addr6); + if (item6 == NULL) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + return item6; + } + } + else + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + /* + * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have. + */ + + if4 = 0; + if6 = 0; + + if (flags & AI_ADDRCONFIG) + { + if (getifaddrs(&ifa) < 0) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) + { + if (ifap->ifa_addr == NULL) continue; + if ((ifap->ifa_flags & IFF_UP) == 0) continue; + if (ifap->ifa_addr->sa_family == AF_INET) if4++; + else if (ifap->ifa_addr->sa_family == AF_INET6) if6++; + } + + freeifaddrs(ifa); + + /* Bail out if there are no interfaces */ + if ((if4 == 0) && (if6 == 0)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + } + + /* + * Figure out what we want. + * If user asked for AF_INET, we only want V4 addresses. + */ + want = WANT_A4_ONLY; + + if (family == AF_INET) + { + if ((flags & AI_ADDRCONFIG) && (if4 == 0)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + } + else if (family == AF_INET6) + { + /* family == AF_INET6 */ + want = WANT_A6_ONLY; + + if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG)) + { + if (flags & AI_ALL) + { + want = WANT_A6_PLUS_MAPPED_A4; + } + else + { + want = WANT_A6_OR_MAPPED_A4_IF_NO_A6; + } + } + else + { + if ((flags & AI_ADDRCONFIG) && (if6 == 0)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + } + } + else + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + item6 = NULL; + item4 = NULL; + + /* fetch IPv6 data if required */ + if ((want == WANT_A6_ONLY) || (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) || (want == WANT_A6_PLUS_MAPPED_A4)) + { + item6 = si_host_byname(si, name, AF_INET6, (uint32_t *)err); + } + + /* fetch IPv4 data if required */ + if ((want == WANT_A4_ONLY) || (want == WANT_A6_PLUS_MAPPED_A4) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (item6 == NULL))) + { + item4 = si_host_byname(si, name, AF_INET, (uint32_t *)err); + } + + if (want == WANT_A4_ONLY) + { + si_item_release(item6); + if ((item4 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return item4; + } + + if (want == WANT_A6_ONLY) + { + si_item_release(item4); + if ((item6 == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return item6; + } + + if ((item6 == NULL) && (item4 == NULL)) + { + if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; + return NULL; + } + + /* output item will have IPv6 + mapped IPv4 addresses */ + + out = (build_hostent_t *)calloc(1, sizeof(build_hostent_t)); + if (out == NULL) + { + si_item_release(item4); + si_item_release(item6); + if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY; + return NULL; + } + + if (item4 != NULL) + { + h = (struct hostent *)((uintptr_t)item4 + sizeof(si_item_t)); + + out->host.h_name = lower_case(h->h_name); + + if (h->h_aliases != NULL) + { + for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out); + } + + for (i = 0; h->h_addr_list[i] != 0; i++) + { + addr6.__u6_addr.__u6_addr32[0] = 0x00000000; + addr6.__u6_addr.__u6_addr32[1] = 0x00000000; + addr6.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff); + memmove(&(addr6.__u6_addr.__u6_addr32[3]), h->h_addr_list[i], IPV4_ADDR_LEN); + append_addr((const char *)&addr6, IPV6_ADDR_LEN, out); + } + } + + if (item6 != NULL) + { + h = (struct hostent *)((uintptr_t)item6 + sizeof(si_item_t)); + + if (out->host.h_name == NULL) out->host.h_name = lower_case(h->h_name); + + if (h->h_aliases != NULL) + { + for (i = 0; h->h_aliases[i] != NULL; i++) merge_alias(h->h_aliases[i], out); + } + + for (i = 0; h->h_addr_list[i] != 0; i++) append_addr((const char *)&(h->h_addr_list[i]), IPV6_ADDR_LEN, out); + } + + si_item_release(item4); + si_item_release(item6); + + unused = 0; + + item6 = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, unused, unused, out->host.h_name, out->host.h_aliases, AF_INET6, IPV6_ADDR_LEN, out->host.h_addr_list); + + free_build_hostent(out); + + return item6; +} diff --git a/lookup.subproj/si_module.c b/lookup.subproj/si_module.c new file mode 100644 index 0000000..42ce205 --- /dev/null +++ b/lookup.subproj/si_module.c @@ -0,0 +1,1138 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "si_module.h" + +#define PLUGIN_DIR_PATH "/usr/lib/info" +#define PLUGIN_BUNDLE_SUFFIX "so" + +#define WORKUNIT_CALL_ACTIVE 0x00000001 +#define WORKUNIT_THREAD_ACTIVE 0x00000002 +#define WORKUNIT_RETURNS_LIST 0x00000004 + +typedef struct si_async_workunit_s +{ + si_mod_t *si; + uint32_t call; + char *str1; + char *str2; + uint32_t num1; + uint32_t num2; + uint32_t num3; + uint32_t num4; + uint32_t err; + /* async support below */ + uint32_t flags; + void *callback; + void *context; + mach_port_t port; + mach_port_t send; + si_item_t *resitem; + si_list_t *reslist; + struct si_async_workunit_s *next; +} si_async_workunit_t; + +static si_mod_t **module_list = NULL; +static uint32_t module_count = 0; +static pthread_mutex_t module_mutex = PTHREAD_MUTEX_INITIALIZER; +static si_async_workunit_t *si_async_worklist = NULL; + +__private_extern__ si_mod_t *si_module_static_search(); +__private_extern__ si_mod_t *si_module_static_file(); +__private_extern__ si_mod_t *si_module_static_cache(); +__private_extern__ si_mod_t *si_module_static_mdns(); +#ifdef DS_AVAILABLE +__private_extern__ si_mod_t *si_module_static_ds(); +#endif + +static void * +si_mod_dlsym(void *so, const char *name, const char *sym) +{ + char *str; + void *out; + + if ((so == NULL) || (name == NULL) || (sym == NULL)) return NULL; + + str = NULL; + asprintf(&str, "%s_%s", name, sym); + if (str == NULL) return NULL; + + out = dlsym(so, str); + free(str); + return out; +} + +static si_mod_t * +si_mod_static(const char *name) +{ + if (name == NULL) return NULL; + + if (string_equal(name, "search")) return si_module_static_search(); + if (string_equal(name, "file")) return si_module_static_file(); + if (string_equal(name, "cache")) return si_module_static_cache(); + if (string_equal(name, "mdns")) return si_module_static_mdns(); +#ifdef DS_AVAILABLE + if (string_equal(name, "ds")) return si_module_static_ds(); +#endif + return NULL; +} + +__private_extern__ si_mod_t * +si_module_with_path(const char *path, const char *name) +{ + void *so; + int (*si_sym_init)(si_mod_t *); + void (*si_sym_close)(si_mod_t *); + int status; + si_mod_t *out; + char *outname; + + if ((path == NULL) || (name == NULL)) + { + errno = EINVAL; + return NULL; + } + + so = dlopen(path, RTLD_LOCAL); + if (so == NULL) return NULL; + + si_sym_init = si_mod_dlsym(so, name, "init"); + if (si_sym_init == NULL) + { + dlclose(so); + errno = ECONNREFUSED; + return NULL; + } + + si_sym_close = si_mod_dlsym(so, name, "close"); + if (si_sym_close == NULL) + { + dlclose(so); + errno = ECONNREFUSED; + return NULL; + } + + out = (si_mod_t *)calloc(1, sizeof(si_mod_t)); + outname = strdup(name); + + if ((out == NULL) || (outname == NULL)) + { + if (out != NULL) free(out); + if (outname != NULL) free(outname); + dlclose(so); + errno = ENOMEM; + return NULL; + } + + out->name = outname; + out->refcount = 1; + out->bundle = so; + + status = si_sym_init(out); + if (status != 0) + { + dlclose(so); + free(out); + free(outname); + errno = ECONNREFUSED; + return NULL; + } + + return out; +} + +si_mod_t * +si_module_with_name(const char *name) +{ + uint32_t i; + char *path; + si_mod_t *out; + + if (name == NULL) + { + errno = EINVAL; + return NULL; + } + + pthread_mutex_lock(&module_mutex); + + for (i = 0; i < module_count; i++) + { + if (string_equal(module_list[i]->name, name)) + { + si_module_retain(module_list[i]); + pthread_mutex_unlock(&module_mutex); + return module_list[i]; + } + } + + pthread_mutex_unlock(&module_mutex); + out = si_mod_static(name); + pthread_mutex_lock(&module_mutex); + + if (out == NULL) + { + path = NULL; + + /* mdns lives in dns.so */ + asprintf(&path, "%s/%s.%s", PLUGIN_DIR_PATH, name, PLUGIN_BUNDLE_SUFFIX); + + if (path == NULL) + { + errno = ENOMEM; + pthread_mutex_unlock(&module_mutex); + return NULL; + } + + out = si_module_with_path(path, name); + free(path); + } + + if (out == NULL) + { + pthread_mutex_unlock(&module_mutex); + return NULL; + } + + /* add out to module_list */ + if (module_count == 0) + { + module_list = (si_mod_t **)calloc(1, sizeof(si_mod_t *)); + } + else + { + module_list = (si_mod_t **)reallocf(module_list, (module_count + 1) * sizeof(si_mod_t *)); + } + + if (module_list == NULL) + { + pthread_mutex_unlock(&module_mutex); + return out; + } + + module_list[module_count] = out; + module_count++; + + pthread_mutex_unlock(&module_mutex); + + return out; +} + +__private_extern__ si_mod_t * +si_module_retain(si_mod_t *si) +{ + if (si == NULL) return NULL; + + OSAtomicIncrement32Barrier(&si->refcount); + + return si; +} + +void +si_module_release(si_mod_t *si) +{ + int32_t i; + + if (si == NULL) return; + + i = OSAtomicDecrement32Barrier(&si->refcount); + if (i > 0) return; + + pthread_mutex_lock(&module_mutex); + + for (i = 0; (i < module_count) && (module_list[i] != si); i++); + if (i >= module_count) + { + pthread_mutex_unlock(&module_mutex); + return; + } + + if (module_count == 1) + { + free(module_list); + module_list = NULL; + module_count = 0; + pthread_mutex_unlock(&module_mutex); + return; + } + + for (i++; i < module_count; i++) module_list[i - 1] = module_list[i]; + module_count--; + module_list = (si_mod_t **)reallocf(module_list, module_count * sizeof(si_mod_t *)); + if (module_list == NULL) module_count = 0; + + pthread_mutex_unlock(&module_mutex); + + if (si->sim_close != NULL) si->sim_close(si); + if (si->bundle != NULL) dlclose(si->bundle); + if (si->name != NULL) free(si->name); + free(si); +} + +__private_extern__ const char * +si_module_name(si_mod_t *si) +{ + if (si == NULL) return NULL; + + return si->name; +} + +__private_extern__ int +si_module_vers(si_mod_t *si) +{ + if (si == NULL) return 0; + + return si->vers; +} + +__private_extern__ int +si_item_match(si_item_t *item, int cat, const void *name, uint32_t num, int which) +{ + int i; + union + { + char *x; + struct passwd *u; + struct group *g; + struct grouplist_s *l; + struct aliasent *a; + struct hostent *h; + struct netent *n; + struct servent *s; + struct protoent *p; + struct rpcent *r; + struct fstab *f; + struct mac_s *m; + } ent; + + if (item == NULL) return 0; + if (which == SEL_ALL) return 1; + if ((which == SEL_NAME) && (name == NULL)) return 0; + + ent.x = (char *)((uintptr_t)item + sizeof(si_item_t)); + + switch (cat) + { + case CATEGORY_USER: + { + if ((which == SEL_NAME) && (string_equal(name, ent.u->pw_name))) return 1; + else if ((which == SEL_NUMBER) && (num == (uint32_t)ent.u->pw_uid)) return 1; + return 0; + } + case CATEGORY_GROUP: + { + if ((which == SEL_NAME) && (string_equal(name, ent.g->gr_name))) return 1; + else if ((which == SEL_NUMBER) && (num == (uint32_t)ent.g->gr_gid)) return 1; + return 0; + } + case CATEGORY_GROUPLIST: + { + if ((which == SEL_NAME) && (string_equal(name, ent.l->gl_user))) return 1; + return 0; + } + case CATEGORY_ALIAS: + { + if ((which == SEL_NAME) && (string_equal(name, ent.a->alias_name))) return 1; + return 0; + } + case CATEGORY_HOST_IPV4: + case CATEGORY_HOST_IPV6: + { + /* N.B. address family is passed in num variable */ + if (ent.h->h_addrtype != num) return 0; + if (which == SEL_NAME) + { + if (string_equal(name, ent.h->h_name)) return 1; + if (ent.h->h_aliases != NULL) + { + for (i = 0; ent.h->h_aliases[i] != NULL; i++) + { + if (string_equal(name, ent.h->h_aliases[i])) return 1; + } + } + } + else if (which == SEL_NUMBER) + { + if (memcmp(name, ent.h->h_addr_list[0], ent.h->h_length) == 0) return 1; + } + return 0; + } + case CATEGORY_NETWORK: + { + if (which == SEL_NAME) + { + if (string_equal(name, ent.n->n_name)) return 1; + if (ent.n->n_aliases != NULL) + { + for (i = 0; ent.n->n_aliases[i] != NULL; i++) + { + if (string_equal(name, ent.n->n_aliases[i])) return 1; + } + } + } + else if (which == SEL_NUMBER) + { + if (num == ent.n->n_net) return 1; + } + return 0; + } + case CATEGORY_SERVICE: + { + if (which == SEL_NAME) + { + /* N.B. for SEL_NAME, num is 0 (don't care), 1 (udp) or 2 (tcp) */ + if ((num == 1) && (string_not_equal("udp", ent.s->s_proto))) return 0; + if ((num == 2) && (string_not_equal("tcp", ent.s->s_proto))) return 0; + + if (string_equal(name, ent.s->s_name)) return 1; + if (ent.s->s_aliases != NULL) + { + for (i = 0; ent.s->s_aliases[i] != NULL; i++) + { + if (string_equal(name, ent.s->s_aliases[i])) return 1; + } + } + } + else if (which == SEL_NUMBER) + { + /* N.B. for SEL_NUMBER, protocol is sent in name variable */ + if ((name != NULL) && (string_not_equal(name, ent.s->s_proto))) return 0; + if (num == ent.s->s_port) return 1; + } + return 0; + } + case CATEGORY_PROTOCOL: + { + if (which == SEL_NAME) + { + if (string_equal(name, ent.p->p_name)) return 1; + if (ent.p->p_aliases != NULL) + { + for (i = 0; ent.p->p_aliases[i] != NULL; i++) + { + if (string_equal(name, ent.p->p_aliases[i])) return 1; + } + } + } + else if (which == SEL_NUMBER) + { + if (num == ent.p->p_proto) return 1; + } + return 0; + } + case CATEGORY_RPC: + { + if (which == SEL_NAME) + { + if (string_equal(name, ent.r->r_name)) return 1; + if (ent.r->r_aliases != NULL) + { + for (i = 0; ent.r->r_aliases[i] != NULL; i++) + { + if (string_equal(name, ent.r->r_aliases[i])) return 1; + } + } + } + else if (which == SEL_NUMBER) + { + if (num == ent.r->r_number) return 1; + } + return 0; + } + case CATEGORY_FS: + { + if ((which == SEL_NAME) && (string_equal(name, ent.f->fs_spec))) return 1; + if ((which == SEL_NUMBER) && (string_equal(name, ent.f->fs_file))) return 1; + return 0; + } + case CATEGORY_MAC: + { + if ((which == SEL_NAME) && (string_equal(name, ent.m->host))) return 1; + if ((which == SEL_NUMBER) && (string_equal(name, ent.m->mac))) return 1; + return 0; + } + default: return 0; + } + + return 0; +} + +__private_extern__ int +si_item_is_valid(si_item_t *item) +{ + si_mod_t *si; + + if (item == NULL) return 0; + + si = item->src; + + if (si == NULL) return 0; + if (si->sim_is_valid == NULL) return 0; + + return si->sim_is_valid(si, item); +} + +__private_extern__ si_item_t * +si_user_byname(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_user_byname == NULL) return NULL; + return si->sim_user_byname(si, name); +} + +__private_extern__ si_item_t * +si_user_byuid(si_mod_t *si, uid_t uid) +{ + if (si == NULL) return NULL; + if (si->sim_user_byuid == NULL) return NULL; + return si->sim_user_byuid(si, uid); +} + +__private_extern__ si_list_t * +si_user_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_user_all == NULL) return NULL; + return si->sim_user_all(si); +} + +__private_extern__ si_item_t * +si_group_byname(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_group_byname == NULL) return NULL; + return si->sim_group_byname(si, name); +} + +__private_extern__ si_item_t * +si_group_bygid(si_mod_t *si, gid_t gid) +{ + if (si == NULL) return NULL; + if (si->sim_group_bygid == NULL) return NULL; + return si->sim_group_bygid(si, gid); +} + +__private_extern__ si_list_t * +si_group_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_group_all == NULL) return NULL; + return si->sim_group_all(si); +} + +__private_extern__ si_item_t * +si_grouplist(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_grouplist == NULL) return NULL; + return si->sim_grouplist(si, name); +} + +__private_extern__ si_list_t * +si_netgroup_byname(struct si_mod_s *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_netgroup_byname == NULL) return NULL; + return si->sim_netgroup_byname(si, name); +} + +__private_extern__ int +si_in_netgroup(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain) +{ + if (si == NULL) return 0; + if (si->sim_in_netgroup == NULL) return 0; + return si->sim_in_netgroup(si, name, host, user, domain); +} + +__private_extern__ si_item_t * +si_alias_byname(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_alias_byname == NULL) return NULL; + return si->sim_alias_byname(si, name); +} + +__private_extern__ si_list_t * +si_alias_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_alias_all == NULL) return NULL; + return si->sim_alias_all(si); +} + +__private_extern__ si_item_t * +si_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err) +{ + if (si == NULL) return NULL; + if (si->sim_host_byname == NULL) return NULL; + return si->sim_host_byname(si, name, af, err); +} + +__private_extern__ si_item_t * +si_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err) +{ + if (si == NULL) return NULL; + if (si->sim_host_byaddr == NULL) return NULL; + return si->sim_host_byaddr(si, addr, af, err); +} + +__private_extern__ si_list_t * +si_host_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_host_all == NULL) return NULL; + return si->sim_host_all(si); +} + +__private_extern__ si_item_t * +si_mac_byname(struct si_mod_s *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_mac_byname == NULL) return NULL; + return si->sim_mac_byname(si, name); +} + +__private_extern__ si_item_t * +si_mac_bymac(struct si_mod_s *si, const char *mac) +{ + if (si == NULL) return NULL; + if (si->sim_mac_bymac == NULL) return NULL; + return si->sim_mac_bymac(si, mac); +} + +__private_extern__ si_list_t * +si_mac_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_mac_all == NULL) return NULL; + return si->sim_mac_all(si); +} + +__private_extern__ si_item_t * +si_network_byname(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_network_byname == NULL) return NULL; + return si->sim_network_byname(si, name); +} + +__private_extern__ si_item_t * +si_network_byaddr(si_mod_t *si, uint32_t addr) +{ + if (si == NULL) return NULL; + if (si->sim_network_byaddr == NULL) return NULL; + return si->sim_network_byaddr(si, addr); +} + +__private_extern__ si_list_t * +si_network_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_network_all == NULL) return NULL; + return si->sim_network_all(si); +} + +__private_extern__ si_item_t * +si_service_byname(si_mod_t *si, const char *name, const char *proto) +{ + if (si == NULL) return NULL; + if (si->sim_service_byname == NULL) return NULL; + return si->sim_service_byname(si, name, proto); +} + +__private_extern__ si_item_t * +si_service_byport(si_mod_t *si, int port, const char *proto) +{ + if (si == NULL) return NULL; + if (si->sim_service_byport == NULL) return NULL; + return si->sim_service_byport(si, port, proto); +} + +__private_extern__ si_list_t * +si_service_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_service_all == NULL) return NULL; + return si->sim_service_all(si); +} + +__private_extern__ si_item_t * +si_protocol_byname(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_protocol_byname == NULL) return NULL; + return si->sim_protocol_byname(si, name); +} + +__private_extern__ si_item_t * +si_protocol_bynumber(si_mod_t *si, uint32_t number) +{ + if (si == NULL) return NULL; + if (si->sim_protocol_bynumber == NULL) return NULL; + return si->sim_protocol_bynumber(si, number); +} + +__private_extern__ si_list_t * +si_protocol_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_protocol_all == NULL) return NULL; + return si->sim_protocol_all(si); +} + +__private_extern__ si_item_t * +si_rpc_byname(si_mod_t *si, const char *name) +{ + if (si == NULL) return NULL; + if (si->sim_rpc_byname == NULL) return NULL; + return si->sim_rpc_byname(si, name); +} + +__private_extern__ si_item_t * +si_rpc_bynumber(si_mod_t *si, int number) +{ + if (si == NULL) return NULL; + if (si->sim_rpc_bynumber == NULL) return NULL; + return si->sim_rpc_bynumber(si, number); +} + +__private_extern__ si_list_t * +si_rpc_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_rpc_all == NULL) return NULL; + return si->sim_rpc_all(si); +} + +__private_extern__ si_item_t * +si_fs_byspec(si_mod_t *si, const char *spec) +{ + if (si == NULL) return NULL; + if (si->sim_fs_byspec == NULL) return NULL; + return si->sim_fs_byspec(si, spec); +} + +__private_extern__ si_item_t * +si_fs_byfile(si_mod_t *si, const char *file) +{ + if (si == NULL) return NULL; + if (si->sim_fs_byfile == NULL) return NULL; + return si->sim_fs_byfile(si, file); +} + +__private_extern__ si_list_t * +si_fs_all(si_mod_t *si) +{ + if (si == NULL) return NULL; + if (si->sim_fs_all == NULL) return NULL; + return si->sim_fs_all(si); +} + +__private_extern__ si_item_t * +si_item_call(struct si_mod_s *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t *err) +{ + if (si == NULL) return NULL; + + switch (call) + { + case SI_CALL_USER_BYNAME: return si_user_byname(si, str1); + case SI_CALL_USER_BYUID: return si_user_byuid(si, (uid_t)num1); + case SI_CALL_GROUP_BYNAME: return si_group_byname(si, str1); + case SI_CALL_GROUP_BYGID: return si_group_bygid(si, (gid_t)num1); + case SI_CALL_GROUPLIST: return si_grouplist(si, str1); + case SI_CALL_ALIAS_BYNAME: return si_alias_byname(si, str1); + case SI_CALL_HOST_BYNAME: return si_host_byname(si, str1, num1, err); + case SI_CALL_HOST_BYADDR: return si_host_byaddr(si, (void *)str1, num1, err); + case SI_CALL_NETWORK_BYNAME: return si_network_byname(si, str1); + case SI_CALL_NETWORK_BYADDR: return si_network_byaddr(si, num1); + case SI_CALL_SERVICE_BYNAME: return si_service_byname(si, str1, str2); + case SI_CALL_SERVICE_BYPORT: return si_service_byport(si, num1, str2); + case SI_CALL_PROTOCOL_BYNAME: return si_protocol_byname(si, str1); + case SI_CALL_PROTOCOL_BYNUMBER: return si_protocol_bynumber(si, num1); + case SI_CALL_RPC_BYNAME: return si_network_byname(si, str1); + case SI_CALL_RPC_BYNUMBER: return si_rpc_bynumber(si, num1); + case SI_CALL_FS_BYSPEC: return si_fs_byspec(si, str1); + case SI_CALL_FS_BYFILE: return si_fs_byfile(si, str1); + case SI_CALL_NAMEINFO: return si_nameinfo(si, (const struct sockaddr *)str1, num1, err); + case SI_CALL_IPNODE_BYNAME: return si_ipnode_byname(si, (const char *)str1, num1, num2, err); + case SI_CALL_MAC_BYNAME: return si_mac_byname(si, (const char *)str1); + case SI_CALL_MAC_BYMAC: return si_mac_bymac(si, (const char *)str1); + + /* Support for DNS async calls */ + case SI_CALL_DNS_QUERY: + case SI_CALL_DNS_SEARCH: + { + if (si->sim_item_call == NULL) return NULL; + return si->sim_item_call(si, call, str1, str2, num1, num2, err); + } + + default: return NULL; + } + + return NULL; +} + +__private_extern__ si_list_t * +si_list_call(struct si_mod_s *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, uint32_t *err) +{ + if (si == NULL) return NULL; + + switch (call) + { + case SI_CALL_USER_ALL: return si_user_all(si); + case SI_CALL_GROUP_ALL: return si_group_all(si); + case SI_CALL_ALIAS_ALL: return si_alias_all(si); + case SI_CALL_HOST_ALL: return si_host_all(si); + case SI_CALL_NETWORK_ALL: return si_network_all(si); + case SI_CALL_SERVICE_ALL: return si_service_all(si); + case SI_CALL_PROTOCOL_ALL: return si_protocol_all(si); + case SI_CALL_RPC_ALL: return si_rpc_all(si); + case SI_CALL_FS_ALL: return si_fs_all(si); + case SI_CALL_MAC_ALL: return si_mac_all(si); + case SI_CALL_ADDRINFO: return si_addrinfo(si, str1, str2, num1, num2, num3, num4, err); + default: return NULL; + } + + return NULL; +} + +static void +si_async_worklist_add_unit(si_async_workunit_t *r) +{ + pthread_mutex_lock(&module_mutex); + r->next = si_async_worklist; + si_async_worklist = r; + pthread_mutex_unlock(&module_mutex); +} + +static void +si_async_worklist_remove_unit(si_async_workunit_t *r) +{ + si_async_workunit_t *x; + + pthread_mutex_lock(&module_mutex); + if (si_async_worklist == r) + { + si_async_worklist = r->next; + } + else + { + for (x = si_async_worklist; (x != NULL) && (x->next != r); x = x->next) {;} + if (x != NULL) x->next = r->next; + } + pthread_mutex_unlock(&module_mutex); +} + +static si_async_workunit_t* +si_async_worklist_find_unit(mach_port_t p) +{ + si_async_workunit_t *r; + + pthread_mutex_lock(&module_mutex); + for (r = si_async_worklist; (r != NULL) && (r->port != p); r = r->next) {;} + pthread_mutex_unlock(&module_mutex); + + return r; +} + +static si_async_workunit_t * +si_async_workunit_create(si_mod_t *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, void *callback, void *context) +{ + si_async_workunit_t *r; + kern_return_t status; + mach_port_t reply, send; + mach_msg_type_name_t type; + char *s1, *s2; + + s1 = NULL; + s2 = NULL; + + if (si_call_str1_is_buffer(call)) + { + if (num3 > 0) + { + s1 = calloc(1, num3); + if (s1 == NULL) return NULL; + memcpy(s1, str1, num3); + } + } + else if (str1 != NULL) + { + s1 = strdup(str1); + if (s1 == NULL) return NULL; + } + + if (str2 != NULL) + { + s2 = strdup(str2); + if (s2 == NULL) + { + if (s1 != NULL) free(s1); + return NULL; + } + } + + r = (si_async_workunit_t *)calloc(1, sizeof(si_async_workunit_t)); + if (r == NULL) + { + if (s1 != NULL) free(s1); + if (s2 != NULL) free(s2); + return NULL; + } + + reply = MACH_PORT_NULL; + send = MACH_PORT_NULL; + type = 0; + + status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &reply); + if (status == KERN_SUCCESS) status = mach_port_extract_right(mach_task_self(), reply, MACH_MSG_TYPE_MAKE_SEND_ONCE, &send, &type); + if (status != KERN_SUCCESS) + { + if (reply != MACH_PORT_NULL) mach_port_mod_refs(mach_task_self(), reply, MACH_PORT_RIGHT_RECEIVE, -1); + if (s1 != NULL) free(s1); + if (s2 != NULL) free(s2); + free(r); + return NULL; + } + + r->si = si; + r->call = call; + r->str1 = s1; + r->str2 = s2; + r->num1 = num1; + r->num2 = num2; + r->num3 = num3; + r->num4 = num4; + + r->flags = WORKUNIT_CALL_ACTIVE | WORKUNIT_THREAD_ACTIVE; + if (si_call_returns_list(call)) r->flags |= WORKUNIT_RETURNS_LIST; + + r->callback = callback; + r->context = context; + r->port = reply; + r->send = send; + + si_async_worklist_add_unit(r); + + return r; +} + +static void +si_async_workunit_release(si_async_workunit_t *r) +{ + if (r == NULL) return; + + if (r->flags & (WORKUNIT_THREAD_ACTIVE | WORKUNIT_CALL_ACTIVE)) return; + + si_async_worklist_remove_unit(r); + + if (r->resitem != NULL) si_item_release(r->resitem); + if (r->reslist != NULL) si_list_release(r->reslist); + + if (r->str1 != NULL) free(r->str1); + if (r->str2 != NULL) free(r->str2); + + free(r); +} + +static void * +si_async_launchpad(void *x) +{ + si_async_workunit_t *r; + kern_return_t status; + mach_msg_empty_send_t msg; + + if (x == NULL) pthread_exit(NULL); + r = (si_async_workunit_t *)x; + + if (r->flags & WORKUNIT_RETURNS_LIST) r->reslist = si_list_call(r->si, r->call, r->str1, r->str2, r->num1, r->num2, r->num3, r->num4, &(r->err)); + else r->resitem = si_item_call(r->si, r->call, r->str1, r->str2, r->num1, r->num2, &(r->err)); + + memset(&msg, 0, sizeof(mach_msg_empty_send_t)); + + msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSGH_BITS_ZERO); + msg.header.msgh_remote_port = r->send; + msg.header.msgh_local_port = MACH_PORT_NULL; + msg.header.msgh_size = sizeof(mach_msg_empty_send_t); + msg.header.msgh_id = r->call; + + OSAtomicAnd32Barrier(~WORKUNIT_THREAD_ACTIVE, &r->flags); + + si_async_workunit_release(r); + + status = mach_msg(&(msg.header), MACH_SEND_MSG, msg.header.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (status != MACH_MSG_SUCCESS) + { + /* receiver failed - clean up to avoid a port leak */ + mach_msg_destroy(&(msg.header)); + } + + pthread_exit(NULL); + + /* UNREACHED */ + return NULL; +} + +mach_port_t +si_async_call(struct si_mod_s *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, void *callback, void *context) +{ + si_async_workunit_t *req; + pthread_attr_t attr; + pthread_t t; + + if (si == NULL) return MACH_PORT_NULL; + if (callback == NULL) return MACH_PORT_NULL; + + /* if module does async on it's own, hand off the call */ + if (si->sim_async_call != NULL) + { + return si->sim_async_call(si, call, str1, str2, num1, num2, num3, num4, callback, context); + } + + req = si_async_workunit_create(si, call, str1, str2, num1, num2, num3, num4, callback, context); + if (req == NULL) return MACH_PORT_NULL; + + /* start a new thread to do the work */ + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&t, &attr, si_async_launchpad, req); + pthread_attr_destroy(&attr); + + return req->port; +} + +void +si_async_cancel(mach_port_t p) +{ + si_async_workunit_t *r; + + r = si_async_worklist_find_unit(p); + if (r == NULL) return; + + OSAtomicAnd32Barrier(~WORKUNIT_CALL_ACTIVE, &r->flags); + + if (r->callback != NULL) + { + if (r->flags & WORKUNIT_RETURNS_LIST) ((list_async_callback)(r->callback))(NULL, SI_STATUS_CALL_CANCELLED, r->context); + else ((item_async_callback)(r->callback))(NULL, SI_STATUS_CALL_CANCELLED, r->context); + } + + si_async_workunit_release(r); + + mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1); +} + +void +si_async_handle_reply(mach_msg_header_t *msg) +{ + si_async_workunit_t *r; + mach_port_t reply = msg->msgh_local_port; + + r = si_async_worklist_find_unit(reply); + if (r == NULL) + { +#ifdef CALL_TRACE + fprintf(stderr, "** %s can't find worklist item\n", __func__); +#endif + return; + } + + if (r->flags & WORKUNIT_THREAD_ACTIVE) + { +#ifdef CALL_TRACE + fprintf(stderr, "** %s workunit thread is still active\n", __func__); +#endif + return; + } + + if (r->callback != NULL) + { + if (r->flags & WORKUNIT_RETURNS_LIST) ((list_async_callback)(r->callback))(r->reslist, r->err, r->context); + else ((item_async_callback)(r->callback))(r->resitem, r->err, r->context); + + r->reslist = NULL; + r->resitem = NULL; + } + else + { +#ifdef CALL_TRACE + fprintf(stderr, "** %s workunit has no callback\n", __func__); +#endif + } + + OSAtomicAnd32Barrier(~WORKUNIT_CALL_ACTIVE, &r->flags); + + si_async_workunit_release(r); + + mach_port_mod_refs(mach_task_self(), reply, MACH_PORT_RIGHT_RECEIVE, -1); +} + +__private_extern__ char * +si_canonical_mac_address(const char *addr) +{ + char e[6][3]; + char *out; + struct ether_addr *ether; + int i, bit; + + if (addr == NULL) return NULL; + + /* ether_aton isn't thread-safe */ + pthread_mutex_lock(&module_mutex); + + ether = ether_aton(addr); + if (ether == NULL) + { + pthread_mutex_unlock(&module_mutex); + return NULL; + } + + for (i = 0, bit = 1; i < 6; i++, bit *= 2) + { + if ((i & bit) && (ether->ether_addr_octet[i] <= 15)) + { + sprintf(e[i], "0%x", ether->ether_addr_octet[i]); + } + else + { + sprintf(e[i], "%x", ether->ether_addr_octet[i]); + } + } + + pthread_mutex_unlock(&module_mutex); + + out = NULL; + asprintf(&out, "%s:%s:%s:%s:%s:%s", e[0], e[1], e[2], e[3], e[4], e[5]); + return out; +} diff --git a/lookup.subproj/si_module.h b/lookup.subproj/si_module.h new file mode 100644 index 0000000..a8e1c34 --- /dev/null +++ b/lookup.subproj/si_module.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2008-2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef __SI_MODULE_H__ +#define __SI_MODULE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define forever for(;;) +#define string_equal(A,B) (strcmp(A,B)==0) +#define string_not_equal(A,B) (strcmp(A,B)!=0) + +#define SI_CALL_USER_BYNAME 0 +#define SI_CALL_USER_BYUID 1 +#define SI_CALL_USER_ALL 2 +#define SI_CALL_GROUP_BYNAME 3 +#define SI_CALL_GROUP_BYGID 4 +#define SI_CALL_GROUP_ALL 5 +#define SI_CALL_NETGROUP_BYNAME 6 +#define SI_CALL_IN_NETGROUP 7 +#define SI_CALL_GROUPLIST 8 +#define SI_CALL_ALIAS_BYNAME 9 +#define SI_CALL_ALIAS_ALL 10 +#define SI_CALL_HOST_BYNAME 11 +#define SI_CALL_HOST_BYADDR 12 +#define SI_CALL_HOST_ALL 13 +#define SI_CALL_NETWORK_BYNAME 14 +#define SI_CALL_NETWORK_BYADDR 15 +#define SI_CALL_NETWORK_ALL 16 +#define SI_CALL_SERVICE_BYNAME 17 +#define SI_CALL_SERVICE_BYPORT 18 +#define SI_CALL_SERVICE_ALL 19 +#define SI_CALL_PROTOCOL_BYNAME 20 +#define SI_CALL_PROTOCOL_BYNUMBER 21 +#define SI_CALL_PROTOCOL_ALL 22 +#define SI_CALL_RPC_BYNAME 23 +#define SI_CALL_RPC_BYNUMBER 24 +#define SI_CALL_RPC_ALL 25 +#define SI_CALL_FS_BYSPEC 26 +#define SI_CALL_FS_BYFILE 27 +#define SI_CALL_FS_ALL 28 +#define SI_CALL_ADDRINFO 29 +#define SI_CALL_NAMEINFO 30 +#define SI_CALL_IPNODE_BYNAME 31 +#define SI_CALL_MAC_BYNAME 32 +#define SI_CALL_MAC_BYMAC 33 +#define SI_CALL_MAC_ALL 34 +#define SI_CALL_DNS_QUERY 35 +#define SI_CALL_DNS_SEARCH 36 + +#define si_call_returns_list(A) \ +((A==SI_CALL_USER_ALL)||(A==SI_CALL_GROUP_ALL)||(A==SI_CALL_HOST_ALL)||(A==SI_CALL_NETWORK_ALL)||\ + (A==SI_CALL_SERVICE_ALL)||(A==SI_CALL_PROTOCOL_ALL)||(A==SI_CALL_RPC_ALL)||(A==SI_CALL_FS_ALL)||\ + (A==SI_CALL_ALIAS_ALL)||(A==SI_CALL_NETGROUP_BYNAME)||(A==SI_CALL_ADDRINFO)||(A==SI_CALL_MAC_ALL)) + +#define si_call_str1_is_buffer(A) \ +((A==SI_CALL_HOST_BYADDR)||(A==SI_CALL_NAMEINFO)) + +#define CATEGORY_USER 0 +#define CATEGORY_GROUP 1 +#define CATEGORY_GROUPLIST 2 +#define CATEGORY_NETGROUP 3 +#define CATEGORY_ALIAS 4 +#define CATEGORY_HOST_IPV4 5 +#define CATEGORY_HOST_IPV6 6 +#define CATEGORY_NETWORK 7 +#define CATEGORY_SERVICE 8 +#define CATEGORY_PROTOCOL 9 +#define CATEGORY_RPC 10 +#define CATEGORY_FS 11 +#define CATEGORY_MAC 12 +#define CATEGORY_NAMEINFO 13 +#define CATEGORY_ADDRINFO 14 +#define CATEGORY_DNSPACKET 15 +#define CATEGORY_SRV 16 +#define CATEGORY_COUNT 17 + +/* convenience */ +#define CATEGORY_HOST CATEGORY_HOST_IPV4 + +#define SEL_ALL 0 +#define SEL_NAME 1 +#define SEL_NUMBER 2 + +/* host, getaddrinfo, and getnameinfo status codes */ +#define SI_STATUS_NO_ERROR 0 +#define SI_STATUS_H_ERRNO_HOST_NOT_FOUND 1 +#define SI_STATUS_H_ERRNO_TRY_AGAIN 2 +#define SI_STATUS_H_ERRNO_NO_RECOVERY 3 +#define SI_STATUS_H_ERRNO_NO_DATA 4 +#define SI_STATUS_INTERNAL 10 +#define SI_STATUS_WORKITEM_NOT_FOUND 11 +#define SI_STATUS_RETURNS_ITEM 12 +#define SI_STATUS_RETURNS_LIST 13 +#define SI_STATUS_CALL_IN_PROGRESS 14 +#define SI_STATUS_CALL_CANCELLED 15 +#define SI_STATUS_EAI_PLUS_100 100 +#define SI_STATUS_EAI_ADDRFAMILY 101 +#define SI_STATUS_EAI_AGAIN 102 +#define SI_STATUS_EAI_BADFLAGS 103 +#define SI_STATUS_EAI_FAIL 104 +#define SI_STATUS_EAI_FAMILY 105 +#define SI_STATUS_EAI_MEMORY 106 +#define SI_STATUS_EAI_NODATA 107 +#define SI_STATUS_EAI_NONAME 108 +#define SI_STATUS_EAI_SERVICE 109 +#define SI_STATUS_EAI_SOCKTYPE 110 +#define SI_STATUS_EAI_SYSTEM 111 +#define SI_STATUS_EAI_BADHINTS 112 +#define SI_STATUS_EAI_PROTOCOL 113 +#define SI_STATUS_EAI_OVERFLOW 114 +#define SI_STATUS_ERRNO_PLUS_200 200 + +typedef void (*item_async_callback)(si_item_t *, uint32_t, void *); +typedef void (*list_async_callback)(si_list_t *, uint32_t, void *); + +typedef struct grouplist_s +{ + char *gl_user; + gid_t gl_basegid; + int gl_count; + gid_t **gl_gid; +} si_grouplist_t; + +typedef struct addrinfo_s +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + uint32_t ai_addrlen; + socket_data_t ai_addr; + char *ai_canonname; +} si_addrinfo_t; + +typedef struct nameinfo_s +{ + char *ni_node; + char *ni_serv; +} si_nameinfo_t; + +typedef struct mac_s +{ + char *host; + char *mac; +} si_mac_t; + +typedef struct netgrent_s +{ + char *ng_host; + char *ng_user; + char *ng_domain; +} si_netgrent_t; + +typedef struct dnspacket_s +{ + int dns_packet_len; + char *dns_packet; + int dns_server_len; + struct sockaddr *dns_server; +} si_dnspacket_t; + +typedef struct si_srv_s { + uint16_t priority; + uint16_t weight; + uint16_t port; + char *target; +} si_srv_t; + +typedef struct si_mod_s +{ + char *name; + uint32_t vers; + int32_t refcount; + + void *bundle; + void *private; + + void (*sim_close)(struct si_mod_s *si); + + int (*sim_is_valid)(struct si_mod_s *si, si_item_t *item); + + si_item_t *(*sim_user_byname)(struct si_mod_s *si, const char *name); + si_item_t *(*sim_user_byuid)(struct si_mod_s *si, uid_t uid); + si_list_t *(*sim_user_all)(struct si_mod_s *si); + + si_item_t *(*sim_group_byname)(struct si_mod_s *si, const char *name); + si_item_t *(*sim_group_bygid)(struct si_mod_s *si, gid_t gid); + si_list_t *(*sim_group_all)(struct si_mod_s *si); + + si_item_t *(*sim_grouplist)(struct si_mod_s *si, const char *name); + + si_list_t *(*sim_netgroup_byname)(struct si_mod_s *si, const char *name); + int (*sim_in_netgroup)(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain); + + si_item_t *(*sim_alias_byname)(struct si_mod_s *si, const char *name); + si_list_t *(*sim_alias_all)(struct si_mod_s *si); + + si_item_t *(*sim_host_byname)(struct si_mod_s *si, const char *name, int af, uint32_t *err); + si_item_t *(*sim_host_byaddr)(struct si_mod_s *si, const void *addr, int af, uint32_t *err); + si_list_t *(*sim_host_all)(struct si_mod_s *si); + + si_item_t *(*sim_network_byname)(struct si_mod_s *si, const char *name); + si_item_t *(*sim_network_byaddr)(struct si_mod_s *si, uint32_t addr); + si_list_t *(*sim_network_all)(struct si_mod_s *si); + + si_item_t *(*sim_service_byname)(struct si_mod_s *si, const char *name, const char *proto); + si_item_t *(*sim_service_byport)(struct si_mod_s *si, int port, const char *proto); + si_list_t *(*sim_service_all)(struct si_mod_s *si); + + si_item_t *(*sim_protocol_byname)(struct si_mod_s *si, const char *name); + si_item_t *(*sim_protocol_bynumber)(struct si_mod_s *si, int number); + si_list_t *(*sim_protocol_all)(struct si_mod_s *si); + + si_item_t *(*sim_rpc_byname)(struct si_mod_s *si, const char *name); + si_item_t *(*sim_rpc_bynumber)(struct si_mod_s *si, int number); + si_list_t *(*sim_rpc_all)(struct si_mod_s *si); + + si_item_t *(*sim_fs_byspec)(struct si_mod_s *si, const char *spec); + si_item_t *(*sim_fs_byfile)(struct si_mod_s *si, const char *file); + si_list_t *(*sim_fs_all)(struct si_mod_s *si); + + si_item_t *(*sim_mac_byname)(struct si_mod_s *si, const char *name); + si_item_t *(*sim_mac_bymac)(struct si_mod_s *si, const char *mac); + si_list_t *(*sim_mac_all)(struct si_mod_s *si); + + si_list_t *(*sim_addrinfo)(struct si_mod_s *si, const void *node, const void *serv, uint32_t family, uint32_t socktype, uint32_t protocol, uint32_t flags, uint32_t *err); + int (*sim_wants_addrinfo)(struct si_mod_s *si); + + si_item_t *(*sim_nameinfo)(struct si_mod_s *si, const struct sockaddr *sa, int flags, uint32_t *err); + + si_list_t *(*sim_srv_byname)(struct si_mod_s *si, const char *qname, uint32_t *err); + + si_item_t *(*sim_item_call)(struct si_mod_s *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t *err); + si_list_t *(*sim_list_call)(struct si_mod_s *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, uint32_t *err); + + mach_port_t (*sim_async_call)(struct si_mod_s *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, void *callback, void *context); + void (*sim_async_cancel)(mach_port_t p); + void (*sim_async_handle_reply)(mach_msg_header_t *msg); +} si_mod_t; + +si_mod_t *si_module_with_name(const char *name); +__private_extern__ si_mod_t *si_module_with_path(const char *path, const char *name); +__private_extern__ si_mod_t *si_module_retain(si_mod_t *si); +void si_module_release(si_mod_t *si); +__private_extern__ const char *si_module_name(si_mod_t *si); +__private_extern__ int si_module_vers(si_mod_t *si); + +si_mod_t *si_search(void); + +__private_extern__ int si_item_match(si_item_t *item, int cat, const void *name, uint32_t num, int which); +__private_extern__ int si_item_is_valid(si_item_t *item); + +__private_extern__ si_item_t *si_user_byname(si_mod_t *si, const char *name); +__private_extern__ si_item_t *si_user_byuid(si_mod_t *si, uid_t uid); +__private_extern__ si_list_t *si_user_all(si_mod_t *si); + +__private_extern__ si_item_t *si_group_byname(si_mod_t *si, const char *name); +__private_extern__ si_item_t *si_group_bygid(si_mod_t *si, gid_t gid); +__private_extern__ si_list_t *si_group_all(si_mod_t *si); + +__private_extern__ si_item_t *si_grouplist(si_mod_t *si, const char *name); + +__private_extern__ int si_in_netgroup(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain); +__private_extern__ si_list_t *si_netgroup_byname(struct si_mod_s *si, const char *name); + +__private_extern__ si_item_t *si_alias_byname(struct si_mod_s *si, const char *name); +__private_extern__ si_list_t *si_alias_all(struct si_mod_s *si); + +__private_extern__ si_item_t *si_host_byname(si_mod_t *si, const char *name, int af, uint32_t *err); +__private_extern__ si_item_t *si_host_byaddr(si_mod_t *si, const void *addr, int af, uint32_t *err); +__private_extern__ si_list_t *si_host_all(si_mod_t *si); + +__private_extern__ si_item_t *si_mac_byname(struct si_mod_s *si, const char *name); +__private_extern__ si_item_t *si_mac_bymac(struct si_mod_s *si, const char *mac); +__private_extern__ si_list_t *si_mac_all(struct si_mod_s *si); + +__private_extern__ si_item_t *si_network_byname(si_mod_t *si, const char *name); +__private_extern__ si_item_t *si_network_byaddr(si_mod_t *si, uint32_t addr); +__private_extern__ si_list_t *si_network_all(si_mod_t *si); + +__private_extern__ si_item_t *si_service_byname(si_mod_t *si, const char *name, const char *proto); +__private_extern__ si_item_t *si_service_byport(si_mod_t *si, int port, const char *proto); +__private_extern__ si_list_t *si_service_all(si_mod_t *si); + +__private_extern__ si_item_t *si_protocol_byname(si_mod_t *si, const char *name); +__private_extern__ si_item_t *si_protocol_bynumber(si_mod_t *si, uint32_t number); +__private_extern__ si_list_t *si_protocol_all(si_mod_t *si); + +__private_extern__ si_item_t *si_rpc_byname(si_mod_t *si, const char *name); +__private_extern__ si_item_t *si_rpc_bynumber(si_mod_t *si, int number); +__private_extern__ si_list_t *si_rpc_all(si_mod_t *si); + +__private_extern__ si_item_t *si_fs_byspec(si_mod_t *si, const char *spec); +__private_extern__ si_item_t *si_fs_byfile(si_mod_t *si, const char *file); +__private_extern__ si_list_t *si_fs_all(si_mod_t *si); + +__private_extern__ int si_wants_addrinfo(si_mod_t *s); +__private_extern__ si_list_t *si_addrinfo(si_mod_t *si, const char *node, const char *serv, uint32_t family, uint32_t socktype, uint32_t protocol, uint32_t flags, uint32_t *err); + +__private_extern__ si_item_t *si_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, uint32_t *err); +__private_extern__ si_item_t *si_ipnode_byname(si_mod_t *si, const char *name, int family, int flags, uint32_t *err); + +__private_extern__ si_list_t *si_srv_byname(si_mod_t *si, const char *qname, uint32_t *err); + +__private_extern__ si_item_t *si_item_call(si_mod_t *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t *err); +__private_extern__ si_list_t *si_list_call(si_mod_t *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, uint32_t *err); + +extern mach_port_t si_async_call(si_mod_t *si, int call, const char *str1, const char *str2, uint32_t num1, uint32_t num2, uint32_t num3, uint32_t num4, void *callback, void *context); +extern void si_async_cancel(mach_port_t p); +extern void si_async_handle_reply(mach_msg_header_t *msg); + +char *si_canonical_mac_address(const char *addr); +si_item_t *si_addrinfo_v4(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in_addr *addr, uint16_t iface, const char *cname); +si_item_t *si_addrinfo_v6(si_mod_t *si, int32_t flags, int32_t sock, int32_t proto, uint16_t port, struct in6_addr *addr, uint16_t iface, const char *cname); +si_list_t *si_addrinfo_list(si_mod_t *si, int socktype, int proto, struct in_addr *a4, struct in6_addr *a6, int port, int scopeid, const char *cname4, const char *cname6); +si_list_t *si_addrinfo_list_from_hostent(si_mod_t *si, uint32_t socktype, uint32_t proto, uint16_t port, uint16_t scope, const struct hostent *h4, const struct hostent *h6); + +int _gai_serv_to_port(const char *serv, uint32_t proto, uint16_t *port); + +#endif /* ! __SI_MODULE_H__ */ diff --git a/lookup.subproj/thread_data.c b/lookup.subproj/thread_data.c new file mode 100644 index 0000000..c29ce54 --- /dev/null +++ b/lookup.subproj/thread_data.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2008 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include + +static pthread_key_t _info_key = 0; +static int _info_key_ok = 0; +static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT; + +struct _li_data_s +{ + uint32_t icount; + uint32_t *ikey; + void **idata; +}; + +typedef struct +{ + si_item_t *thread_item; + si_list_t *thread_list; +} li_thread_data_t; + +static void +_LI_thread_info_free(void *x) +{ + li_thread_data_t *tdata; + + if (x == NULL) return; + + tdata = (li_thread_data_t *)x; + si_item_release(tdata->thread_item); + si_list_release(tdata->thread_list); + + free(tdata); +} + +static void +_LI_data_free(void *x) +{ + struct _li_data_s *t; + int i; + + if (x == NULL) return; + + t = (struct _li_data_s *)x; + + for (i = 0; i < t->icount; i++) + { + _LI_thread_info_free(t->idata[i]); + t->idata[i] = NULL; + } + + if (t->ikey != NULL) free(t->ikey); + t->ikey = NULL; + + if (t->idata != NULL) free(t->idata); + t->idata = NULL; + + free(t); +} + +static void +_LI_data_init() +{ + /* _info_key_ok is set to 1 if pthread_key_create succeeded */ + if (pthread_key_create(&_info_key, _LI_data_free) == 0) _info_key_ok = 1; + return; +} + +static struct _li_data_s * +_LI_data_get() +{ + struct _li_data_s *libinfo_data; + + /* only one thread should create the _info_key */ + pthread_once(&_info_key_initialized, _LI_data_init); + + /* no thread-specific data if pthread_key_create failed */ + if (_info_key_ok == 0) return NULL; + + /* Check if this thread already created libinfo_data */ + libinfo_data = pthread_getspecific(_info_key); + if (libinfo_data != NULL) return libinfo_data; + + libinfo_data = (struct _li_data_s *)calloc(1, sizeof(struct _li_data_s)); + if (libinfo_data == NULL) return NULL; + + pthread_setspecific(_info_key, libinfo_data); + return libinfo_data; +} + +static li_thread_data_t * +LI_get_thread_info(uint32_t key) +{ + struct _li_data_s *libinfo_data; + li_thread_data_t *tdata; + uint32_t i, n; + + libinfo_data = _LI_data_get(); + if (libinfo_data == NULL) return NULL; + + for (i = 0; i < libinfo_data->icount; i++) + { + if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i]; + } + + i = libinfo_data->icount; + n = i + 1; + + if (i == 0) + { + libinfo_data->ikey = (uint32_t *)malloc(sizeof(uint32_t)); + libinfo_data->idata = (void **)malloc(sizeof(void *)); + } + else + { + libinfo_data->ikey = (uint32_t *)reallocf(libinfo_data->ikey, n * sizeof(uint32_t)); + libinfo_data->idata = (void **)reallocf(libinfo_data->idata, n * sizeof(void *)); + } + + if ((libinfo_data->ikey == NULL) || (libinfo_data->idata == NULL)) + { + if (libinfo_data->ikey != NULL) free(libinfo_data->ikey); + libinfo_data->ikey = NULL; + + if (libinfo_data->idata != NULL) free(libinfo_data->idata); + libinfo_data->idata = NULL; + + return NULL; + } + + tdata = (li_thread_data_t *)calloc(1, sizeof(li_thread_data_t)); + if (tdata == NULL) return NULL; + + libinfo_data->ikey[i] = key; + libinfo_data->idata[i] = tdata; + libinfo_data->icount++; + + return tdata; +} + +__private_extern__ si_item_t * +LI_get_thread_item(uint32_t key) +{ + li_thread_data_t *tdata; + + tdata = LI_get_thread_info(key); + if (tdata == NULL) return NULL; + + return tdata->thread_item; +} + +__private_extern__ si_list_t * +LI_get_thread_list(uint32_t key) +{ + li_thread_data_t *tdata; + + tdata = LI_get_thread_info(key); + if (tdata == NULL) return NULL; + + return tdata->thread_list; +} + +__private_extern__ void +LI_set_thread_item(uint32_t key, si_item_t *item) +{ + li_thread_data_t *tdata; + + tdata = LI_get_thread_info(key); + if (tdata == NULL) return; + + si_item_release(tdata->thread_item); + tdata->thread_item = item; +} + +__private_extern__ void +LI_set_thread_list(uint32_t key, si_list_t *list) +{ + li_thread_data_t *tdata; + + tdata = LI_get_thread_info(key); + if (tdata == NULL) return; + + si_list_release(tdata->thread_list); + + si_list_reset(list); + tdata->thread_list = list; +} diff --git a/lookup.subproj/DSlibinfoMIG_types.h b/lookup.subproj/thread_data.h similarity index 56% rename from lookup.subproj/DSlibinfoMIG_types.h rename to lookup.subproj/thread_data.h index f6e0350..08dd022 100644 --- a/lookup.subproj/DSlibinfoMIG_types.h +++ b/lookup.subproj/thread_data.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2008 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -21,32 +21,14 @@ * @APPLE_LICENSE_HEADER_END@ */ -/*! - * @header DSlibinfoMIG_types.h - */ - -#ifndef __DSLIBINFOMIG_TYPES_H__ -#define __DSLIBINFOMIG_TYPES_H__ - -#ifndef kDSStdMachDSLookupPortName -#define kDSStdMachDSLookupPortName "com.apple.system.DirectoryService.libinfo_v1" -#endif - -#define MAX_MIG_INLINE_DATA 16384 - -typedef char *inline_data_t; -typedef char *proc_name_t; +#ifndef __THREAD_DATA_H__ +#define __THREAD_DATA_H__ -struct sLibinfoRequest -{ - mach_port_t fReplyPort; - int32_t fProcedure; - char *fBuffer; - int32_t fBufferLen; - mach_vm_address_t fCallbackAddr; - audit_token_t fToken; -}; +#include -extern boolean_t DSlibinfoMIGAsyncReply_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); +__private_extern__ si_item_t *LI_get_thread_item(uint32_t key); +__private_extern__ si_list_t *LI_get_thread_list(uint32_t key); +__private_extern__ void LI_set_thread_item(uint32_t key, si_item_t *item); +__private_extern__ void LI_set_thread_list(uint32_t key, si_list_t *list); -#endif /* __DSLIBINFOMIG_TYPES_H__ */ +#endif /* ! __THREAD_DATA_H__ */ diff --git a/membership.subproj/DSmemberdMIG.defs b/membership.subproj/DSmemberdMIG.defs deleted file mode 100644 index 3c5bf1a..0000000 --- a/membership.subproj/DSmemberdMIG.defs +++ /dev/null @@ -1 +0,0 @@ -#include <../include/DSmemberdMIG.defs> diff --git a/membership.subproj/Makefile b/membership.subproj/Makefile index 9f7473c..20b6836 100644 --- a/membership.subproj/Makefile +++ b/membership.subproj/Makefile @@ -1,49 +1,36 @@ -# -# Generated by the NeXT 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. -# +Project = membership +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES -NAME = membership - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component +PRODUCT = $(shell tconf --product) HFILES = membership.h membershipPriv.h ntsid.h CFILES = membership.c -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble DSmemberdMIG.defs \ - mbr_check_membership.3 mbr_uid_to_uuid.3 mbr_uid_to_uuid_so.3 - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -NEXTSTEP_INSTALLDIR = /Local/Developer/System -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - -PUBLIC_HEADERS = membership.h ntsid.h - +MANPAGES = mbr_check_membership.3 mbr_uid_to_uuid.3 -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 +ifeq ($(PRODUCT),MacOSX) +USERDEFS = /usr/local/include/DSmemberdMIG.defs +endif -include $(MAKEFILEDIR)/platform.make +Install_Headers = membership.h ntsid.h +Install_Private_Headers = membershipPriv.h --include Makefile.preamble +Extra_CC_Flags = -Wall -fno-common \ + -D__MigTypeCheck=1 -D__DARWIN_NON_CANCELABLE=1 +ifeq ($(PRODUCT),MacOSX) +Extra_CC_Flags += -DDS_AVAILABLE +endif -include $(MAKEFILEDIR)/$(MAKEFILE) +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make --include Makefile.postamble +after_install: + @for LINK in mbr_gid_to_uuid.3 mbr_sid_to_uuid.3 mbr_uuid_to_id.3 \ + mbr_uuid_to_sid.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/mbr_uid_to_uuid.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done --include Makefile.dependencies diff --git a/membership.subproj/Makefile.postamble b/membership.subproj/Makefile.postamble deleted file mode 100644 index f20fb6f..0000000 --- a/membership.subproj/Makefile.postamble +++ /dev/null @@ -1,11 +0,0 @@ -install-man-page: $(DSTROOT)/usr/share/man/man3 - install -d $(DSTROOT)/usr/share/man/man3 - install -c -m 644 mbr_check_membership.3 $(DSTROOT)/usr/share/man/man3 - install -c -m 644 mbr_uid_to_uuid.3 $(DSTROOT)/usr/share/man/man3 - install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_gid_to_uuid.3 - install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_sid_to_uuid.3 - install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_uuid_to_id.3 - install -c -m 644 mbr_uid_to_uuid_so.3 $(DSTROOT)/usr/share/man/man3/mbr_uuid_to_sid.3 - -$(DSTROOT)/usr/share/man/man3: - $(MKDIRS) $@ diff --git a/membership.subproj/Makefile.preamble b/membership.subproj/Makefile.preamble deleted file mode 100644 index c77ddea..0000000 --- a/membership.subproj/Makefile.preamble +++ /dev/null @@ -1,18 +0,0 @@ -AFTER_POSTINSTALL += install-man-page -OTHER_PRIVATE_HEADERS = membershipPriv.h - -# Enable MIG type checking -OTHER_CFLAGS += -D__MigTypeCheck=1 -D__DARWIN_NON_CANCELABLE=1 - -# Additional flags (MiG generated files) -DEFSFILES = DSmemberdMIG.defs -OTHER_OFILES = DSmemberdMIGUser.o - -BEFORE_INSTALLHDRS += $(SFILE_DIR) $(INTERNAL_HDRS) -# AFTER_INSTALLHDRS += mdns_hdrs -PRIVATE_HEADER_DIR = /usr/local/include - - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/membership.subproj/PB.project b/membership.subproj/PB.project deleted file mode 100644 index 3e5c151..0000000 --- a/membership.subproj/PB.project +++ /dev/null @@ -1,34 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = ( - membershipPriv.h, - ntsid.h - ); - OTHER_LINKED = (membership.c); - OTHER_SOURCES = ( - Makefile.preamble, - Makefile, - Makefile.postamble, - DSmemberdMIG.defs - ); - PRECOMPILED_HEADERS = (); - PROJECT_HEADERS = (); - PUBLIC_HEADERS = (membership.h, ntsid.h); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /bin/gnumake; - NEXTSTEP_INSTALLDIR = /Local/Developer/System; - 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 = lookup; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/membership.subproj/mbr_check_membership.3 b/membership.subproj/mbr_check_membership.3 index e268baa..5f947c3 100644 --- a/membership.subproj/mbr_check_membership.3 +++ b/membership.subproj/mbr_check_membership.3 @@ -42,7 +42,7 @@ tests if a given user is a member of a group, individually or as a member of a n .Fa ismember is set to 1 if the user is a member of the group, and 0 otherwise. .Pp -Users may belong to any number of grouos. +Users may belong to any number of groups. .Fn mbr_check_membership should be always be used to check group membership, rather than calling @@ -83,11 +83,11 @@ Note that does not test whether .Fa group exists or not. -Querying membership for a nonexistant group will result in +Querying membership for a nonexistent group will result in .Fa ismember being to 0 and a return value of 0. .Sh SEE ALSO .Xr setgroups 2 , .Xr getgroups 2 , .Xr mbr_uid_to_uuid 3 , -.Xr DirectoryService 8 \ No newline at end of file +.Xr DirectoryService 8 diff --git a/membership.subproj/mbr_uid_to_uuid.3 b/membership.subproj/mbr_uid_to_uuid.3 index 2e7aeec..96d8ae6 100644 --- a/membership.subproj/mbr_uid_to_uuid.3 +++ b/membership.subproj/mbr_uid_to_uuid.3 @@ -62,9 +62,15 @@ daemon. .Fn mbr_uid_to_uuid takes a uid and looks up the associated user account. It provides the the uuid for that user as an output parameter. +Note that this routine will succeed and return a fabricated uuid if the input user uid does not exist. +.Fn getpwuid +should be used to test for the existence of a uid. .Pp .Fn mbr_gid_to_uuid similarly gets the uuid associated with a group. +Note that this routine will succeed and return a fabricated uuid if the input group gid does not exist. +.Fn getgrgid +should be used to test for the existence of a gid. .Pp .Fn mbr_uuid_to_id takes a uuid that refers to a user or group and fetches the corresponding uid or gid. @@ -94,6 +100,11 @@ These functions return 0 on success, or EIO if communications with the .Xr DirectoryService 8 daemon fails. ENOENT is returned if the mapping can not be performed. +.Pp +.Fn mbr_gid_to_uuid +and +.Fn mbr_uid_to_uuid +return 0 (success), even if the user/group does not exist. .Sh SEE ALSO .Xr getpwuid 3 , .Xr getgrgid 3 , diff --git a/membership.subproj/mbr_uid_to_uuid_so.3 b/membership.subproj/mbr_uid_to_uuid_so.3 deleted file mode 100644 index af5c721..0000000 --- a/membership.subproj/mbr_uid_to_uuid_so.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/mbr_uid_to_uuid.3 diff --git a/membership.subproj/membership.c b/membership.subproj/membership.c index 83e1345..4d9edb9 100644 --- a/membership.subproj/membership.c +++ b/membership.subproj/membership.c @@ -20,23 +20,26 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include "membership.h" -#include "membershipPriv.h" -#include "DSmemberdMIG.h" -#include "DSmemberdMIG_types.h" +#include #include #include +#include "membership.h" +#include "membershipPriv.h" #include -#include #include +#ifdef DS_AVAILABLE +#include +#include +#endif - -extern mach_port_t _ds_port; +#ifdef DS_AVAILABLE +extern mach_port_t _mbr_port; extern int _ds_running(void); static const uint8_t _mbr_root_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00}; #define MAX_LOOKUP_ATTEMPTS 10 +#endif __private_extern__ uid_t audit_token_uid(audit_token_t a) @@ -48,6 +51,7 @@ audit_token_uid(audit_token_t a) return (uid_t)a.val[1]; } +#ifdef DS_AVAILABLE static int _mbr_MembershipCall(struct kauth_identity_extlookup *req) { @@ -56,18 +60,18 @@ _mbr_MembershipCall(struct kauth_identity_extlookup *req) uint32_t i; if (_ds_running() == 0) return EIO; - if (_ds_port == MACH_PORT_NULL) return EIO; + if (_mbr_port == MACH_PORT_NULL) return EIO; memset(&token, 0, sizeof(audit_token_t)); status = MIG_SERVER_DIED; - for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) + for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) { - status = memberdDSmig_MembershipCall(_ds_port, req, &token); + status = memberdDSmig_MembershipCall(_mbr_port, req, &token); if (status == MACH_SEND_INVALID_DEST) { - mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); - _ds_port = MACH_PORT_NULL; + mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1); + _mbr_port = MACH_PORT_NULL; _ds_running(); status = MIG_SERVER_DIED; } @@ -78,7 +82,9 @@ _mbr_MembershipCall(struct kauth_identity_extlookup *req) return 0; } +#endif +#ifdef DS_AVAILABLE static int _mbr_MapName(char *name, int type, guid_t *uu) { @@ -90,20 +96,20 @@ _mbr_MapName(char *name, int type, guid_t *uu) if (strlen(name) > 255) return EINVAL; if (_ds_running() == 0) return EIO; - if (_ds_port == MACH_PORT_NULL) return EIO; + if (_mbr_port == MACH_PORT_NULL) return EIO; memset(&token, 0, sizeof(audit_token_t)); status = MIG_SERVER_DIED; - for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) + for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) { - status = memberdDSmig_MapName(_ds_port, type, name, uu, &token); + status = memberdDSmig_MapName(_mbr_port, type, name, uu, &token); if (status == KERN_FAILURE) return ENOENT; if (status == MACH_SEND_INVALID_DEST) { - mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); - _ds_port = MACH_PORT_NULL; + mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1); + _mbr_port = MACH_PORT_NULL; _ds_running(); status = MIG_SERVER_DIED; } @@ -114,7 +120,9 @@ _mbr_MapName(char *name, int type, guid_t *uu) return 0; } +#endif +#ifdef DS_AVAILABLE static int _mbr_ClearCache() { @@ -122,16 +130,16 @@ _mbr_ClearCache() uint32_t i; if (_ds_running() == 0) return EIO; - if (_ds_port == MACH_PORT_NULL) return EIO; + if (_mbr_port == MACH_PORT_NULL) return EIO; status = MIG_SERVER_DIED; - for (i = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) + for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) { - status = memberdDSmig_ClearCache(_ds_port); + status = memberdDSmig_ClearCache(_mbr_port); if (status == MACH_SEND_INVALID_DEST) { - mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1); - _ds_port = MACH_PORT_NULL; + mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1); + _mbr_port = MACH_PORT_NULL; _ds_running(); status = MIG_SERVER_DIED; } @@ -141,9 +149,12 @@ _mbr_ClearCache() return 0; } +#endif -int mbr_uid_to_uuid(uid_t id, uuid_t uu) +int +mbr_uid_to_uuid(uid_t id, uuid_t uu) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -164,10 +175,15 @@ int mbr_uid_to_uuid(uid_t id, uuid_t uu) memcpy(uu, &request.el_uguid, sizeof(guid_t)); return 0; +#else + return EIO; +#endif } -int mbr_gid_to_uuid(gid_t id, uuid_t uu) +int +mbr_gid_to_uuid(gid_t id, uuid_t uu) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -181,10 +197,15 @@ int mbr_gid_to_uuid(gid_t id, uuid_t uu) memcpy(uu, &request.el_gguid, sizeof(guid_t)); return 0; +#else + return EIO; +#endif } -int mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) +int +mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -222,10 +243,15 @@ int mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) } return 0; +#else + return EIO; +#endif } -int mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) +int +mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -244,10 +270,82 @@ int mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) else return ENOENT; return 0; +#else + return EIO; +#endif +} + +int +mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, uuid_t uu) +{ +#ifdef DS_AVAILABLE + kern_return_t status; + audit_token_t token; + vm_offset_t ool = 0; + mach_msg_type_number_t oolCnt = 0; + uint32_t i; +#if __BIG_ENDIAN__ + id_t newID; +#endif + + if (identifier == NULL) return EINVAL; + if (identifier_size == 0) return EINVAL; + else if (identifier_size == -1) identifier_size = strlen((char*) identifier) + 1; + + if (_ds_running() == 0) return EIO; + if (_mbr_port == MACH_PORT_NULL) return EIO; + + memset(&token, 0, sizeof(audit_token_t)); + +#if __BIG_ENDIAN__ + switch (id_type) + { + case ID_TYPE_UID: + case ID_TYPE_GID: + if (identifier_size < sizeof(id_t)) return EINVAL; + newID = OSSwapInt32(*((id_t *) identifier)); + identifier = &newID; + break; + } +#endif + + if (identifier_size > MAX_MIG_INLINE_DATA) + { + if (vm_read(mach_task_self(), (vm_offset_t) identifier, identifier_size, &ool, &oolCnt) != 0) return ENOMEM; + identifier = NULL; + identifier_size = 0; + } + + status = MIG_SERVER_DIED; + for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++) + { + status = memberdDSmig_MapIdentifier(_mbr_port, id_type, (vm_offset_t)identifier, identifier_size, ool, oolCnt, uu, &token); + if (status == KERN_FAILURE) return ENOENT; + + if (status == MACH_SEND_INVALID_DEST) + { + if (ool != 0) vm_deallocate(mach_task_self(), ool, oolCnt); + + mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1); + _mbr_port = MACH_PORT_NULL; + _ds_running(); + status = MIG_SERVER_DIED; + } + } + + if (status != KERN_SUCCESS) return EIO; + if (audit_token_uid(token) != 0) return EAUTH; + + return 0; +#else + return EIO; +#endif } -int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type) +int +mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -275,10 +373,15 @@ int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type) } return 0; +#else + return EIO; +#endif } -int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) +int +mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) { +#ifdef DS_AVAILABLE int type, status; type = 0; @@ -287,10 +390,15 @@ int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) if (status != 0) return status; return 0; +#else + return EIO; +#endif } -int mbr_check_membership(uuid_t user, uuid_t group, int *ismember) +int +mbr_check_membership(uuid_t user, uuid_t group, int *ismember) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -305,10 +413,15 @@ int mbr_check_membership(uuid_t user, uuid_t group, int *ismember) *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); return 0; +#else + return EIO; +#endif } -int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember) +int +mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -323,10 +436,15 @@ int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember) *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); return 0; +#else + return EIO; +#endif } -int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember) +int +mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember) { +#ifdef DS_AVAILABLE struct kauth_identity_extlookup request; int status; @@ -341,25 +459,45 @@ int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember) *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0); return 0; +#else + return EIO; +#endif } -int mbr_reset_cache() +int +mbr_reset_cache() { +#ifdef DS_AVAILABLE return _mbr_ClearCache(); +#else + return EIO; +#endif } -int mbr_user_name_to_uuid(const char *name, uuid_t uu) +int +mbr_user_name_to_uuid(const char *name, uuid_t uu) { +#ifdef DS_AVAILABLE return _mbr_MapName((char *)name, 1, (guid_t *)uu); +#else + return EIO; +#endif } -int mbr_group_name_to_uuid(const char *name, uuid_t uu) +int +mbr_group_name_to_uuid(const char *name, uuid_t uu) { +#ifdef DS_AVAILABLE return _mbr_MapName((char *)name, 0, (guid_t *)uu); +#else + return EIO; +#endif } -int mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember) +int +mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember) { +#ifdef DS_AVAILABLE char *prefix = "com.apple.access_"; char *all_services = "com.apple.access_all_services"; char groupName[256]; @@ -398,9 +536,14 @@ int mbr_check_service_membership(const uuid_t user, const char *servicename, int } return result; +#else + return EIO; +#endif } -static char *ConvertBytesToDecimal(char *buffer, unsigned long long value) +#ifdef DS_AVAILABLE +static char * +ConvertBytesToDecimal(char *buffer, unsigned long long value) { char *temp; buffer[24] = '\0'; @@ -419,9 +562,12 @@ static char *ConvertBytesToDecimal(char *buffer, unsigned long long value) return temp; } +#endif -int mbr_sid_to_string(const nt_sid_t *sid, char *string) +int +mbr_sid_to_string(const nt_sid_t *sid, char *string) { +#ifdef DS_AVAILABLE char *current = string; long long temp = 0; int i; @@ -450,10 +596,15 @@ int mbr_sid_to_string(const nt_sid_t *sid, char *string) } return 0; +#else + return EIO; +#endif } -int mbr_string_to_sid(const char *string, nt_sid_t *sid) +int +mbr_string_to_sid(const char *string, nt_sid_t *sid) { +#ifdef DS_AVAILABLE char *current = (char *)string+2; int count = 0; long long temp; @@ -483,9 +634,14 @@ int mbr_string_to_sid(const char *string, nt_sid_t *sid) sid->sid_authcount = count; return 0; +#else + return EIO; +#endif } -static void ConvertBytesToHex(char **string, char **data, int numBytes) +#ifdef DS_AVAILABLE +static void +ConvertBytesToHex(char **string, char **data, int numBytes) { int i; @@ -509,9 +665,12 @@ static void ConvertBytesToHex(char **string, char **data, int numBytes) (*data)++; } } +#endif -int mbr_uuid_to_string(const uuid_t uu, char *string) +int +mbr_uuid_to_string(const uuid_t uu, char *string) { +#ifdef DS_AVAILABLE char *guid = (char*)uu; char *strPtr = string; ConvertBytesToHex(&strPtr, &guid, 4); @@ -526,10 +685,15 @@ int mbr_uuid_to_string(const uuid_t uu, char *string) *strPtr = '\0'; return 0; +#else + return EIO; +#endif } -int mbr_string_to_uuid(const char *string, uuid_t uu) +int +mbr_string_to_uuid(const char *string, uuid_t uu) { +#ifdef DS_AVAILABLE short dataIndex = 0; int isFirstNibble = 1; @@ -572,5 +736,8 @@ int mbr_string_to_uuid(const char *string, uuid_t uu) if (dataIndex != 16) return EINVAL; return 0; +#else + return EIO; +#endif } diff --git a/membership.subproj/membership.h b/membership.subproj/membership.h index 9a0aef0..32c8a8a 100644 --- a/membership.subproj/membership.h +++ b/membership.subproj/membership.h @@ -18,7 +18,7 @@ * under the License. * * @APPLE_LICENSE_HEADER_END@ - */ + */ #ifndef _MEMBERSHIP_H_ #define _MEMBERSHIP_H_ @@ -26,19 +26,185 @@ #include #include -#define ID_TYPE_UID 0 -#define ID_TYPE_GID 1 +/*! + @defined ID_TYPE_UID + @abstract is of type uid_t + @discussion is of type uid_t +*/ +#define ID_TYPE_UID 0 + +/*! + @defined ID_TYPE_GID + @abstract is of type gid_t + @discussion is of type gid_t +*/ +#define ID_TYPE_GID 1 + +/*! + @defined ID_TYPE_SID + @abstract is of type ntsid_t + @discussion is of type ntsid_t +*/ +#define ID_TYPE_SID 3 + +/*! + @defined ID_TYPE_USERNAME + @abstract is a NULL terminated UTF8 string + @discussion is a NULL terminated UTF8 string +*/ +#define ID_TYPE_USERNAME 4 + +/*! + @defined ID_TYPE_GROUPNAME + @abstract is a NULL terminated UTF8 string + @discussion is a NULL terminated UTF8 string +*/ +#define ID_TYPE_GROUPNAME 5 + +/*! + @defined ID_TYPE_GSS_EXPORT_NAME + @abstract is a gss exported name + @discussion is the data in gss_buffer_t as returned from gss_export_name. +*/ +#define ID_TYPE_GSS_EXPORT_NAME 10 + +/*! + @defined ID_TYPE_X509_DN + @abstract is a NULL terminated string representation of the X.509 certificate identity + @discussion is a NULL terminated string with the format of: + + DN of the Certificate authorityDN of the holder + + Example: + + DC=com,DC=example,CN=CertificatAuthorityDC=com,DC=example,CN=username +*/ +#define ID_TYPE_X509_DN 11 + +/*! + @defined ID_TYPE_KERBEROS + @abstract is a NULL terminated string representation of a Kerberos principal + @discussion is a NULL terminated string in the form of user\@REALM representing a typical + Kerberos principal. +*/ +#define ID_TYPE_KERBEROS 12 __BEGIN_DECLS -int mbr_uid_to_uuid(uid_t id, uuid_t uu); -int mbr_gid_to_uuid(gid_t id, uuid_t uu); -int mbr_uuid_to_id( const uuid_t uu, uid_t* id, int* id_type); -int mbr_sid_to_uuid( const nt_sid_t* sid, uuid_t uu); -int mbr_uuid_to_sid( const uuid_t uu, nt_sid_t* sid); +/*! + @function mbr_uid_to_uuid + @abstract convert a UID to a corresponding UUID + @discussion will convert a UID of a user to a corresponding UUID value. + This call will always succeed and may return a synthesized + UUID with the prefix FFFFEEEE-DDDD-CCCC-BBBB-AAAAxxxxxxxx, + where 'xxxxxxxx' is a hex conversion of the UID. The returned + UUID can be used for any operation including ACL and SACL + memberships, even if a UUID is later assigned to the user + record. + @param uid the uid_t to be converted + @param uu is the UUID found for the provided UID + @result returns 0 on success or appropriate errno code. +*/ +int mbr_uid_to_uuid(uid_t uid, uuid_t uu); +/*! + @function mbr_gid_to_uuid + @abstract convert a GID to a corresponding UUID + @discussion will convert a GID of a group to a corresponding UUID value. + This call will always succeed and may return a synthesized + UUID with the prefix AAAABBBB-CCCC-DDDD-EEEE-FFFFxxxxxxxx, + where 'xxxxxxxx' is a hex conversion of the UID. The returned + UUID can be used for any operation including ACL and SACL + memberships, even if a UUID is later assigned to the group + record. + @param gid the gid_t to be converted + @param uu is the UUID found for the provided GID + @result returns 0 on success or appropriate errno code. +*/ +int mbr_gid_to_uuid(gid_t gid, uuid_t uu); + +/*! + @function mbr_sid_to_uuid + @abstract convert a SID to a corresponding UUID + @discussion will convert a SID to a corresponding UUID value. This call + can fail for records that do not have a valid SID or RID. + @param sid the nt_sid_t to be converted + @param uu is the UUID found for the provided GID + @result returns 0 on success or appropriate errno code. +*/ +int mbr_sid_to_uuid(const nt_sid_t* sid, uuid_t uu); + +/*! + @function mbr_identifier_to_uuid + @abstract resolves various identifiers to corresponding UUID + @discussion will resolve various identifiers such as X.509 Distinguished + Names, Kerberos ID or other forms of security identifiers to a + corresponding UUID. + @param id_type is one of the defined types + @param identifier is a generic pointer as defined by the type + @param identifier_size is the size of the data pointed to in identifier + @param uu is the UUID found for the identifier + @result returns 0 on success or appropriate errno code. +*/ +int mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, + uuid_t uu); + +/*! + @function mbr_uuid_to_id + @abstract resolves a UUID to a corresponding ID and type + @discussion will resolve a UUID to a corresponding GID or UID and return + the type of ID (ID_TYPE_UID or ID_TYPE_GID). Synthesized + UUID values will be directly translated to corresponding ID. + A UID will always be returned even if the UUID is not found. + The returned ID is not persistant, but can be used to map back + to the UUID during runtime. + @param uu is the UUID to be resolved + @param uid_or_gid is the UID or GID found for the UUID + @param id_type is the type of ID + @result returns 0 on success or appropriate errno code. +*/ +int mbr_uuid_to_id(const uuid_t uu, id_t* uid_or_gid, int* id_type); + +/*! + @function mbr_uuid_to_sid + @abstract resolves a UUID to a corresponding SID + @discussion will resolve a UUID to a corresponding SID. + @param uu is the UUID to be resolved + @param sid is the SID found for the UUID + @result returns 0 on success or appropriate errno code. +*/ +int mbr_uuid_to_sid(const uuid_t uu, nt_sid_t* sid); + +/*! + @function mbr_check_membership + @abstract checks if a user is a member of a group + @discussion will check if a user is a member of a group either through + direct membership or via nested group membership. + @param user is the UUID of the user in question + @param group is the UUID of the group to be checked + @param ismember is set to 1 if user is a member of the group, + otherwise 0 is returned + @result returns 0 on success or appropriate errno code. +*/ int mbr_check_membership(uuid_t user, uuid_t group, int* ismember); +/*! + @function mbr_check_service_membership + @abstract checks if a user is part of a service group + @discussion will check if a user is a member of a service access group. + The servicename provided will be automatically prefixed with + "com.apple.access_" (e.g., "afp" becomes "com.apple.access_afp"). + In addition a special service group "com.apple.access_all_services" + will be checked in addition to the specific service. + @param user is the UUID of the user in question + @param servicename is the service type (e.g., "afp", "ftp", etc.) + @param ismember is set to 1 if user is a member of the group, + otherwise 0 is returned + @result returns 0 on success or appropriate errno code. +*/ +int mbr_check_service_membership(const uuid_t user, const char *servicename, + int *ismember); + __END_DECLS #endif /* !_MEMBERSHIP_H_ */ diff --git a/membership.subproj/membershipPriv.h b/membership.subproj/membershipPriv.h index 35a6fe3..a98854e 100644 --- a/membership.subproj/membershipPriv.h +++ b/membership.subproj/membershipPriv.h @@ -38,7 +38,6 @@ int mbr_reset_cache(); int mbr_user_name_to_uuid(const char *name, uuid_t uu); int mbr_group_name_to_uuid(const char *name, uuid_t uu); int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember); -int mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember); int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember); int mbr_uuid_to_string(const uuid_t uu, char *string); int mbr_string_to_uuid(const char *string, uuid_t uu); diff --git a/netinfo.subproj/Makefile b/netinfo.subproj/Makefile index 1be3dea..41f5577 100644 --- a/netinfo.subproj/Makefile +++ b/netinfo.subproj/Makefile @@ -1,44 +1,12 @@ -# -# Generated by the NeXT 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. -# +Project = netinfo +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES -NAME = netinfo - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component - -HFILES = CFILES = ni_stub.c -OTHERSRCS = Makefile Makefile.preamble - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - -PRIVATE_HEADERS = -# NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) -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 +Extra_CC_Flags = -Wall -fno-common \ + -D__DARWIN_NON_CANCELABLE=1 --include Makefile.dependencies +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/netinfo.subproj/Makefile.preamble b/netinfo.subproj/Makefile.preamble deleted file mode 100644 index 004b71b..0000000 --- a/netinfo.subproj/Makefile.preamble +++ /dev/null @@ -1,5 +0,0 @@ -OTHER_CFLAGS += -D__DARWIN_NON_CANCELABLE=1 - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/netinfo.subproj/PB.project b/netinfo.subproj/PB.project deleted file mode 100644 index 0d879af..0000000 --- a/netinfo.subproj/PB.project +++ /dev/null @@ -1,23 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = (); - OTHER_LINKED = (ni_stub.c); - OTHER_SOURCES = (Makefile.preamble, Makefile); - PRIVATE_HEADERS = (); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /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 = netinfo; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/nis.subproj/Makefile b/nis.subproj/Makefile index 542d835..8859ee9 100644 --- a/nis.subproj/Makefile +++ b/nis.subproj/Makefile @@ -1,16 +1,8 @@ -# -# Generated by the NeXT 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 = nis - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component +Project = nis +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES HFILES = ypclnt.h ypinternal.h yp_prot.h @@ -25,37 +17,16 @@ CFILES = getdomainname.c getnetgrent.c innetgr.c setdomainname.c\ yp_all.c yp_bind.c yp_first.c yp_get_default_domain.c\ yp_maplist.c yp_master.c yp_order.c -OTHERSRCS = Makefile.preamble Makefile yp_all.3 yp_bind.3 yp_first.3\ +MANPAGES = yp_all.3 yp_bind.3 yp_first.3\ yp_get_default_domain.3 yp_master.3 yp_match.3 yp_next.3\ yp_order.3 yp_unbind.3 ypclnt.3 yperr_string.3 ypprot_err.3\ - yp.8 Makefile.postamble - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - -PUBLIC_HEADERS = ypclnt.h yp_prot.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 + yp.8 -include $(MAKEFILEDIR)/$(MAKEFILE) +Install_Headers = ypclnt.h yp_prot.h +Install_Headers_Directory = /usr/include/rpcsvc --include Makefile.postamble +Extra_CC_Flags = -Wall -fno-common -I. \ + -I../gen.subproj -I../lookup.subproj \ + -D__DARWIN_NON_CANCELABLE=1 --include Makefile.dependencies +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make diff --git a/nis.subproj/Makefile.postamble b/nis.subproj/Makefile.postamble deleted file mode 100644 index 019c45f..0000000 --- a/nis.subproj/Makefile.postamble +++ /dev/null @@ -1,133 +0,0 @@ -############################################################################### -# NeXT Makefile.postamble Template -# Copyright 1993, NeXT Computer, Inc. -# -# This Makefile is used for configuring the standard app makefiles associated -# with ProjectBuilder. -# -# Use this template to set attributes for a project, sub-project, bundle, or -# palette. Each node in the project's tree of sub-projects and bundles -# should have it's own Makefile.preamble and Makefile.postamble. Additional -# rules (e.g., after_install) that are defined by the developer should be -# defined in this file. -# -############################################################################### -# -# Here are the variables exported by the common "app" makefiles that can be -# used in any customizations you make to the template below: -# -# PRODUCT_ROOT - Name of the directory to which resources are copied. -# OFILE_DIR - Directory into which .o object files are generated. -# (Note that this name is calculated based on the target -# architectures specified in Project Builder). -# DERIVED_SRC_DIR - Directory used for all other derived files -# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations -# -# NAME - name of application, bundle, subproject, palette, etc. -# LANGUAGE - langage in which the project is written (default "English") -# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" -# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" -# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project -# GLOBAL_RESOURCES - non-localized resources of project -# PROJECTVERSION - version of ProjectBuilder that output Makefile -# APPICON - application icon file -# DOCICONS - dock icon files -# ICONSECTIONS - Specifies icon sections when linking executable -# -# CLASSES - Class implementation files in project. -# HFILES - Header files in project. -# MFILES - Other Objective-C source files in project. -# CFILES - Other C source files in project. -# PSWFILES - .psw files in the project -# PSWMFILES - .pswm files in the project -# SUBPROJECTS - Subprojects of this project -# BUNDLES - Bundle subprojects of this project -# OTHERSRCS - Other miscellaneous sources of this project -# OTHERLINKED - Source files not matching a standard source extention -# -# LIBS - Libraries to link with when making app target -# DEBUG_LIBS - Libraries to link with when making debug target -# PROF_LIBS - Libraries to link with when making profile target -# OTHERLINKEDOFILES - Other relocatable files to (always) link in. -# -# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles -# MAKEFILEDIR - Directory in which to find $(MAKEFILE) -# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) -# INSTALLDIR - Directory app will be installed into by 'install' target -# -############################################################################### - - -# Change defaults assumed by the standard makefiles here. Edit the -# following default values as appropriate. (Note that if no Makefile.postamble -# exists, these values will have defaults set in common.make). - -# Versioning of frameworks, libraries, bundles, and palettes: -#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary -#DEPLOY_WITH_VERSION_NAME = A -#COMPATIBILITY_PROJECT_VERSION = 1 - -# Some compiler flags can be easily overridden here, but onlytake effect at -# the top-level: -#OPTIMIZATION_CFLAG = -O -#DEBUG_SYMBOLS_CFLAG = -g -#WARNING_CFLAGS = -Wall -#DEBUG_BUILD_CFLAGS = -DDEBUG -#PROFILE_BUILD_CFLAGS = -pg -DPROFILE - -# Flags passed to yacc -#YFLAGS = -d - -# Library and Framework projects only: -# 1. If you want something other than the default .dylib name, override it here -#DYLIB_INSTALL_NAME = lib$(NAME).dylib - -# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. -#DYLIB_INSTALL_DIR = $(INSTALLDIR) - -# 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 for various project types. Note: -S strips debugging symbols -# (executables can be stripped down further with -x or, if they load no bundles, with no -# options at all). -#APP_STRIP_OPTS = -S -#TOOL_STRIP_OPTS = -S -#LIBRARY_STRIP_OPTS = -S # for .a archives -#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries - -######################################################################### -# Put rules to extend the behavior of the standard Makefiles here. "Official" -# user-defined rules are: -# * before_install -# * after_install -# * after_installhdrs -# 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. - -# BUILD_OFILES_LIST_ONLY = YES - -MAN3DIR=/usr/share/man/man3 -MAN5DIR=/usr/share/man/man5 -MAN8DIR=/usr/share/man/man8 - -install-nis-man: - install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN3DIR) - install -m 755 -o root -g wheel -d $(DSTROOT)$(MAN8DIR) - install -m 644 -o root -g wheel -c yp_all.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_bind.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_first.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_get_default_domain.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_master.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_match.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_next.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_order.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp_unbind.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c ypclnt.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yperr_string.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c ypprot_err.3 "$(DSTROOT)$(MAN3DIR)" - install -m 644 -o root -g wheel -c yp.8 "$(DSTROOT)$(MAN8DIR)" - diff --git a/nis.subproj/Makefile.preamble b/nis.subproj/Makefile.preamble deleted file mode 100644 index a0abefb..0000000 --- a/nis.subproj/Makefile.preamble +++ /dev/null @@ -1,8 +0,0 @@ -AFTER_POSTINSTALL += install-nis-man -PUBLIC_HEADER_DIR_SUFFIX = /rpcsvc - -OTHER_CFLAGS += -D__DARWIN_NON_CANCELABLE=1 - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/nis.subproj/PB.project b/nis.subproj/PB.project deleted file mode 100644 index 8771000..0000000 --- a/nis.subproj/PB.project +++ /dev/null @@ -1,74 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = (ypclnt.h, ypinternal.h, yp_prot.h); - OTHER_LINKED = ( - getdomainname.c, - getnetgrent.c, - innetgr.c, - setdomainname.c, - xdr_domainname.c, - xdr_keydat.c, - xdr_mapname.c, - xdr_peername.c, - xdr_valdat.c, - xdr_ypbind_binding.c, - xdr_ypbind_resp.c, - xdr_ypbind_resptype.c, - xdr_ypbind_setdom.c, - xdr_ypmaplist.c, - xdr_ypreq_key.c, - xdr_ypreq_nokey.c, - xdr_ypresp_all.c, - xdr_ypresp_key_val.c, - xdr_ypresp_maplist.c, - xdr_ypresp_master.c, - xdr_ypresp_order.c, - xdr_ypresp_val.c, - xdr_ypstat.c, - yperr_string.c, - ypmatch_cache.c, - yppasswdd_xdr.c, - ypprot_err.c, - yp_all.c, - yp_bind.c, - yp_first.c, - yp_get_default_domain.c, - yp_maplist.c, - yp_master.c, - yp_order.c - ); - OTHER_SOURCES = ( - Makefile.preamble, - Makefile.postamble, - Makefile, - yp_all.3, - yp_bind.3, - yp_first.3, - yp_get_default_domain.3, - yp_master.3, - yp_match.3, - yp_next.3, - yp_order.3, - yp_unbind.3, - ypclnt.3, - yperr_string.3, - ypprot_err.3 - ); - PUBLIC_HEADERS = (ypclnt.h, yp_prot.h); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /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 = nis; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/nis.subproj/getdomainname.c b/nis.subproj/getdomainname.c index ea560ec..853cc67 100644 --- a/nis.subproj/getdomainname.c +++ b/nis.subproj/getdomainname.c @@ -29,11 +29,12 @@ #include int -getdomainname(char *val, int len) +getdomainname(char *val, int inlen) { int mib[2]; + size_t len = inlen; mib[0] = CTL_KERN; mib[1] = KERN_DOMAINNAME; - return sysctl(mib, 2, (void *)val, (size_t *)&len, NULL, 0); + return sysctl(mib, 2, val, &len, NULL, 0); } diff --git a/nis.subproj/yp.8 b/nis.subproj/yp.8 index b903753..cec5834 100644 --- a/nis.subproj/yp.8 +++ b/nis.subproj/yp.8 @@ -62,20 +62,16 @@ support is enabled in .Pp The .Nm YP -subsystem is started automatically in -.Pa /etc/rc -if it has been initialized in -.Pa /etc/rc.conf +subsystem is started automatically by +.Xr launchd 8 +if an +.Tn NIS +domain is specified in the +.Pa /etc/defaultdomain +configuration file, and if the directory .Pa /var/yp exists (which it does in the default distribution). -The default -.Tn NIS -domain must also be set with the -.Xr domainname 1 -command, which will happen automatically at system startup if it is -specified in -.Pa /etc/rc.conf . .Pp .Tn NIS is an diff --git a/nis.subproj/ypclnt.3 b/nis.subproj/ypclnt.3 index 669104a..36e0744 100644 --- a/nis.subproj/ypclnt.3 +++ b/nis.subproj/ypclnt.3 @@ -279,6 +279,9 @@ something useful or simply ignore it. .El .It Fn yp_order Returns the order number for a map. +The order number is updated whenever a map is updated. +Clients may use the order number to check whether they are using the most +recent map. .It Fn yp_master Returns the hostname for the machine on which the master YP server process for a map is running. @@ -339,4 +342,4 @@ The client cannot communicate with the YP server process. .Xr ypbind 8 , .Xr ypserv 8 .Sh AUTHOR -Theo De Raadt \ No newline at end of file +Theo De Raadt diff --git a/rpc.subproj/DISCLAIMER b/rpc.subproj/DISCLAIMER new file mode 100644 index 0000000..1a66d5f --- /dev/null +++ b/rpc.subproj/DISCLAIMER @@ -0,0 +1,28 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ diff --git a/rpc.subproj/Makefile b/rpc.subproj/Makefile index f74a525..1aeaab7 100644 --- a/rpc.subproj/Makefile +++ b/rpc.subproj/Makefile @@ -1,16 +1,8 @@ -# -# Generated by the NeXT 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 = rpc - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component +Project = rpc +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES HFILES = auth.h auth_unix.h clnt.h pmap_clnt.h pmap_prot.h pmap_rmt.h\ rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h pmap_wakeup.h @@ -25,37 +17,55 @@ CFILES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c\ xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c\ xdr_sizeof.c xdr_stdio.c getrpcport.c pmap_wakeup.c -OTHERSRCS = Makefile.preamble Makefile Makefile.postamble \ - bindresvport.3 getrpcent.3 getrpcport.3 rpc.3 xdr.3 - +MANPAGES = bindresvport.3 getrpcent.3 getrpcport.3 rpc.3 xdr.3 -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.make -LIBS = -DEBUG_LIBS = $(LIBS) -PROF_LIBS = $(LIBS) - - -PUBLIC_HEADERS = auth.h auth_unix.h clnt.h pmap_clnt.h pmap_prot.h\ +Install_Headers_Directory = /usr/include/rpc +Install_Headers = auth.h auth_unix.h clnt.h pmap_clnt.h pmap_prot.h\ pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h\ xdr.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 - -include $(MAKEFILEDIR)/$(MAKEFILE) - --include Makefile.postamble - --include Makefile.dependencies +Extra_CC_Flags = -Wall -fno-common \ + -I../gen.subproj -I../lookup.subproj \ + -D__DARWIN_NON_CANCELABLE=1 + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +after_install: + @for LINK in getrpcbyname.3 getrpcbynumber.3 \ + endrpcent.3 setrpcent.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in auth_destroy.3 authnone_create.3 authunix_create.3 \ + authunix_create_default.3 callrpc.3 clnt_broadcast.3 \ + clnt_call.3 clnt_control.3 clnt_create.3 clnt_destroy.3 \ + clnt_freeres.3 clnt_geterr.3 clnt_pcreateerror.3 \ + clnt_perrno.3 clnt_perror.3 clnt_spcreateerror.3 \ + clnt_sperrno.3 clnt_sperror.3 clntraw_create.3 \ + clnttcp_create.3 clntudp_bufcreate.3 clntudp_create.3 \ + get_myaddress.3 pmap_getmaps.3 pmap_getport.3 pmap_rmtcall.3 \ + pmap_set.3 pmap_unset.3 regsterrpc.3 rpc_createerr.3 \ + svc_destroy.3 svc_fds.3 svc_fdset.3 svc_getargs.3 \ + svc_getcaller.3 svc_getreg.3 svc_getregset.3 svc_register.3 \ + svc_run.3 svc_sendreply.3 svc_unregister.3 svcerr_auth.3 \ + svcerr_decode.3 svcerr_noproc.3 svcerr_noprog.3 \ + svcerr_progvers.3 svcerr_systemerr.3 svcerr_weakauth.3 \ + svcfd_create.3 svcraw_create.3 svctcp_create.3 \ + svcudp_bufcreate.3 xdr_accepted_reply.3 xdr_authunix_parms.3 \ + xdr_callhdr.3 xdr_callmsg.3 xdr_opaque_auth.3 xdr_pmap.3 \ + xdr_pmaplist.3 xdr_rejected_reply.3 xdr_replymsg.3 \ + xprt_register.3 xprt_unregister.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + @for LINK in xdr_array.3 xdr_bool.3 xdr_bytes.3 xdr_char.3 \ + xdr_destroy.3 xdr_double.3 xdr_enum.3 xdr_float.3 xdr_free.3 \ + xdr_getpos.3 xdr_inline.3 xdr_int.3 xdr_long.3 \ + xdrmem_create.3 xdr_opaque.3 xdr_pointer.3 xdrrec_create.3 \ + xdrrec_endofrecord.3 xdrrec_eof.3 xdrrec_skiprecord.3 \ + xdr_reference.3 xdr_setpos.3 xdr_short.3 xdrstdio_create.3 \ + xdr_string.3 xdr_u_char.3 xdr_u_long.3 xdr_u_short.3 \ + xdr_union.3 xdr_vector.3 xdr_void.3 xdr_wrapstring.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done diff --git a/rpc.subproj/Makefile.inc b/rpc.subproj/Makefile.inc new file mode 100644 index 0000000..73c0fd1 --- /dev/null +++ b/rpc.subproj/Makefile.inc @@ -0,0 +1,115 @@ +# from: @(#)Makefile.inc 5.3 (Berkeley) 2/20/91 +# $Id: Makefile.inc,v 1.2 2004/12/19 22:45:44 zarzycki Exp $ + +# librpc sources +.PATH: ${.CURDIR}/arch/${MACHINE}/rpc ${.CURDIR}/rpc + +SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \ + clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \ + clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \ + pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \ + pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \ + svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \ + svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \ + xdr_rec.c xdr_reference.c xdr_stdio.c pmap_wakeup.c + +MAN3+= bindresvport.0 getrpcent.0 getrpcport.0 rpc.0 xdr.0 +MLINKS+= getrpcport.3 getrpcbyname.3 \ + getrpcport.3 getrpcbynumber.3 \ + getrpcport.3 endrpcent.3 \ + getrpcport.3 setrpcent.3 \ + rpc.3 auth_destroy.3 \ + rpc.3 authnone_create.3 \ + rpc.3 authunix_create.3 \ + rpc.3 authunix_create_default.3 \ + rpc.3 callrpc.3 \ + rpc.3 clnt_broadcast.3 \ + rpc.3 clnt_call.3 \ + rpc.3 clnt_control.3 \ + rpc.3 clnt_create.3 \ + rpc.3 clnt_destroy.3 \ + rpc.3 clnt_freeres.3 \ + rpc.3 clnt_geterr.3 \ + rpc.3 clnt_pcreateerror.3 \ + rpc.3 clnt_perrno.3 \ + rpc.3 clnt_perror.3 \ + rpc.3 clnt_spcreateerror.3 \ + rpc.3 clnt_sperrno.3 \ + rpc.3 clnt_sperror.3 \ + rpc.3 clntraw_create.3 \ + rpc.3 clnttcp_create.3 \ + rpc.3 clntudp_bufcreate.3 \ + rpc.3 clntudp_create.3 \ + rpc.3 get_myaddress.3 \ + rpc.3 pmap_getmaps.3 \ + rpc.3 pmap_getport.3 \ + rpc.3 pmap_rmtcall.3 \ + rpc.3 pmap_set.3 \ + rpc.3 pmap_unset.3 \ + rpc.3 regsterrpc.3 \ + rpc.3 rpc_createerr.3 \ + rpc.3 svc_destroy.3 \ + rpc.3 svc_fds.3 \ + rpc.3 svc_fdset.3 \ + rpc.3 svc_getargs.3 \ + rpc.3 svc_getcaller.3 \ + rpc.3 svc_getreg.3 \ + rpc.3 svc_getregset.3 \ + rpc.3 svc_register.3 \ + rpc.3 svc_run.3 \ + rpc.3 svc_sendreply.3 \ + rpc.3 svc_unregister.3 \ + rpc.3 svcerr_auth.3 \ + rpc.3 svcerr_decode.3 \ + rpc.3 svcerr_noproc.3 \ + rpc.3 svcerr_noprog.3 \ + rpc.3 svcerr_progvers.3 \ + rpc.3 svcerr_systemerr.3 \ + rpc.3 svcerr_weakauth.3 \ + rpc.3 svcfd_create.3 \ + rpc.3 svcraw_create.3 \ + rpc.3 svctcp_create.3 \ + rpc.3 svcudp_bufcreate.3 \ + rpc.3 xdr_accepted_reply.3 \ + rpc.3 xdr_authunix_parms.3 \ + rpc.3 xdr_callhdr.3 \ + rpc.3 xdr_callmsg.3 \ + rpc.3 xdr_opaque_auth.3 \ + rpc.3 xdr_pmap.3 \ + rpc.3 xdr_pmaplist.3 \ + rpc.3 xdr_rejected_reply.3 \ + rpc.3 xdr_replymsg.3 \ + rpc.3 xprt_register.3 \ + rpc.3 xprt_unregister.3 \ + xdr.3 xdr_array.3 \ + xdr.3 xdr_bool.3 \ + xdr.3 xdr_bytes.3 \ + xdr.3 xdr_char.3 \ + xdr.3 xdr_destroy.3 \ + xdr.3 xdr_double.3 \ + xdr.3 xdr_enum.3 \ + xdr.3 xdr_float.3 \ + xdr.3 xdr_free.3 \ + xdr.3 xdr_getpos.3 \ + xdr.3 xdr_inline.3 \ + xdr.3 xdr_int.3 \ + xdr.3 xdr_long.3 \ + xdr.3 xdrmem_create.3 \ + xdr.3 xdr_opaque.3 \ + xdr.3 xdr_pointer.3 \ + xdr.3 xdrrec_create.3 \ + xdr.3 xdrrec_endofrecord.3 \ + xdr.3 xdrrec_eof.3 \ + xdr.3 xdrrec_skiprecord.3 \ + xdr.3 xdr_reference.3 \ + xdr.3 xdr_setpos.3 \ + xdr.3 xdr_short.3 \ + xdr.3 xdrstdio_create.3 \ + xdr.3 xdr_string.3 \ + xdr.3 xdr_u_char.3 \ + xdr.3 xdr_u_long.3 \ + xdr.3 xdr_u_short.3 \ + xdr.3 xdr_union.3 \ + xdr.3 xdr_vector.3 \ + xdr.3 xdr_void.3 \ + xdr.3 xdr_wrapstring.3 diff --git a/rpc.subproj/Makefile.postamble b/rpc.subproj/Makefile.postamble deleted file mode 100644 index b851b91..0000000 --- a/rpc.subproj/Makefile.postamble +++ /dev/null @@ -1,224 +0,0 @@ -############################################################################### -# NeXT Makefile.postamble Template -# Copyright 1993, NeXT Computer, Inc. -# -# This Makefile is used for configuring the standard app makefiles associated -# with ProjectBuilder. -# -# Use this template to set attributes for a project, sub-project, bundle, or -# palette. Each node in the project's tree of sub-projects and bundles -# should have it's own Makefile.preamble and Makefile.postamble. Additional -# rules (e.g., after_install) that are defined by the developer should be -# defined in this file. -# -############################################################################### -# -# Here are the variables exported by the common "app" makefiles that can be -# used in any customizations you make to the template below: -# -# PRODUCT_ROOT - Name of the directory to which resources are copied. -# OFILE_DIR - Directory into which .o object files are generated. -# (Note that this name is calculated based on the target -# architectures specified in Project Builder). -# DERIVED_SRC_DIR - Directory used for all other derived files -# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations -# -# NAME - name of application, bundle, subproject, palette, etc. -# LANGUAGE - langage in which the project is written (default "English") -# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project -# GLOBAL_RESOURCES - non-localized resources of project -# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) -# ICONSECTIONS - Specifies icon sections when linking executable -# -# CLASSES - Class implementation files in project. -# HFILES - Header files in project. -# MFILES - Other Objective-C source files in project. -# CFILES - Other C source files in project. -# PSWFILES - .psw files in the project -# PSWMFILES - .pswm files in the project -# SUBPROJECTS - Subprojects of this project -# BUNDLES - Bundle subprojects of this project -# OTHERSRCS - Other miscellaneous sources of this project -# OTHERLINKED - Source files not matching a standard source extention -# -# LIBS - Libraries to link with when making app target -# DEBUG_LIBS - Libraries to link with when making debug target -# PROF_LIBS - Libraries to link with when making profile target -# OTHERLINKEDOFILES - Other relocatable files to (always) link in. -# -# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles -# MAKEFILEDIR - Directory in which to find $(MAKEFILE) -# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) -# INSTALLDIR - Directory app will be installed into by 'install' target -# -############################################################################### - - -# Change defaults assumed by the standard makefiles here. Edit the -# following default values as appropriate. (Note that if no Makefile.postamble -# exists, these values will have defaults set in common.make). - -# Versioning of frameworks, libraries, bundles, and palettes: -#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary -#DEPLOY_WITH_VERSION_NAME = A -#COMPATIBILITY_PROJECT_VERSION = 1 - -# Some compiler flags can be easily overridden here, but onlytake effect at -# the top-level: -#OPTIMIZATION_CFLAG = -O -#DEBUG_SYMBOLS_CFLAG = -g -#WARNING_CFLAGS = -Wall -#DEBUG_BUILD_CFLAGS = -DDEBUG -#PROFILE_BUILD_CFLAGS = -pg -DPROFILE - -# Flags passed to yacc -#YFLAGS = -d - -# Library and Framework projects only: -# 1. If you want something other than the default .dylib name, override it here -#DYLIB_INSTALL_NAME = lib$(NAME).dylib - -# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. -#DYLIB_INSTALL_DIR = $(INSTALLDIR) - -# 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 for various project types. Note: -S strips debugging symbols -# (executables can be stripped down further with -x or, if they load no bundles, with no -# options at all). -#APP_STRIP_OPTS = -S -#TOOL_STRIP_OPTS = -S -#LIBRARY_STRIP_OPTS = -S # for .a archives -#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries - -######################################################################### -# Put rules to extend the behavior of the standard Makefiles here. "Official" -# user-defined rules are: -# * before_install -# * after_install -# * after_installhdrs -# 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. - - -#install:: -# @(if [ "$(CODE_GEN_STYLE)" != "STATIC" ]; then\ -# $(MAKE) install "CODE_GEN_STYLE=STATIC"\ -# "DSTROOT=$(DSTROOT)"\ -# "OBJROOT=$(OBJROOT)"\ -# "SYMROOT=$(SYMROOT)"\ -# "RC_CFLAGS = $(RC_CFLAGS)"\ -# "RC_ARCHS = $(RC_ARCHS)" ;\ -# fi ) - -install-man-page: - mkdir -p "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 bindresvport.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 getrpcent.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 getrpcport.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 rpc.3 "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 xdr.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/getrpcbyname.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/getrpcbynumber.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/endrpcent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/getrpcent.3" "$(DSTROOT)/usr/share/man/man3/setrpcent.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/auth_destroy.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/authnone_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/authunix_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/authunix_create_default.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/callrpc.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_broadcast.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_call.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_control.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_destroy.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_freeres.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_geterr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_pcreateerror.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_perrno.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_perror.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_spcreateerror.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_sperrno.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnt_sperror.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clntraw_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clnttcp_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clntudp_bufcreate.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/clntudp_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/get_myaddress.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_getmaps.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_getport.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_rmtcall.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_set.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/pmap_unset.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/regsterrpc.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/rpc_createerr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_destroy.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_fds.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_fdset.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getargs.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getcaller.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getreg.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_getregset.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_register.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_run.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_sendreply.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svc_unregister.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_auth.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_decode.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_noproc.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_noprog.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_progvers.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_systemerr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcerr_weakauth.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcfd_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcraw_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svctcp_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/svcudp_bufcreate.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_accepted_reply.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_authunix_parms.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_callhdr.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_callmsg.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_opaque_auth.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_pmap.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_pmaplist.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_rejected_reply.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xdr_replymsg.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xprt_register.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rpc.3" "$(DSTROOT)/usr/share/man/man3/xprt_unregister.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_array.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_bool.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_bytes.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_char.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_destroy.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_double.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_enum.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_float.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_free.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_getpos.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_inline.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_int.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_long.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrmem_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_opaque.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_pointer.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_endofrecord.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_eof.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrrec_skiprecord.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_reference.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_setpos.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_short.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdrstdio_create.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_string.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_u_char.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_u_long.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_u_short.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_union.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_vector.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_void.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/xdr.3" "$(DSTROOT)/usr/share/man/man3/xdr_wrapstring.3" - diff --git a/rpc.subproj/Makefile.preamble b/rpc.subproj/Makefile.preamble deleted file mode 100644 index e827b3c..0000000 --- a/rpc.subproj/Makefile.preamble +++ /dev/null @@ -1,15 +0,0 @@ -OTHER_CFLAGS = \ - -D__DARWIN_NON_CANCELABLE=1 \ - -Dsetrpcent=_old_setrpcent \ - -Dgetrpcent=_old_getrpcent \ - -Dendrpcent=_old_endrpcent \ - -Dgetrpcbyname=_old_getrpcbyname \ - -Dgetrpcbynumber=_old_getrpcbynumber - -PUBLIC_HEADER_DIR_SUFFIX = /rpc - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) - -AFTER_POSTINSTALL += install-man-page diff --git a/rpc.subproj/PB.project b/rpc.subproj/PB.project deleted file mode 100644 index f7685fe..0000000 --- a/rpc.subproj/PB.project +++ /dev/null @@ -1,91 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - H_FILES = ( - auth.h, - auth_unix.h, - clnt.h, - pmap_clnt.h, - pmap_prot.h, - pmap_rmt.h, - pmap_wakeup.h, - rpc.h, - rpc_msg.h, - svc.h, - svc_auth.h, - types.h, - xdr.h - ); - OTHER_LINKED = ( - auth_none.c, - auth_unix.c, - authunix_prot.c, - bindresvport.c, - clnt_generic.c, - clnt_perror.c, - clnt_raw.c, - clnt_simple.c, - clnt_tcp.c, - clnt_udp.c, - get_myaddress.c, - pmap_clnt.c, - pmap_getmaps.c, - pmap_getport.c, - pmap_prot.c, - pmap_prot2.c, - pmap_rmt.c, - pmap_wakeup.c, - rpc_callmsg.c, - rpc_commondata.c, - rpc_dtablesize.c, - rpc_prot.c, - svc.c, - svc_auth.c, - svc_auth_unix.c, - svc_raw.c, - svc_run.c, - svc_simple.c, - svc_tcp.c, - getrpcent.c, - svc_udp.c, - xdr.c, - xdr_array.c, - xdr_float.c, - xdr_mem.c, - xdr_rec.c, - xdr_reference.c, - xdr_sizeof.c, - xdr_stdio.c, - getrpcport.c - ); - OTHER_SOURCES = (Makefile.preamble, Makefile); - PUBLIC_HEADERS = ( - auth.h, - auth_unix.h, - clnt.h, - pmap_clnt.h, - pmap_prot.h, - pmap_rmt.h, - rpc.h, - rpc_msg.h, - svc.h, - svc_auth.h, - types.h, - xdr.h - ); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /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 = rpc; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/rpc.subproj/README b/rpc.subproj/README new file mode 100644 index 0000000..ad9d70f --- /dev/null +++ b/rpc.subproj/README @@ -0,0 +1,233 @@ +RPCSRC 4.0 7/11/89 + +This distribution contains Sun Microsystem's implementation of the +RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD. Also +included is complete documentation, utilities, RPC service +specification files, and demonstration services in the format used by +the RPC protocol compiler (rpcgen). See WHAT'S NEW below for +details. + +NOTE ABOUT SECURE RPC: + +This release of RPCSRC contains most of the code needed to implement +Secure RPC (see "DES Authentication" in the RPC Protocol Specification, +doc/rpc.rfc.ms). Due to legal considerations, we are unable to +distribute an implementation of DES, the Data Encryption Standard, which +Secure RPC requires. For this reason, all of the files, documentation, and +programs associated with Secure RPC have been placed into a separate +directory, secure_rpc. The RPC library contained in the main body of this +release *DOES NOT* support Secure RPC. See secure_rpc/README for more +details. (A DES library was posted in Volume 18 of comp.sources.unix.) + +If you wish to report bugs found in this release, send mail to: + +Portable ONC/NFS +Sun Microsystems, Inc +MS 12-33 +2550 Garcia Avenue +Mountain View, CA 94043 + +or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet). + +ROADMAP + +The directory hierarchy is as follows: + + demo/ Various demonstration services + demo/dir Remote directory lister + demo/msg Remote console message delivery service + demo/sort Remote sort service + + doc/ Documentation for RPC, XDR and NFS in "-ms" format. + + etc/ Utilities (rpcinfo and portmap). portmap must be + started by root before any other RPC network services are + used. SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER. + + man/ Manual pages for RPC library, rpcgen, and utilities. + + rpc/ The RPC and XDR library. SEE BELOW + FOR BUGFIX TO 4.2BSD COMPILER. + + rpcgen/ The RPC Language compiler (for .x files) + + rpcsvc/ Service definition files for various services and the + server and client code for the Remote Status service. + + secure_rpc/ The files in this directory are used to build a version of + the RPC library with DES Authentication. See the README + file in that directory for more details. + +BUILD INSTRUCTIONS + +Makefiles can be found in all directories except for man. The +Makefile in the top directory will cause these others to be invoked +(except for in the doc, man and demo directories), in turn building the +entire release. + +WARNING! THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES +IN /usr/include, /usr/lib, /usr/bin and /etc. + +The master RPC include file, rpc/rpc.h, is used by all programs and +routines that use RPC. It includes other RPC and system include files +needed by the RPC system. PLEASE NOTE: If your system has NFS, it +may have been based on Sun's NFS Source. The include files installed +by this package may duplicate include files you will find on your NFS +system. The RPCSRC 4.0 include files are upwardly compatible to all +NFS Source include files as of the date of this distribution (not +including any new definitions or declarations added by your system +vendor). HOWEVER: Please read the comments towards the end of +rpc/rpc.h regarding rpc/netdb.h. You may need to uncomment the +inclusion of that file if the structures it defines are already +defined by your system's include files. + +After making any compiler fixes that are needed (see below), at +the top directory, type: + + make install + +For all installations, the Makefile macro DESTDIR is prepended to the +installation path. It is defined to be null in the Makefiles, so +installations are relative to root. (You will probably need root +privileges for installing the files under the default path.) To +install the files under some other tree (e.g., /usr/local), use the +command: + + make install DESTDIR=/usr/local + +This will place the include files in /usr/local/usr/include, the RPC +library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the +utilities in /usr/local/etc. You'll have to edit the Makefiles or +install the files by hand if you want to do anything other than this +kind of relocation of the installation tree. + +The RPC library will be built and installed first. By default it is +installed in /usr/lib as "librpclib.a". The directory +/usr/include/rpc will also be created, and several header files will +be installed there. ALL RPC SERVICES INCLUDE THESE HEADER FILES. + +The programs in etc/ link in routines from librpclib.a. If you change +where it is installed, be sure to edit etc/'s Makefile to reflect this. +These programs are installed in /etc. PORTMAP MUST BE RUNNING ON +YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE. + +rpcgen is installed in /usr/bin. This program is required to build +the demonstration services in demo and the rstat client and server in +rpcsvc/. + +The rpcsvc/ directory will install its files in the directory +/usr/include/rpcsvc. The Remote Status service (rstat_svc) will be +compiled and installed in /etc. If you wish to make this service +available, you should either start this service when needed or have +it started at boot time by invoking it in your /etc/rc.local script. +(Be sure that portmap is started first!) Sun has modified its +version of inetd to automatically start RPC services. (Use "make +LIB=" when building rstat on a Sun Workstation.) The Remote Status +client (rstat) will be installed in /usr/bin. This program queries +the rstat_svc on a remote host and prints a system status summary +similar to the one printed by "uptime". + +The documentation is not built during the "make install" command. +Typing "make" in the doc directory will cause all of the manuals to +be formatted using nroff into a single file. We have had a report +that certain "troff" equivalents have trouble processing the full +manual. If you have trouble, try building the manuals individually +(see the Makefile). + +The demonstration services in the demo directory are not built by the +top-level "make install" command. To build these, cd to the demo +directory and enter "make". The three services will be built. +RPCGEN MUST BE INSTALLED in a path that make can find. To run the +services, start the portmap program as root and invoke the service +(you probably will want to put it in the background). rpcinfo can be +used to check that the service succeeded in getting registered with +portmap, and to ping the service (see rpcinfo's man page). You can +then use the corresponding client program to exercise the service. +To build these services on a Sun workstation, you must prevent the +Makefile from trying to link the RPC library (as these routines are +already a part of Sun's libc). Use: "make LIB=". + +BUGFIX FOR 4.3BSD COMPILER + +The use of a 'void *' declaration for one of the arguments in +the reply_proc() procedure in etc/rpcinfo.c will trigger a bug +in the 4.3BSD compiler. The bug is fixed by the following change to +the compiler file mip/manifest.h: + +*** manifest.h.r1.1 Thu Apr 30 13:52:25 1987 +--- manifest.h.r1.2 Mon Nov 23 18:58:17 1987 +*************** +*** 21,27 **** + /* + * Bogus type values + */ +! #define TNULL PTR /* pointer to UNDEF */ + #define TVOID FTN /* function returning UNDEF (for void) */ + + /* +--- 21,27 ---- + /* + * Bogus type values + */ +! #define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */ + #define TVOID FTN /* function returning UNDEF (for void) */ + + /* + +If you cannot fix your compiler, change the declaration in reply_proc() +from 'void *' to 'char *'. + +BUGFIX FOR 4.2BSD COMPILER + +Unpatched 4.2BSD compilers complain about valid C. You can make old +compilers happy by changing some voids to ints. However, the fix to +the 4.2 VAX compiler is as follows (to mip/trees.c): + +*** trees.c.r1.1 Mon May 11 13:47:58 1987 +--- trees.c.r1.2 Wed Jul 2 18:28:52 1986 +*************** +*** 1247,1253 **** + if(o==CAST && mt1==0)return(TYPL+TYMATCH); + if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); + else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); +! else if( mt12 == 0 ) break; + else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); + else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); + break; +--- 1261,1269 ---- + if(o==CAST && mt1==0)return(TYPL+TYMATCH); + if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH ); + else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN ); +! /* if right is TVOID and looks like a CALL, is not ok */ +! else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL)) +! break; + else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN ); + else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN ); + break; + +WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0 + +The previous release was RPCSRC 3.9. As with all previous releases, +this release is based directly on files from Sun Microsystem's +implementation. + +Upgrade from RPCSRC 3.9 + +1) RPCSRC 4.0 upgrades RPCSRC 3.9. Improvements from SunOS 4.0 have + been integrated into this release. + +Secure RPC (in the secure_rpc/ directory) + +2) DES Authentication routines and programs are provided. +3) A new manual, "Secure NFS" is provided, which describes Secure RPC + and Secure NFS. +4) Skeleton routines and manual pages are provided which describe the + DES encryption procedures required by Secure RPC. HOWEVER, NO DES + ROUTINE IS PROVIDED. + +New Functionality + +5) rpcinfo can now be used to de-register services from the portmapper + which may have terminated abnormally. +6) A new client, rstat, is provided which queries the rstat_svc and + prints a status line similar to the one displayed by "uptime". diff --git a/rpc.subproj/bindresvport.3 b/rpc.subproj/bindresvport.3 index 0ec6ffb..92ebf56 100644 --- a/rpc.subproj/bindresvport.3 +++ b/rpc.subproj/bindresvport.3 @@ -1,27 +1,103 @@ -.\" from: @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI -.\" $Id: bindresvport.3,v 1.1 1999/04/13 23:15:36 wsanchez Exp $ +.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI +.\" $NetBSD: bindresvport.3,v 1.8 2000/07/05 15:45:33 msaitoh Exp $ +.\" $FreeBSD: src/lib/libc/rpc/bindresvport.3,v 1.15 2002/12/18 12:45:10 ru Exp $ .\" .Dd November 22, 1987 .Dt BINDRESVPORT 3 .Os .Sh NAME -.Nm bindresvport +.Nm bindresvport , +.Nm bindresvport_sa .Nd bind a socket to a privileged IP port +.Sh LIBRARY +.Lb libc .Sh SYNOPSIS -.Fd #include -.Fd include +.In sys/types.h +.In rpc/rpc.h .Ft int -.Fn bindresvport "int sd" "struct sockaddr_in **sin" +.Fn bindresvport "int sd" "struct sockaddr_in *sin" +.Ft int +.Fn bindresvport_sa "int sd" "struct sockaddr *sa" .Sh DESCRIPTION +The .Fn bindresvport -is used to bind a socket descriptor to a privileged +and +.Fn bindresvport_sa +functions +are used to bind a socket descriptor to a privileged .Tn IP port, that is, a port number in the range 0-1023. -The routine returns 0 if it is successful, -otherwise -1 is returned and -.Va errno -set to reflect the cause of the error. +.Pp +If +.Fa sin +is a pointer to a +.Ft "struct sockaddr_in" +then the appropriate fields in the structure should be defined. +Note that +.Fa sin->sin_family +must be initialized to the address family of the socket, passed by +.Fa sd . +If +.Fa sin->sin_port +is +.Sq 0 +then an anonymous port (in the range 600-1023) will be +chosen, and if +.Xr bind 2 +is successful, the +.Fa sin->sin_port +will be updated to contain the allocated port. +.Pp +If +.Fa sin +is the +.Dv NULL +pointer, +an anonymous port will be allocated (as above). +However, there is no way for +.Fn bindresvport +to return the allocated port in this case. .Pp Only root can bind to a privileged port; this call will fail for any other users. +.Pp +Function prototype of +.Fn bindresvport +is biased to +.Dv AF_INET +socket. +The +.Fn bindresvport_sa +function +acts exactly the same, with more neutral function prototype. +Note that both functions behave exactly the same, and +both support +.Dv AF_INET6 +sockets as well as +.Dv AF_INET +sockets. +.Sh RETURN VALUES +.Rv -std bindresvport +.Sh ERRORS +.Bl -tag -width Er +.It Bq Er EPFNOSUPPORT +If second argument was supplied, +and address family did not match between arguments. +.El +.Pp +The +.Fn bindresvport +function +may also fail and set +.Va errno +for any of the errors specified for the calls +.Xr bind 2 , +.Xr getsockopt 2 , +or +.Xr setsockopt 2 . +.Sh SEE ALSO +.Xr bind 2 , +.Xr getsockopt 2 , +.Xr setsockopt 2 , +.Xr ip 4 diff --git a/rpc.subproj/clnt_udp.c b/rpc.subproj/clnt_udp.c index 53c618b..db3c242 100644 --- a/rpc.subproj/clnt_udp.c +++ b/rpc.subproj/clnt_udp.c @@ -188,7 +188,7 @@ clntudp_bufcreate_timeout(struct sockaddr_in *raddr, uint32_t program, uint32_t cu->cu_total_timeout.tv_sec = -1; cu->cu_total_timeout.tv_usec = -1; - if (total_timeout != NULL) cu->cu_total_timeout = *retry_timeout; + if (total_timeout != NULL) cu->cu_total_timeout = *total_timeout; rfd = open("/dev/random", O_RDONLY, 0); if ((rfd < 0) || (read(rfd, &call_msg.rm_xid, sizeof(call_msg.rm_xid)) != sizeof(call_msg.rm_xid))) @@ -430,8 +430,11 @@ send_again: if (inlen < sizeof(u_long)) continue; /* see if reply transaction id matches sent id */ - if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf))) - continue; +#ifdef __LP64__ + if (*((uint32_t *)(cu->cu_inbuf)) != *((uint32_t *)(cu->cu_outbuf))) continue; +#else + if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf))) continue; +#endif /* we now assume we have the proper reply */ break; } diff --git a/rpc.subproj/getrpcent.3 b/rpc.subproj/getrpcent.3 index dc4826d..2e8bcf1 100644 --- a/rpc.subproj/getrpcent.3 +++ b/rpc.subproj/getrpcent.3 @@ -1,5 +1,6 @@ -.\" from: @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI -.\" $Id: getrpcent.3,v 1.1 1999/04/13 23:15:37 wsanchez Exp $ +.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI +.\" $NetBSD: getrpcent.3,v 1.6 1998/02/05 18:49:06 perry Exp $ +.\" $FreeBSD: src/lib/libc/rpc/getrpcent.3,v 1.18 2005/01/20 09:17:04 ru Exp $ .\" .Dd December 14, 1987 .Dt GETRPCENT 3 @@ -11,8 +12,10 @@ .Nm endrpcent , .Nm setrpcent .Nd get RPC entry +.Sh LIBRARY +.Lb libc .Sh SYNOPSIS -.Fd #include +.In rpc/rpc.h .Ft struct rpcent * .Fn getrpcent void .Ft struct rpcent * @@ -21,19 +24,21 @@ .Fn getrpcbynumber "int number" .Ft void .Fn setrpcent "int stayopen" -.Ft void +.Ft void .Fn endrpcent void .Sh DESCRIPTION +The .Fn getrpcent , .Fn getrpcbyname , and -.Fn getrpcbynumber , +.Fn getrpcbynumber +functions each return a pointer to an object with the following structure containing the broken-out fields of a line in the rpc program number data base, .Pa /etc/rpc : -.Bd -literal -offset indent +.Bd -literal struct rpcent { char *r_name; /* name of server for this rpc program */ char **r_aliases; /* alias list */ @@ -43,51 +48,65 @@ struct rpcent { .Pp The members of this structure are: .Bl -tag -width r_aliases -offset indent -.It r_name +.It Va r_name The name of the server for this rpc program. -.It r_aliases +.It Va r_aliases A zero terminated list of alternate names for the rpc program. -.It r_number +.It Va r_number The rpc program number for this service. .El .Pp +The .Fn getrpcent +function reads the next line of the file, opening the file if necessary. .Pp +The .Fn setrpcent -opens and rewinds the file. If the +function +opens and rewinds the file. +If the .Fa stayopen flag is non-zero, the net data base will not be closed after each call to -.Fn getrpcent +.Fn getrpcent (either directly, or indirectly through one of -the other +the other .Dq getrpc calls). .Pp +The .Fn endrpcent +function closes the file. .Pp +The .Fn getrpcbyname and .Fn getrpcbynumber +functions sequentially search from the beginning of the file until a matching rpc program name or program number is found, or until end-of-file is encountered. .Sh FILES -.Pa /etc/rpc -.Sh SEE ALSO -.Xr rpc 5 , -.Xr rpcinfo 8 , -.Xr ypserv 8 +.Bl -tag -width /etc/rpc -compact +.It Pa /etc/rpc +.El .Sh DIAGNOSTICS A .Dv NULL -pointer is returned on +pointer is returned on .Dv EOF or error. +.Sh SEE ALSO +.Xr rpc 5 , +.Xr rpcinfo 8 , +.Xr ypserv 8 .Sh BUGS -All information -is contained in a static area -so it must be copied if it is -to be saved. +.\"All information +.\"is contained in a static area +.\"so it must be copied if it is +.\"to be saved. +The data space used by +these functions is thread-specific; if future use requires the data, it should be +copied before any subsequent calls to these functions overwrite it. diff --git a/rpc.subproj/getrpcent.c b/rpc.subproj/getrpcent.c index 6e53c28..3bee95b 100644 --- a/rpc.subproj/getrpcent.c +++ b/rpc.subproj/getrpcent.c @@ -66,6 +66,11 @@ static char *rcsid = "$Id: getrpcent.c,v 1.3 2002/02/19 20:36:23 epeyton Exp $"; #include #include +/* forward */ +void _old_setrpcent(int f); +struct rpcent *_old_getrpcent(); +void _old_endrpcent(); + /* * Internet version. */ @@ -97,7 +102,7 @@ _rpcdata() } struct rpcent * -getrpcbynumber(number) +_old_getrpcbynumber(number) #ifdef __LP64__ int32_t number; #else @@ -114,8 +119,8 @@ getrpcbynumber(number) if (d == 0) return (0); - setrpcent(0); - while ((p = getrpcent())) + _old_setrpcent(0); + while ((p = _old_getrpcent())) { #ifdef __LP64__ if (p->r_number == x) break; @@ -123,12 +128,12 @@ getrpcbynumber(number) if (p->r_number == number) break; #endif } - endrpcent(); + _old_endrpcent(); return (p); } struct rpcent * -getrpcbyname(name) +_old_getrpcbyname(name) #if defined(__APPLE__) const char *name; #else @@ -138,8 +143,8 @@ getrpcbyname(name) struct rpcent *rpc; char **rp; - setrpcent(0); - while ((rpc = getrpcent())) { + _old_setrpcent(0); + while ((rpc = _old_getrpcent())) { if (strcmp(rpc->r_name, name) == 0) return (rpc); for (rp = rpc->r_aliases; *rp != NULL; rp++) { @@ -147,12 +152,12 @@ getrpcbyname(name) return (rpc); } } - endrpcent(); + _old_endrpcent(); return (NULL); } void -setrpcent(f) +_old_setrpcent(f) int f; { register struct rpcdata *d = _rpcdata(); @@ -167,7 +172,7 @@ setrpcent(f) } void -endrpcent() +_old_endrpcent() { register struct rpcdata *d = _rpcdata(); @@ -180,7 +185,7 @@ endrpcent() } struct rpcent * -getrpcent() +_old_getrpcent() { register struct rpcdata *d = _rpcdata(); @@ -208,14 +213,14 @@ interpret(val, len) p = d->line; d->line[len] = '\n'; if (*p == '#') - return (getrpcent()); + return (_old_getrpcent()); cp = strpbrk(p, "#\n"); if (cp == NULL) - return (getrpcent()); + return (_old_getrpcent()); *cp = '\0'; cp = strpbrk(p, " \t"); if (cp == NULL) - return (getrpcent()); + return (_old_getrpcent()); *cp++ = '\0'; /* THIS STUFF IS INTERNET SPECIFIC */ d->rpc.r_name = d->line; diff --git a/rpc.subproj/getrpcport.3 b/rpc.subproj/getrpcport.3 index 16ab68c..5cf79fa 100644 --- a/rpc.subproj/getrpcport.3 +++ b/rpc.subproj/getrpcport.3 @@ -1,5 +1,5 @@ -.\" from: @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI -.\" $Id: getrpcport.3,v 1.1 1999/04/13 23:15:37 wsanchez Exp $ +.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI +.\" $FreeBSD: src/lib/libc/rpc/getrpcport.3,v 1.9 2004/07/02 23:52:12 ru Exp $ .\" .Dd October 6, 1987 .Dt GETRPCPORT 3 @@ -7,12 +7,16 @@ .Sh NAME .Nm getrpcport .Nd get RPC port number +.Sh LIBRARY +.Lb libc .Sh SYNOPSIS -.Fd #include +.In rpc/rpc.h .Ft int .Fn getrpcport "char *host" "int prognum" "int versnum" "int proto" .Sh DESCRIPTION +The .Fn getrpcport +function returns the port number for version .Fa versnum of the RPC program @@ -23,7 +27,8 @@ and using protocol .Fa proto . It returns 0 if it cannot contact the portmapper, or if .Fa prognum -is not registered. If +is not registered. +If .Fa prognum is registered but not with version .Fa versnum , diff --git a/rpc.subproj/pmap_getport.c b/rpc.subproj/pmap_getport.c index 2a09492..44a87ef 100644 --- a/rpc.subproj/pmap_getport.c +++ b/rpc.subproj/pmap_getport.c @@ -71,7 +71,6 @@ static char *rcsid = "$Id: pmap_getport.c,v 1.4 2004/12/19 22:45:44 zarzycki Exp #include static struct timeval default_timeout = { 5, 0 }; -static struct timeval default_tottimeout = { 60, 0 }; /* * Find the mapped port for program,version. diff --git a/rpc.subproj/svc.h b/rpc.subproj/svc.h index ca1270d..d671045 100644 --- a/rpc.subproj/svc.h +++ b/rpc.subproj/svc.h @@ -350,4 +350,11 @@ __BEGIN_DECLS extern SVCXPRT *svctcp_create __P((int, unsigned int, unsigned int)); __END_DECLS +/* + * Any open file descriptor based rpc. + */ +__BEGIN_DECLS +extern SVCXPRT *svcfd_create __P((int, u_int, u_int)); +__END_DECLS + #endif /* !_RPC_SVC_H */ diff --git a/rpc.subproj/xdr.3 b/rpc.subproj/xdr.3 index 029eb4f..852ccae 100644 --- a/rpc.subproj/xdr.3 +++ b/rpc.subproj/xdr.3 @@ -1,5 +1,5 @@ .\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI -.\" $FreeBSD: src/lib/libc/xdr/xdr.3,v 1.16 2002/12/19 09:40:28 ru Exp $ +.\" $FreeBSD: src/lib/libc/xdr/xdr.3,v 1.17 2005/11/24 07:12:01 ru Exp $ .\" .Dd February 16, 1988 .Dt XDR 3 @@ -211,7 +211,7 @@ This routine returns one if it succeeds, zero otherwise. .Ft void .Xc .It Xo -.Fn xdr_free "xdrproc_t proc" "char *objp" +.Fn xdr_free "xdrproc_t proc" "void *objp" .Xc .Pp Generic freeing routine. @@ -397,7 +397,7 @@ linked lists. .Fa "XDR *xdrs" .Fa "u_int sendsize" .Fa "u_int recvsize" -.Fa "char *handle" +.Fa "void *handle" .Fa "int \*(lp*readit\*(rp\*(lp\*(rp" .Fa "int \*(lp*writeit\*(rp\*(lp\*(rp" .Fc diff --git a/rpc.subproj/xdr.c b/rpc.subproj/xdr.c index 3cf13bb..2b167ea 100644 --- a/rpc.subproj/xdr.c +++ b/rpc.subproj/xdr.c @@ -526,7 +526,7 @@ xdr_opaque(xdrs, cp, cnt) u_int cnt; { u_int32_t rndup; - static int crud[BYTES_PER_XDR_UNIT]; + u_int8_t crud[BYTES_PER_XDR_UNIT]; /* * if no data we are done diff --git a/util.subproj/Makefile b/util.subproj/Makefile index fed6205..ee01d36 100644 --- a/util.subproj/Makefile +++ b/util.subproj/Makefile @@ -1,46 +1,23 @@ -# -# Generated by the NeXT 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 = util - -PROJECTVERSION = 2.8 -PROJECT_TYPE = Component - -CFILES = hton.c putpwpasswd.c pwcache.c rcmd.c\ - rcmdsh.c - -OTHERSRCS = Makefile Makefile.preamble Makefile.postamble rcmd.3 hosts.equiv.5 - - -MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles -CODE_GEN_STYLE = DYNAMIC -MAKEFILE = subproj.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 +Project = util +ProductType = staticlib +Install_Dir = /scratch +BuildDebug = YES +BuildProfile = YES + +CFILES = hton.c putpwpasswd.c rcmd.c rcmdsh.c +MANPAGES = rcmd.3 hosts.equiv.5 + +Extra_CC_Flags = -Wall -fno-common -I. \ + -I../dns.subproj -I../gen.subproj -I../lookup.subproj \ + -D__DARWIN_NON_CANCELABLE=1 -DINET6=1 + +include $(MAKEFILEPATH)/CoreOS/ReleaseControl/BSDCommon.make + +after_install: + @for LINK in iruserok.3 iruserok_sa.3 rcmd_af.3 rresvport.3 \ + rresvport_af.3 ruserok.3 ; do \ + $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" \ + "$(DSTROOT)/usr/share/man/man3/$${LINK}" ; \ + done + $(LN) -f "$(DSTROOT)/usr/share/man/man5//hosts.equiv.5" \ + "$(DSTROOT)/usr/share/man/man5/.rhosts.5" diff --git a/util.subproj/Makefile.postamble b/util.subproj/Makefile.postamble deleted file mode 100644 index d1c33e5..0000000 --- a/util.subproj/Makefile.postamble +++ /dev/null @@ -1,122 +0,0 @@ -############################################################################### -# NeXT Makefile.postamble Template -# Copyright 1993, NeXT Computer, Inc. -# -# This Makefile is used for configuring the standard app makefiles associated -# with ProjectBuilder. -# -# Use this template to set attributes for a project, sub-project, bundle, or -# palette. Each node in the project's tree of sub-projects and bundles -# should have it's own Makefile.preamble and Makefile.postamble. Additional -# rules (e.g., after_install) that are defined by the developer should be -# defined in this file. -# -############################################################################### -# -# Here are the variables exported by the common "app" makefiles that can be -# used in any customizations you make to the template below: -# -# PRODUCT_ROOT - Name of the directory to which resources are copied. -# OFILE_DIR - Directory into which .o object files are generated. -# (Note that this name is calculated based on the target -# architectures specified in Project Builder). -# DERIVED_SRC_DIR - Directory used for all other derived files -# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations -# -# NAME - name of application, bundle, subproject, palette, etc. -# LANGUAGE - langage in which the project is written (default "English") -# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" -# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" -# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project -# GLOBAL_RESOURCES - non-localized resources of project -# PROJECTVERSION - version of ProjectBuilder that output Makefile -# APPICON - application icon file -# DOCICONS - dock icon files -# ICONSECTIONS - Specifies icon sections when linking executable -# -# CLASSES - Class implementation files in project. -# HFILES - Header files in project. -# MFILES - Other Objective-C source files in project. -# CFILES - Other C source files in project. -# PSWFILES - .psw files in the project -# PSWMFILES - .pswm files in the project -# SUBPROJECTS - Subprojects of this project -# BUNDLES - Bundle subprojects of this project -# OTHERSRCS - Other miscellaneous sources of this project -# OTHERLINKED - Source files not matching a standard source extention -# -# LIBS - Libraries to link with when making app target -# DEBUG_LIBS - Libraries to link with when making debug target -# PROF_LIBS - Libraries to link with when making profile target -# OTHERLINKEDOFILES - Other relocatable files to (always) link in. -# -# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles -# MAKEFILEDIR - Directory in which to find $(MAKEFILE) -# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) -# INSTALLDIR - Directory app will be installed into by 'install' target -# -############################################################################### - - -# Change defaults assumed by the standard makefiles here. Edit the -# following default values as appropriate. (Note that if no Makefile.postamble -# exists, these values will have defaults set in common.make). - -# Versioning of frameworks, libraries, bundles, and palettes: -#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary -#DEPLOY_WITH_VERSION_NAME = A -#COMPATIBILITY_PROJECT_VERSION = 1 - -# Some compiler flags can be easily overridden here, but onlytake effect at -# the top-level: -#OPTIMIZATION_CFLAG = -O -#DEBUG_SYMBOLS_CFLAG = -g -#WARNING_CFLAGS = -Wall -#DEBUG_BUILD_CFLAGS = -DDEBUG -#PROFILE_BUILD_CFLAGS = -pg -DPROFILE - -# Flags passed to yacc -#YFLAGS = -d - -# Library and Framework projects only: -# 1. If you want something other than the default .dylib name, override it here -#DYLIB_INSTALL_NAME = lib$(NAME).dylib - -# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. -#DYLIB_INSTALL_DIR = $(INSTALLDIR) - -# 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 for various project types. Note: -S strips debugging symbols -# (executables can be stripped down further with -x or, if they load no bundles, with no -# options at all). -#APP_STRIP_OPTS = -S -#TOOL_STRIP_OPTS = -S -#LIBRARY_STRIP_OPTS = -S # for .a archives -#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries - -######################################################################### -# Put rules to extend the behavior of the standard Makefiles here. "Official" -# user-defined rules are: -# * before_install -# * after_install -# * after_installhdrs -# 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. -# -install-man-page: - mkdir -p "$(DSTROOT)/usr/share/man/man3" - install -c -m 644 rcmd.3 "$(DSTROOT)/usr/share/man/man3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/iruserok.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/iruserok_sa.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/rcmd_af.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/rresvport.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/rresvport_af.3" - $(LN) -f "$(DSTROOT)/usr/share/man/man3/rcmd.3" "$(DSTROOT)/usr/share/man/man3/ruserok.3" - mkdir -p "$(DSTROOT)/usr/share/man/man5" - install -c -m 644 hosts.equiv.5 "$(DSTROOT)/usr/share/man/man5" - $(LN) -f "$(DSTROOT)/usr/share/man/man5//hosts.equiv.5" "$(DSTROOT)/usr/share/man/man5/.rhosts.5" diff --git a/util.subproj/Makefile.preamble b/util.subproj/Makefile.preamble deleted file mode 100644 index 1d8f0c6..0000000 --- a/util.subproj/Makefile.preamble +++ /dev/null @@ -1,8 +0,0 @@ -AFTER_POSTINSTALL += install-man-page -OTHER_CFLAGS = \ - -D__DARWIN_NON_CANCELABLE=1 \ - -DINET6=1 - -# for building 64-bit -# Libinfo need to build with gcc-3.5 and 3-way fat -NEXTSTEP_OBJCPLUS_COMPILER = $(CCOMPILER) diff --git a/util.subproj/PB.project b/util.subproj/PB.project deleted file mode 100644 index af7392b..0000000 --- a/util.subproj/PB.project +++ /dev/null @@ -1,21 +0,0 @@ -{ - DYNAMIC_CODE_GEN = YES; - FILESTABLE = { - OTHER_LINKED = (hton.c, putpwpasswd.c, pwcache.c, rcmd.c, rcmdsh.c); - OTHER_SOURCES = (Makefile, Makefile.preamble, Makefile.postamble, rcmd.3, hosts.equiv.5); - }; - LANGUAGE = English; - MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; - NEXTSTEP_BUILDTOOL = /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 = util; - PROJECTTYPE = Component; - PROJECTVERSION = 2.8; - WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; - WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; - WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; -} diff --git a/util.subproj/hton.c b/util.subproj/hton.c index 312d514..b40320f 100644 --- a/util.subproj/hton.c +++ b/util.subproj/hton.c @@ -1,52 +1,46 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2008 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. * * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ -/* Copyright (c) 1994 NeXT Computer, Inc. All rights reserved. - * - * File: hton.c - * Author: Matt Watson, NeXT Computer, Inc. - * - * Use the machine independent byte-swapping code for htonl-type functions. - * - * HISTORY - * 15-Dec-94 Matt Watson (Matt_Watson@NeXT.COM) - * Created. - */ +/* Copyright (c) 1994 NeXT Computer, Inc. All rights reserved. */ -#import +#import +#import -long ntohl(long x) { - return NXSwapBigLongToHost(x); +uint32_t ntohl(uint32_t x) +{ + return OSSwapBigToHostInt32(x); } -short ntohs(short x) { - return NXSwapBigShortToHost(x); +uint32_t htonl(uint32_t x) +{ + return OSSwapHostToBigInt32(x); } -long htonl(long x) { - return NXSwapHostLongToBig(x); +uint16_t ntohs(uint16_t x) +{ + return OSSwapBigToHostInt16(x); } -short htons(short x) { - return NXSwapHostShortToBig(x); +uint16_t htons(uint16_t x) +{ + return OSSwapHostToBigInt16(x); } diff --git a/util.subproj/pwcache.c b/util.subproj/pwcache.c deleted file mode 100644 index ce31e7a..0000000 --- a/util.subproj/pwcache.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved - * - * Copyright (c) 1980, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * @(#)fstab.c 8.1 (Berkeley) 6/4/93 - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#define NCACHE 64 /* power of 2 */ -#define MASK (NCACHE - 1) /* bits to store with */ - -char * -user_from_uid(uid, nouser) - uid_t uid; - int nouser; -{ - static struct ncache { - uid_t uid; - char name[_UTX_USERSIZE + 1]; - } *c_uid[NCACHE]; - static int pwopen; - static char nbuf[15]; /* 32 bits == 10 digits */ - register struct passwd *pw; - register struct ncache **cp; - - cp = &c_uid[uid & MASK]; - if (*cp == NULL || (*cp)->uid != uid || !*(*cp)->name) { - if (pwopen == 0) { - setpassent(1); - pwopen = 1; - } - if ((pw = getpwuid(uid)) == NULL) { -err: - if (nouser) - return (NULL); - (void)snprintf(nbuf, sizeof(nbuf), "%u", uid); - return (nbuf); - } - if (*cp == NULL) { - *cp = malloc(sizeof(struct ncache)); - if (*cp == NULL) - goto err; - } - (*cp)->uid = uid; - (void)strncpy((*cp)->name, pw->pw_name, _UTX_USERSIZE); - (*cp)->name[_UTX_USERSIZE] = '\0'; - } - return ((*cp)->name); -} - -char * -group_from_gid(gid, nogroup) - gid_t gid; - int nogroup; -{ - static struct ncache { - gid_t gid; - char name[_UTX_USERSIZE + 1]; - } *c_gid[NCACHE]; - static int gropen; - static char nbuf[15]; /* 32 bits == 10 digits */ - struct group *gr; - struct ncache **cp = NULL; - - cp = &c_gid[gid & MASK]; - if (*cp == NULL || (*cp)->gid != gid || !*(*cp)->name) { - if (gropen == 0) { - setgroupent(1); - gropen = 1; - } - if ((gr = getgrgid(gid)) == NULL) { -err: - if (nogroup) - return (NULL); - (void)snprintf(nbuf, sizeof(nbuf), "%u", gid); - return (nbuf); - } - if (*cp == NULL) { - *cp = malloc(sizeof(struct ncache)); - if (*cp == NULL) - goto err; - } - (*cp)->gid = gid; - (void)strncpy((*cp)->name, gr->gr_name, _UTX_USERSIZE); - (*cp)->name[_UTX_USERSIZE] = '\0'; - } - return ((*cp)->name); -} diff --git a/util.subproj/rcmd.c b/util.subproj/rcmd.c index 02c497b..b11476f 100644 --- a/util.subproj/rcmd.c +++ b/util.subproj/rcmd.c @@ -83,7 +83,8 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; #include #include #endif -#include + +#include "nameser8_compat.h" /* wrapper for KAME-special getnameinfo() */ #ifndef NI_WITHSCOPEID -- 2.45.2